/**
 * Profile Editor + Public Profile — On-brand styling
 * Matches existing site: white backgrounds, navy #031B83 headings, gold #CC9900 accents.
 * Scoped under .profile-editor-wrapper / .profile-public-wrapper to avoid Seeko conflicts.
 * Uses native CSS Grid — no third-party library.
 */

/* ============================================================
   Layout & Toolbar (editor only)
   ============================================================ */

/* Break editor out of Seeko's nested .container and sidebar-single constraints */
body.profile-editor-active .bp-member-layout > .container {
    max-width: none;
}
body.profile-editor-active .row.sidebar-single > .col-header {
    display: none !important;
}
body.profile-editor-active .row.sidebar-single > .col-main {
    grid-column: 1 / -1 !important;
}
/* Constrain the cover image header to match dashboard/profile width */
body.profile-editor-active #item-header {
    max-width: 1080px;
    margin: 0 auto;
    padding: 0 15px;
    box-sizing: border-box;
}
@media (min-width: 1440px) {
    body.profile-editor-active #item-header {
        max-width: 1440px;
    }
}
body.profile-editor-active #item-body > .container {
    max-width: none;
    padding: 0;
}
body.profile-editor-active #item-body > .container > .row > .col-12 {
    padding: 0;
}
body.profile-editor-active #item-body > .container > .row > .col-12 > .col-inner {
    padding: 0;
}

/* Profile + dashboard: constrain Seeko container on all own-profile pages
   EXCEPT the editor page which needs max-width: none (set above).
   overflow: hidden clips Bootstrap's negative row margins that would otherwise
   push inner content wider than the container. */
body.profile-public-active .bp-member-layout > .container,
body.profile-dashboard-active:not(.profile-editor-active) .bp-member-layout > .container {
    max-width: 1080px;
    margin: 0 auto;
    padding: 0 15px;
    box-sizing: border-box;
    overflow: hidden;
}
@media (min-width: 1440px) {
    body.profile-public-active .bp-member-layout > .container,
    body.profile-dashboard-active:not(.profile-editor-active) .bp-member-layout > .container {
        max-width: 1440px;
    }
}

.profile-editor-wrapper {
    max-width: 1080px;
    margin: 0 auto;
    padding: 8px 0;
    box-sizing: border-box;
}

/* Widescreen editor */
@media (min-width: 1440px) {
    .profile-editor-wrapper {
        max-width: 1440px;
    }
}

.editor-toolbar {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 20px;   /* S213 08/09/26, Rob: "after removing the original single sentence that was
                              under this gold menu on the customise page, it has now squashed it so that the
                              saved notifications are overlapping the border below." The status line is
                              ABSOLUTELY positioned under the Save button, so it takes no space and hangs
                              13px past the toolbar; with only 8px of margin it sat 1px INTO the device
                              selector below - measured. 20px clears it with 7px to spare. */
    flex-wrap: nowrap;
    gap: 14px;
    padding: 0;
    line-height: 1 !important;
    font-size: 0 !important;
}

.editor-title {
    font-family: 'Montserrat', sans-serif;
    color: #031B83;
    font-size: 20px !important;
    font-weight: 700;
    margin: 0;
    /* S77 Rob: asymmetric padding to bump glyphs up 1px \u2014 matches toolbar
       button text treatment (Montserrat bold caps sit high in em-box). */
    padding: 8px 0 10px 0;
    white-space: nowrap;
    line-height: 1 !important;
}

/* S200 01/09/26, Rob: "shift the gold top menu into the center, and make it the same width as
   the menu below it for choosing platform size." The heading beside it is gone, so the row
   centres on its own; the WIDTH is matched to the preview-size bar by syncToolbarWidth() in
   profile-grid.js, because that bar is content-sized and only the browser knows how wide it
   ends up. space-between spreads the buttons across the matched width rather than bunching
   them at one end. */
.editor-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-wrap: nowrap;
    margin: 0 auto;
    line-height: 1 !important;
    font-size: 0 !important;
}

/* Override Seeko theme-static.min.css which adds margin-bottom: 18px to all buttons */
.editor-actions button {
    margin: 0 !important;
}

.editor-hint {
    color: #031B83;
    font-size: 13px;
    margin: 0 0 12px 0;
    text-align: center;
    font-weight: 500;
}

/* S77 Rob item 7: device selector — content centred as a row. Equal
   vertical padding + align-items:center + consistent child heights means
   label and buttons share the same baseline. Label nav-blue, not grey. */
.device-selector {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    /* S200: 12px, matching the rail below it and the workspace below that. */
    margin: 12px auto 0 auto !important;
    width: fit-content !important;
    max-width: 100%;
    padding: 8px 16px;
    background: #f5f5f5;
    border: 2px solid #CC9900;
    border-radius: 10px;
}
.device-selector > * {
    align-self: center;
}
.device-selector-label {
    font-family: 'Montserrat', sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: #031B83;
    margin-right: 4px;
    display: inline-flex;
    align-items: center;
    line-height: 1;
    height: 36px;
}
/* S77 Rob item 7: preview-size buttons — white bg default (not cream, not
   grey), gold border, navy text. Hover flips to gold bg + navy text (D055).
   Active/pressed state stays navy bg + gold text. Explicit :focus rule
   prevents browser default grey-focus. min-height fixes vertical centring
   within the .device-selector frame (buttons + label row-align flush). */
.device-btn {
    /* B21 (S85 04/05/26): explicit margin: 0 to override Seeko parent
       theme's `seeko-dynamic.css` rule that sets `margin-bottom: 1rem` on
       all `button` elements. With that 18px invisible bottom margin, flex's
       align-items: center treated the button as 58px tall (40 box + 18
       margin), centring the OUTER margin-box and leaving the visible button
       outline 9px above the row's true midline. Reset gives proper centring
       and natural text-to-text baseline alignment with the .device-selector-
       label without transform hacks. Supersedes S85-006 + S85-007. */
    margin: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    min-height: 36px;
    border: 2px solid #CC9900;
    border-radius: 8px;
    background: #ffffff;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: 'Montserrat', sans-serif;
    font-size: 12px;
    font-weight: 700;
    color: #031B83;
    outline: none;
}
.device-btn .dashicons {
    font-size: 20px;
    width: 20px;
    height: 20px;
    line-height: 20px;
    color: #031B83;
    transition: color 0.2s;
}
.device-btn:hover {
    border-color: #CC9900;
    color: #031B83;
    background: #CC9900;
}
.device-btn:hover .dashicons {
    color: #031B83;
}
.device-btn:focus,
.device-btn:focus-visible {
    outline: none;
    background: #ffffff;
    border-color: #CC9900;
    color: #031B83;
    box-shadow: 0 0 0 2px rgba(204, 153, 0, 0.25);
}
.device-btn:focus .dashicons,
.device-btn:focus-visible .dashicons {
    color: #031B83;
}
.device-btn:active {
    background: #031B83 !important;
    border-color: #CC9900 !important;
    color: #CC9900 !important;
}
.device-btn:active .dashicons {
    color: #CC9900 !important;
}
/* S77 Rob item 7 pt2: aggressive override — Seeko / autofill / button-reset
   rules were winning at equal specificity on the active state. Bump to
   `.device-selector .device-btn.active` + !important. */
.device-selector .device-btn.active,
.device-btn.active {
    border-color: #CC9900 !important;
    background: #031B83 !important;
    color: #CC9900 !important;
    box-shadow: 0 2px 6px rgba(3, 27, 131, 0.25) !important;
}
.device-selector .device-btn.active .dashicons,
.device-btn.active .dashicons {
    color: #CC9900 !important;
}
/* Label vertical-align: inline-flex + line-height:1 lets align-items:center
   on .device-selector do its job precisely. */
.device-selector-label {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    line-height: 1;
}
.device-label {
    line-height: 1;
}

/* Device preview: constrain wrapper width + centre with visual frame.
   S67 F23 fix: widths aligned to canonical site breakpoints (1920/1280/768/360).
   Previous values (1200/820/390) did not match real-world viewer widths so the
   preview did not show what the member's profile would actually look like to
   visitors at each breakpoint. Only the editor-content (widget grid) shrinks —
   toolbar and device selector stay full width. */
.profile-editor-wrapper.device-desktop .editor-content {
    max-width: 1280px;
    margin: 0 auto;
}
.profile-editor-wrapper.device-tablet .editor-content {
    max-width: 768px;
    margin: 0 auto;
}
.profile-editor-wrapper.device-mobile .editor-content {
    max-width: 360px;
    margin: 0 auto;
}
/* Subtle border to show the "device frame" when previewing smaller sizes */
.profile-editor-wrapper.device-desktop .editor-content,
.profile-editor-wrapper.device-tablet .editor-content,
.profile-editor-wrapper.device-mobile .editor-content {
    border-left: 2px solid #e8e8e8;
    border-right: 2px solid #e8e8e8;
    padding-left: 10px;
    padding-right: 10px;
    border-radius: 12px;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.04);
}

/* ============================================================
   Save / Reset / Glass / Colors Buttons
   ============================================================ */

/* ---- Soft layered shadow buttons (Material-inspired) ---- */

.btn-save {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-save:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
}

.btn-save:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}

.btn-save.unsaved {
    animation: pulse-gold 1.5s ease infinite;
}

/* S199 31/08/26, Rob (raised twice): "when a new design is saving, the word saving still is
   light when it doesn't need to be."
   THE CAUSE WAS NOT THE COLOUR. `.status-saving` has been solid navy since S198 and computes
   as rgb(3,27,131) - but the status text was relocated INSIDE this button by the sigil-picker
   footer script (profile-system.php ~9817 appends `.save-btn-status-below` to #profile-save-btn
   so it hangs neatly beneath it), and saveLayout() disables the button while the save is in
   flight. `opacity` creates a group: everything inside faded to 60%, the status text with it,
   and a descendant cannot opt out of an ancestor's opacity. Measuring the computed colour
   said navy every time; only the painted pixels showed it washed out (LB-334).
   The disabled look is now painted with explicit muted values instead of group opacity, so
   the button still reads as unavailable and the status underneath keeps its own colour. */
.btn-save:disabled {
    /* Seeko's own `button:disabled` fades to opacity .65 - measured live on this button after
       the local 0.6 was removed - and opacity applies to the whole group, status text and all.
       Pinned to 1 so the muted look below is the ONLY thing that says "disabled". */
    opacity: 1 !important;
    background: linear-gradient(to bottom, #e8cf8a 0%, #d6bd7a 100%) !important;
    color: #5a6b9a !important;
    box-shadow: none !important;
    cursor: not-allowed;
    animation: none;
    transform: none !important;
}
/* The status hangs under the button but is not part of it - never inherit the muted fill. */
.btn-save:disabled .save-btn-status-below,
.btn-save:disabled .save-status {
    color: inherit;
}
.btn-save:disabled .save-status.status-saving { color: #031B83 !important; }
.btn-save:disabled .save-status.status-saved  { color: var(--color-success) !important; }
.btn-save:disabled .save-status.status-error  { color: #dc3545 !important; }
.btn-save:disabled .save-status.status-unsaved{ color: #CC9900 !important; }

@keyframes pulse-gold {
    0%, 100% { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(184, 134, 11, 0.2), 0 0 0 0 rgba(204, 153, 0, 0.4) !important; }
    50% { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(184, 134, 11, 0.2), 0 0 0 8px rgba(204, 153, 0, 0) !important; }
}

.btn-reset {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s, color 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-reset:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
}

.btn-reset:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}

/* Toolbar buttons — gold default, press inverts to blue bg + gold text */
/* Glass toggle */
.btn-glass {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s, color 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-glass:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
}

.btn-glass:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}

.btn-glass.active {
    background: linear-gradient(to bottom, #031B83 0%, #021466 100%) !important;
    color: #CC9900 !important;
    border: none !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(3, 27, 131, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-glass.active:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(3, 27, 131, 0.2) !important;
}

.btn-glass.active:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
}

/* Colours toggle */
.btn-colors {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s, color 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-colors:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
}

.btn-colors:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}

.btn-colors.active {
    background: linear-gradient(to bottom, #031B83 0%, #021466 100%) !important;
    color: #CC9900 !important;
    border: none !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(3, 27, 131, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-colors.active:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
}

/* Colour Picker toolbar button */
.btn-color-picker {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 14px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s, color 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.btn-color-picker .dashicons {
    font-size: 15px;
    width: 15px;
    height: 15px;
    line-height: 15px;
}
.btn-color-picker:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(184, 134, 11, 0.3) !important;
}
.btn-color-picker:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}
.btn-color-picker.active {
    background: linear-gradient(to bottom, #031B83 0%, #021466 100%) !important;
    color: #CC9900 !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(3, 27, 131, 0.2) !important;
}
.btn-color-picker.active:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
}

/* ===== Colour Picker Modal ===== */
.color-picker-modal {
    position: fixed;
    z-index: 100010;
    width: 280px;
    background: var(--color-surface, #FFFFFF);
    border: 2px solid var(--color-gold, #CC9900);
    border-radius: 12px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.08);
    font-family: 'Montserrat', sans-serif;
    user-select: none;
}
.cpm-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: linear-gradient(to right, #031B83, #0a2494);
    border-radius: 10px 10px 0 0;
    border-bottom: 2px solid var(--color-gold, #CC9900);
}
.cpm-title {
    color: var(--color-gold, #CC9900);
    font-weight: 700;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.cpm-title .dashicons {
    font-size: 16px;
    width: 16px;
    height: 16px;
}
.cpm-close {
    background: none;
    border: 1px solid rgba(204, 153, 0, 0.4);
    color: var(--color-gold, #CC9900);
    font-size: 18px;
    line-height: 1;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}
.cpm-close:hover {
    background: rgba(204, 153, 0, 0.15);
}
.cpm-body {
    padding: 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
/* Kill Seeko margin overrides on all cpm-body children */
.cpm-body > * {
    margin-bottom: 0 !important;
}
.cpm-spectrum-wrap {
    position: relative;
    width: calc(100% - 28px);
    height: 160px;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid rgba(0, 0, 0, 0.1);
    cursor: crosshair;
}
.cpm-spectrum {
    display: block;
    width: 100%;
    height: 160px;
}
.cpm-spectrum-cursor {
    position: absolute;
    width: 14px;
    height: 14px;
    border: 2px solid #fff;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.4), inset 0 0 0 1px rgba(0,0,0,0.3);
    pointer-events: none;
    transform: translate(-7px, -7px);
    top: 0;
    left: 220px;
}
.cpm-hue-wrap {
    position: relative;
    width: 20px;
    height: 160px;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid rgba(0, 0, 0, 0.1);
    cursor: pointer;
}
.cpm-hue {
    display: block;
    width: 20px;
    height: 160px;
}
.cpm-hue-cursor {
    position: absolute;
    left: -2px;
    width: 24px;
    height: 6px;
    border: 2px solid #fff;
    border-radius: 3px;
    box-shadow: 0 0 2px rgba(0,0,0,0.5);
    pointer-events: none;
    transform: translateY(-3px);
    top: 0;
}
.cpm-output {
    width: 100%;
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 2px;
    margin-bottom: 0;
}
.cpm-preview-swatch {
    width: 31px;
    height: 31px;
    border-radius: 5px;
    border: 2px solid rgba(0, 0, 0, 0.1);
    background: #CC9900;
    flex-shrink: 0;
}
.cpm-fields {
    flex: 1;
    min-width: 0;
}
.cpm-field-row {
    display: flex;
    align-items: center;
    gap: 4px;
}
.cpm-field-row label {
    color: var(--color-text-secondary, rgba(3,27,131,.75));   /* S199, Rob: no greys */
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    min-width: 28px;
}
.cpm-hex {
    flex: 1;
    min-width: 0;
    padding: 6px 8px !important;
    margin: 0 !important;
    font-size: 13px !important;
    font-family: 'Montserrat', monospace !important;
    font-weight: 600;
    background: #f8f9fa !important;
    border: 1px solid rgba(0, 0, 0, 0.12) !important;
    border-radius: 5px;
    color: #1a1a2e;
    text-transform: uppercase;
    height: auto !important;
    line-height: 1.3 !important;
}
.cpm-hex:focus {
    outline: none;
    border-color: var(--color-gold, #CC9900);
    box-shadow: 0 0 0 2px rgba(204, 153, 0, 0.2);
}
.cpm-copy {
    background: rgba(204, 153, 0, 0.1);
    border: 1px solid rgba(204, 153, 0, 0.3) !important;
    color: #b8860b;
    border-radius: 5px;
    padding: 5px 7px !important;
    margin: 0 !important;
    cursor: pointer;
    display: flex;
    align-items: center;
    flex-shrink: 0;
    transition: background 0.15s;
}
.cpm-copy .dashicons {
    font-size: 14px;
    width: 14px;
    height: 14px;
}
.cpm-copy:hover {
    background: rgba(204, 153, 0, 0.2);
}
.cpm-copy.copied {
    background: rgba(0, 180, 0, 0.1);
    border-color: rgba(0, 180, 0, 0.3);
    color: #4caf50;
}

/* View Profile button in toolbar */
.btn-view-profile {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s, color 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-view-profile:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    color: #031B83 !important;
    text-decoration: none;
}

.btn-view-profile:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}

/* .btn-dashboard rule retired S100 (26/05/26) — class name now owned by the
   universal button system (page-polish.css §43.2). The original use was an
   orphaned gold-gradient toolbar button class with no remaining HTML emit
   point. Recoverable from git if a legitimate toolbar button needs restyling. */

/* S77 Rob: toolbar button text rendering 1px low \u2014 Montserrat bold caps
   sit high in the em-box so vertical centring looks wrong. Asymmetric
   padding (-1px top, +1px bottom) pushes the glyph baseline up without
   changing overall button height or the shadow/transform layering. /da
   rule 23a. */
.btn-save,
.btn-reset,
.btn-glass,
.btn-glass.active,
.btn-colors,
.btn-colors.active,
.btn-color-picker,
.btn-add-photo {
    padding-top: 8px !important;
    padding-bottom: 10px !important;
}

/* Add Photo Panel button */
.btn-add-photo {
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%) !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 13px !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: box-shadow 0.15s, transform 0.15s, background 0.15s, color 0.15s !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
    transform: translateY(-1px) !important;
}

.btn-add-photo:hover {
    transform: translateY(-1px) !important;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(184, 134, 11, 0.2) !important;
}

.btn-add-photo:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2) !important;
    background: #031B83 !important;
    color: #CC9900 !important;
}

/* ============================================================
   Background Picker (glass mode)
   ============================================================ */

.bg-picker {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex-wrap: nowrap;
    /* S76-006 Rob: shrink to content + horizontally centred, not full width. */
    /* S200 01/09/26, Rob: "all the menus are equidistant and vertically stacked". The stack is
       Preview size, Background, the widget rail, then the workspace. One 12px pitch for all of
       them - the bottom margin here is 0 because the rail below carries its own 12px top. */
    margin: 12px auto 0 auto !important;
    width: fit-content !important;
    max-width: 100%;
    padding: 10px 18px;
    /* Match sidenav grey. */
    background: #f5f5f5;
    border-radius: 10px;
    border: 2px solid #CC9900;
    line-height: 1 !important;
    font-size: 0 !important;
}

.bg-picker-label {
    font-size: 11px !important;
    font-weight: 600;
    color: #031B83 !important;
    font-family: 'Montserrat', sans-serif;
    line-height: 1 !important;
    padding: 6px 0;
    border: 1px solid transparent;
}

/* S200 01/09/26, Rob: "if none is selected for background, it's blue. Shouldn't be blue.
   Whichever one of those is selected should be the darker cream. Just like any of the other
   buttons. It's light cream until selected, then it's darker cream."
   NO NEW COLOURS MINTED: this is the documented brand pair, --color-cream #FFFBE6 at rest and
   --color-cream-hover #FFF5CC when chosen, which is exactly what .btn-option--cta and
   .btn-dashboard already use (BRAND_GUIDE D-084 / LB-023). The chips were white at rest and
   navy when chosen. */
.bg-chip {
    font-size: 11px !important;
    font-weight: 500;
    padding: 4px 12px;
    border-radius: 16px;
    border: 1px solid #CC9900;
    background: var(--color-cream, #FFFBE6);
    color: #031B83;
    cursor: pointer;
    font-family: 'Montserrat', sans-serif;
    transition: all 0.2s ease;
    line-height: 1 !important;
    margin: 0 !important;
}

.bg-chip:hover {
    border-color: #CC9900;
    background: #CC9900;
    color: #031B83;
}

.bg-picker .bg-chip.active,
.bg-chip.active {
    background: var(--color-gold-dark, #80641D) !important;
    color: #031B83 !important;
    border-color: #CC9900 !important;
}
/* S200: the My Photos special case is RETIRED. It existed only to keep that one chip out of the
   navy selected state; with the whole row now cream-to-darker-cream there is no navy left to
   avoid, and Rob's rule is that every chip in the row behaves the same way. */
/* S76 Rob: remove stuck focus/hover grey after modal closes. */
.bg-chip:focus,
.bg-chip:focus-visible {
    outline: none;
}
.bg-chip:not(.active):focus {
    background: var(--color-cream, #FFFBE6);
    color: #031B83;
    border-color: #CC9900;
}

/* ============================================================
   Status Indicators
   ============================================================ */

.save-status-row {
    text-align: center;
    min-height: 16px;
    margin-bottom: 2px;
}

.save-status {
    font-size: 11px;
    font-weight: 600;
    /* S199 31/08/26, Rob: "The 'unsaved changes' changing color slightly right at the beginning
       when it first appears ... It looks like it's blue to begin with and then suddenly loads
       as gold."
       NOTHING WAS STACKED - he asked me to check and the four status colours are each declared
       once. It was THIS transition: the label changes its text and its class in the same frame,
       so the browser eased from the colour it was already showing to the new one over 200ms.
       Going from the navy of `Saving...` (or the button's own navy while the label is empty) to
       the gold of `Unsaved changes` smears through blue on the way. A status label should snap. */
    white-space: nowrap;
}

.status-unsaved { color: #CC9900; }
.status-saving  { color: #031B83; }   /* S198, Rob: was #666 */
.status-saved   { color: var(--color-success); }
.status-error   { color: #dc3545; }

/* ============================================================
   Editor Content — Grid + Sidebar flex container
   ============================================================ */

.editor-content {
    display: flex;
    gap: 12px;
    align-items: flex-start;
}

/* ============================================================
   CSS Grid Container
   ============================================================ */

/* S77 Rob: workspace border \u2014 the grid where widgets drop needs a visible
   gold frame on the customise page so the user sees where the workspace
   ends. Hidden on public profile view where the grid chrome is irrelevant. */
.profile-editor-wrapper .profile-grid {
    border: 2px solid #CC9900;
    border-radius: 12px;
    padding: 12px;
}
.profile-public-wrapper .profile-grid,
body.bp-user .profile-grid-public {
    border: 0 !important;
    padding: 0 !important;
}

.profile-grid {
    display: grid;
    /* S185 Rob: 12 -> 24 columns, so a widget can be positioned on half-column
       offsets and sit under a differently-sized one. Saved x/w are doubled by the
       layout-version migration in profile-system.php §0.3, and every widget-type
       default was doubled with it, so existing layouts render at the same width
       (a former w6 spans 674px against 662px before). Serves the public grid too:
       .profile-grid-public also carries this class. */
    grid-template-columns: repeat(48, 1fr); /* S200: 48 columns - see UKS_PROFILE_GRID_COLS in profile-system.php */
    grid-auto-rows: 10px;
    gap: 10px;
    min-height: 400px;
    position: relative;
    flex: 1;
    transition: background 0.3s ease, padding 0.3s ease;
}

/* ============================================================
   Widget Cards
   ============================================================ */

/* S63 Phase 1c — profile-widget (T455 C13/C14): 16px radius (D090), gold hairline
   instead of grey border (LB-024 no greys). */
.profile-widget {
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    /* S199 31/08/26, Rob: "It should be the same border as the workspace itself."
       The workspace frame is `2px solid #CC9900` (.profile-editor-wrapper .profile-grid,
       just above), and every widget now carries the identical rule - measured 1px against
       the workspace's 2px, which is why About Me read as too thin beside it.
       S198 note kept, because its reasoning still holds: this was a 35%-opacity gold that
       read as a grey hairline against the header's solid gold rule directly below it. */
    border: 2px solid #CC9900;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    transition: box-shadow 0.2s ease, background 0.3s ease, border-color 0.3s ease, opacity 0.3s ease;
}

/* Per-widget border colour override — set via colour picker, persisted as
   --widget-border-color on the widget element (Rob 11/05/26). Use LONGHAND
   properties because shorthand `border:` was getting its colour overridden
   somewhere in the cascade despite !important (only width+style were
   winning, colour kept reverting to the default rgba(204,153,0,0.35)).
   Longhand `border-color !important` beats shorthand reliably. */
/* Specificity bumped to (0,4,1) on the public side to beat the existing
   `body.bp-user .profile-grid-public .profile-widget { border-color: ...
   !important }` rule (0,3,1) further up the file. Without that prefix our
   override loses despite !important. The bare selector still covers the
   customise editor where no body-prefix rule competes. */
body.bp-user .profile-grid-public .profile-widget[data-border-color]:not(.profile-widget--quote-autofit),
.profile-widget[data-border-color]:not(.profile-widget--quote-autofit) {
    border-width: 2px !important;
    border-style: solid !important;
    border-color: var(--widget-border-color) !important;
}
/* Public chrome-strip variants (.profile-widget--sigil / --party)
   use `border: 0 none !important` shorthand which clobbers even our
   longhand widths. Restore explicitly with matching specificity.
   --quote-autofit is INTENTIONALLY excluded: the autofit widget is
   invisible (transparent, max-content), so adding a border on the wrapper
   draws a second outer stroke around the visible bubble. For quote the
   bubble alone gets the border-colour treatment (rule below). */
body.bp-user .profile-grid-public .profile-widget--sigil[data-border-color],
body.bp-user .profile-grid-public .profile-widget--party[data-border-color] {
    border-width: 2px !important;
    border-style: solid !important;
    border-color: var(--widget-border-color) !important;
}
/* Quote widget's visible element on public is the inner bubble, not the
   widget wrapper — so the border-colour override paints the bubble. */
.profile-widget[data-widget-id="quote"][data-border-color] .widget-quote,
.profile-widget--quote-autofit[data-border-color] .widget-quote {
    border-width: 2px !important;
    border-style: solid !important;
    border-color: var(--widget-border-color) !important;
}

/* S63 Phase 1c — profile-widget body text (T455 C16/C17): override Seeko Muli/grey
   inheritance to brand Nunito Sans + navy inside public-profile widgets. */
.profile-grid-public .profile-widget,
.profile-grid-public .profile-widget * {
    font-family: 'Nunito Sans', sans-serif;
}
.profile-grid-public .profile-widget p,
.profile-grid-public .profile-widget li,
/* S203 03/09/26 (VS4 task 50, R5b): the organiser Specialities and venue Type pills are navy
   pills with GOLD text (.vw-pill-navy, venue-organiser-widgets.php, D055) - this span rule was
   painting their text navy too, so on the PUBLIC profile they rendered as blank navy blobs while
   every DOM read passed. Exempted like the other coloured spans; the editor never had the rule. */
/* S209 07/09/26: the Google reviews widget's stars (.vw-stars, gold) and the count in its navy summary bar (.vw-reviews-count, cream) are exempted the same way, or they paint navy on navy. */
.profile-grid-public .profile-widget span:not(.interest-tag):not(.bio-level):not([class*="badge"]):not(.vw-pill-navy):not(.vw-stars):not(.vw-reviews-count) {
    color: #031B83;
}
.profile-grid-public .profile-widget h1,
.profile-grid-public .profile-widget h2,
.profile-grid-public .profile-widget h3,
.profile-grid-public .profile-widget h4,
.profile-grid-public .profile-widget .widget-title {
    font-family: 'Montserrat', sans-serif;
    color: #031B83;
}

/* Dragging state — dim the original */
.profile-widget.dragging {
    opacity: 0.4;
    pointer-events: none;
}

/* Ghost clone following cursor */
.profile-widget-ghost {
    position: fixed;
    pointer-events: none;
    z-index: 1000;
    border: 2px solid #CC9900;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
    /* S77 Rob item 24: match the widget's 16px radius on the ghost so the
       photo-panel placeholder's bottom corners don't go square during drag.
       Previous 8px ghost radius was clipping the inner 16px corner. */
    border-radius: 16px;
    background: #fff;
    opacity: 0.9;
    overflow: hidden;
}

/* Preserve glass effect on ghost during drag */
.profile-widget-ghost.glass-ghost {
    background: rgba(255, 255, 255, 0.35);
    backdrop-filter: blur(16px) saturate(1.2);
    -webkit-backdrop-filter: blur(16px) saturate(1.2);
}

/* Drop placeholder in grid */
.grid-placeholder {
    border: 2px dashed #CC9900;
    background: rgba(204, 153, 0, 0.05);
    border-radius: 8px;
    pointer-events: none;
}

/* ============================================================
   Drag Handle (editor) / Header (public)
   ============================================================ */

.widget-drag-handle {
    display: flex;
    align-items: center;
    /* S199: 10px, the spacing Rob approved on the photo panel header, so both are equal. */
    gap: 10px;
    padding: 8px 12px;
    background: #f8f8f8;
    border-bottom: 1px solid #eee;
    cursor: grab;
    user-select: none;
    flex-shrink: 0;
    touch-action: none;
    /* S199 31/08/26, Rob: "The top left and top right hand corners seem to be missing
       their gold border." The widget is a 16px radius with a 2px border, so its INNER
       curve is 14px; the header was drawn at 8px, so at each top corner the cream stopped
       short of the curve and the white body showed through beside the gold - which reads
       as the border breaking up exactly there. Matching the inner radius closes it. */
    border-radius: 14px 14px 0 0;
    transition: background 0.2s ease;
    position: relative;
}

.widget-drag-handle:active {
    cursor: grabbing;
}

.widget-drag-handle .dashicons {
    color: #CC9900;
    font-size: 16px;
    width: 16px;
    height: 16px;
}

/* S200 01/09/26: a widget type can now serve brand SVG instead of a Dashicons class
   (profile-system.php §0.1.4g), which is how the Interested widgets carry the site's own
   gold-and-navy eye. The span has to occupy exactly what the Dashicons span occupied, or the
   header's whole control row shifts on the widgets that use it. */
.widget-drag-handle .widget-type-icon--svg,
.widget-header-public .widget-type-icon--svg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}
.widget-drag-handle .widget-type-icon--svg svg,
.widget-header-public .widget-type-icon--svg svg {
    width: 16px;
    height: 16px;
    display: block;
}
/* The eye is a two-colour brand mark: gold lids, navy iris. The header's blanket
   `svg { stroke: #031B83 }` above would repaint the lids navy, so its own colours are pinned. */
.widget-drag-handle .uks-icon-interest-eye,
.widget-header-public .uks-icon-interest-eye,
#widget-sidebar .uks-icon-interest-eye {
    stroke: #CC9900 !important;
    color: #CC9900 !important;
}
#widget-sidebar > .sidebar-icon .widget-type-icon--svg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
}
#widget-sidebar > .sidebar-icon .widget-type-icon--svg svg {
    width: 18px;
    height: 18px;
    display: block;
}

.widget-title {
    font-family: 'Montserrat', sans-serif;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #031B83;
    flex: 1;
    /* S187: the title used to wrap to a second line and run underneath the colours and
       visibility buttons on any narrow widget — measured on a 4-column party sigil, where
       the title spanned 36-114px while those two buttons sit at 77-121px. They are
       position:absolute (right:56px and right:32px) so they take no space in the flex flow
       and the title had nothing stopping it growing under them. The margin reserves their
       strip, and a flex child needs min-width:0 before it will shrink below its own text
       width at all. One line, ellipsised only when there is genuinely not room.
       Reserved for the VISIBILITY button alone here, because the colours button is
       display:none until colours mode is switched on — reserving for both at all times
       cost ~24px on every widget and truncated "Restore Britain" to "RE…". */
    /* S199: was 24px, reserving a strip for the two absolutely-positioned controls. They
       are in normal flow now, so they claim their own width and the reservation would just
       punch a 24px hole between the title and the icons. */
    margin-right: 0;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* S187's colours-mode strip reservation retired with the margin above (S199) - the button
   takes its own space when it appears, and gives it back when it does not. */

.drag-grip {
    display: none;
}

/* Photo panel — corner label instead of full header */
.profile-widget[data-is-photo-panel="1"] {
    position: relative;
    /* S76 Rob: defensive explicit 4-corner radius so the bottom-left never
       renders square due to cascade order or Seeko overrides. */
    border-radius: 16px !important;
}
/* S76 Rob: lift overflow:hidden during photo reposition mode so the Save /
   Reset / Cancel toolbar (positioned just below the panel) isn't clipped. */
.profile-widget.is-repositioning {
    overflow: visible !important;
    z-index: 20;
}
.photo-panel-handle {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 3;
    /* S198 30/08/26, Rob: "I don't like that gold anyway ... use the light cream and then
       change it to dark cream on hover/grab." The solid gold bar sat on top of the member's
       own photo, which is the one place the chrome should recede. */
    /* S199 31/08/26, Rob: "the headers aren't changing colour in either background or
       front, still." The S198 cream was fixed here with `!important` as well as in the
       shared rule further down, and THIS one was still beating the colour picker's inline
       background on photo panels. Default only, and only until the member picks. */
    background: var(--color-cream, #FFFBE6);
    border: none !important;
    border-bottom: none !important;
    /* S76 Rob: header's bottom corners are square so they meet the body's top edge flat
       (no round-meets-round mismatch). S199: the top corners follow the widget's INNER
       curve (16px outer minus the 2px border), not a flat 8px. */
    border-radius: 14px 14px 0 0 !important;
    padding: 6px 10px !important;
    gap: 8px !important;
    width: auto !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    line-height: 1 !important;
}
/* S198: dark cream while hovered or being dragged, matching the button family's
   cream -> cream-hover pair. S199: unconditional again now that header colours have left the
   picker and every header is cream. */
.photo-panel-handle:hover,
.profile-widget.dragging .photo-panel-handle,
.photo-panel-handle:active {
    background: var(--color-gold-dark, #80641D);
}
.photo-corner-label {
    font-family: 'Montserrat', sans-serif;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: #031B83;
    /* Base rule. The actual nudge lives on the higher-specificity selector
       `.profile-widget[data-is-photo-panel="1"] .photo-corner-label` further
       down — translateY(4px) per /da rule 23a. */
    line-height: 1;
    text-transform: uppercase;
    display: inline-block;
}
.photo-panel-handle .widget-title,
.photo-panel-handle .dashicons {
    display: none;
}
.photo-panel-handle .widget-delete-btn {
    color: #031B83 !important;
    opacity: 1 !important;
    font-size: 14px;
    line-height: 1;
    padding: 0 !important;
    margin: 0 !important;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    /* S76-006 Rob: round bubble on hover, not a tight rectangle. */
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: transparent;
    transition: background 120ms ease, color 120ms ease;
    /* S195 (VS4 task 39): the panel header's controls are right-pinned at a 24px pitch
       (swatch right:56, visibility right:32) while this one was a centred flex child, so at
       the panel's SPAWN width the swatch painted over the delete's centre and a member's
       click on the X opened the colour picker instead. Same mechanism as its siblings:
       pinned at the next step of the pitch. */
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
}
.photo-panel-handle .widget-delete-btn:hover {
    color: #031B83 !important;
    background: #FFFBE6 !important;
    opacity: 1 !important;
}
.photo-panel-body {
    padding: 0 !important;
    height: 100%;
}
.photo-panel-body .photo-panel-content {
    height: 100%;
    position: relative;
    overflow: hidden;
}
.photo-panel-body .photo-panel-content img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* S77 T-FU-S76-05: bottom corners must match outer widget (16px) — not 8px.
       Per-corner !important to defeat any cascade override that was leaving
       bottom-left square while bottom-right curved. */
    /* S199 31/08/26, Rob: the image is square too - the panel itself clips it. */
    border-radius: 0 !important;
    /* S76 Rob: drag is only enabled while in reposition mode. Show grab
       cursor only then — not by default, or users accidentally drag. */
    cursor: default;
}
.photo-panel-content.reposition-active img {
    cursor: grab;
}
.photo-panel-content.reposition-active img.dragging,
.photo-panel-content.reposition-active img:active {
    cursor: grabbing;
}
/* S76's photo-panel-only marker hide is now the platform default (S199, Rob), so the
   override it needed is gone. The rule that does it lives with .resize-handle below. */
.photo-panel-body {
    container-type: size;
    container-name: photopanel;
    overflow: hidden;
}
.photo-panel-body .photo-panel-placeholder {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    min-height: 0;
    gap: 6px;
}
/* Public profile: no label at all, image fills widget */
.profile-grid-public .photo-panel-public {
    overflow: hidden;
    border-radius: 8px;
}
.profile-grid-public .photo-panel-public .widget-body {
    padding: 0 !important;
    height: 100%;
}
.profile-grid-public .photo-panel-public .photo-panel-content img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* ============================================================
   Minimize Button (replaces remove — sends to sidebar)
   ============================================================ */

.widget-minimize-btn {
    background: none;
    border: none;
    color: #031B83;   /* S199, Rob: no greys. Was #ccc. */
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    /* S187: was `margin-left: 4px`, which left Seeko's own margin-bottom:1rem on every
       <button> (seeko-dynamic.css, a ~30-selector list ending in `button`) untouched. The
       header is display:flex; align-items:center, so the flex centring centred this
       button's MARGIN box and pushed the visible glyph 9.5px above the header's centre
       line — measured identical on About Me, My Quote and Spotify. The shorthand replaces
       the inherited bottom margin instead of stacking another rule on top of it.
       This is the S89 failure class: align-items:center computing correctly while the
       result is visibly off-centre because something inflated the box. */
    /* S199: was `0 0 0 4px`. A 4px left margin on top of the header's 10px gap made the
       last gap 14px where the others were 10px - the uneven spacing Rob asked to fix. The
       shorthand still replaces Seeko's inherited margin-bottom (the S187 note below). */
    margin: 0;
    transition: color 0.2s;
}

.widget-minimize-btn:hover {
    color: #CC9900;
}

/* ============================================================
   Widget Body — NO scrollbars
   ============================================================ */

/* ============================================================================
   S199 31/08/26, Rob: CONTENT SCALES WITH THE WIDGET.
   "That's the whole point of being able to resize the widgets. It's resizing the content ...
   They should all have a minimum cap so that the font stays the minimum of the size it is
   when it spawns and the content, but can scale up bigger on resizing of the widget window."
   AUDITED FIRST: every member widget was placed, measured at its spawn size, doubled, and
   measured again - events, attendance, music, quote and bio ALL held the same font at twice
   the size. Nothing scaled, because no widget body was a query container, so there was no
   unit to scale against.
   THE PATTERN, used by every widget converted below:
       font-size: max(<the size it spawns at>, <n>cqw);
   `max()` IS the minimum cap he asked for - the widget can never render its content smaller
   than it does on the day it is dropped, and grows from there in proportion to the widget's
   own width. `container-type: inline-size` contains WIDTH only, so the body still flexes to
   the card's height exactly as before.
   ============================================================================ */
.widget-body {
    padding: 12px;
    flex: 1;
    overflow: auto;
    overflow-x: hidden;
    font-size: 14px;
    color: #031B83;   /* S199, Rob: no greys */
    container-type: inline-size;
    container-name: widgetbody;
}

/* When body text color is set, force ALL descendants to use it */
.profile-widget[data-body-color] .widget-body,
.profile-widget[data-body-color] .widget-body * {
    color: var(--body-text-color) !important;
}

/* ============================================================
   Resize Handle
   ============================================================ */

.resize-handle {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 20px;
    height: 20px;
    cursor: se-resize;
    touch-action: none;
    z-index: 2;
}

/* S199 31/08/26, Rob: "I don't want there to be one on any widget."
   The little right-angle in the bottom-right corner was a resize affordance, drawn on
   every widget except photo panels (S76 had already hidden it there, which is how Rob
   spotted the inconsistency). The MARKER is gone platform-wide; the handle itself is
   untouched, so dragging the corner still resizes exactly as before. */
.resize-handle::after {
    content: none;
}

/* ============================================================
   Per-Widget Color Picker
   ============================================================ */

/* S199 31/08/26, Rob: "So I say uniform or symmetrical ... please fix it on all the
   other widgets." These controls were pinned to fixed right offsets (56px and 32px) while
   the minimise button sat in normal flow, so the gaps came out 4px then 2px - visibly
   uneven up close. They now flow in source order with the header's own gap, which is the
   arrangement Rob signed off on the photo panel, so every widget header is spaced the
   same. */
.color-swatch-btn {
    width: 20px;
    height: 20px;
    border-radius: 4px;
    border: none;
    background: none;
    cursor: pointer;
    padding: 0;
    display: none;           /* hidden until Colors mode is on */
    position: static;
    flex: 0 0 auto;
    font-size: 16px;
    line-height: 1;
    color: #031B83;
    transition: color 0.2s;
    z-index: 2;
}

.colors-active .color-swatch-btn {
    display: flex;
    align-items: center;
    justify-content: center;
}

.color-swatch-btn:hover {
    color: #CC9900;
    transform: scale(1.15);
}
/* S199: on the photo panel these controls are in normal flow, so the hover must not
   re-introduce the -50% lift the absolute layout needed - it made the icon jump 10px on
   hover. Scale only. */
.photo-panel-handle .color-swatch-btn:hover,
.photo-panel-handle .widget-visibility-btn:hover {
    transform: scale(1.15) !important;
}

/* S76: Per-widget visibility button — always visible in the editor (not gated
   by colours mode). Opens the visibility-popover anchored to this button. */
.widget-visibility-btn {
    width: 20px;
    height: 20px;
    border-radius: 4px;
    border: none;
    background: none;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* S199: normal flow, same as the swatch above - see the note there. */
    position: static;
    flex: 0 0 auto;
    font-size: 16px;
    line-height: 1;
    color: #031B83;
    transition: color 0.2s;
    z-index: 2;
}

.widget-visibility-btn:hover {
    color: #CC9900;
    transform: scale(1.15);
}

/* Hide on the public-facing grid */
.profile-grid-public .widget-visibility-btn {
    display: none;
}

/* Colour popover — S76-005: reverted to pre-rebrand chrome per Rob.
   Original white+grey was fine; other page elements were the real target. */
/* S199 31/08/26, Rob: "the colour picker itself should have a gold border. Same as all
   the others, but it's missing." Matched to .visibility-popover, which is the canonical
   popover frame on this page: 2px gold, 12px radius. The grey hairline was also an LB-024
   breach (no greys). */
.color-popover {
    position: absolute;
    z-index: 999999;
    background: #fff;
    max-height: 80vh;
    overflow-y: auto;
    border: 2px solid #CC9900;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    padding: 4px 7px 7px;
    display: none;
    width: 148px;
}

.color-popover.open {
    display: block;
}

.color-section-label {
    font-family: 'Montserrat', sans-serif;
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-muted, rgba(3,27,131,.55));      /* S199, Rob: no greys */
    margin: 8px 0 2px 0;
    line-height: 1;
}
.color-section-label:first-of-type {
    margin-top: 0;
}

.color-presets {
    display: flex;
    gap: 3px;
    flex-wrap: wrap;
    margin-bottom: 0;
}

.color-preset {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid #e0e0e0;
    cursor: pointer;
    padding: 0 !important;
    margin: 0 !important;
    transition: border-color 0.2s, transform 0.15s;
}

.color-preset:hover {
    transform: scale(1.15);
    border-color: #CC9900;
}

.color-preset.selected {
    border-color: #CC9900;
    box-shadow: 0 0 0 2px rgba(204, 153, 0, 0.3);
}

.color-hex-input {
    width: 100%;
    padding: 3px 5px !important;
    margin: 2px 0 2px !important;
    border: 1px solid #ddd !important;
    border-radius: 3px;
    font-family: 'Montserrat', monospace !important;
    font-size: 11px !important;
    color: #555;
    height: auto !important;
    min-height: 0 !important;
    line-height: 1.3 !important;
    box-sizing: border-box !important;
    background: #fafafa !important;
}

.color-hex-input:focus {
    outline: none;
    border-color: #CC9900;
}

/* T337: Widget visibility dropdown in popover */
.widget-visibility-select {
    width: 100%;
    padding: 5px 8px;
    margin: 4px 0 2px;
    border: 2px solid #CC9900;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-size: 11px;
    font-weight: 600;
    color: #031B83;
    background: #fff;
    cursor: pointer;
    appearance: auto;
}
.widget-visibility-select:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(204, 153, 0, 0.3);
}

/* S76: Branded background-picker modal — replaces the native prompt() and
   the wp.media() modal. One dialog: URL input at top, user photo gallery
   below. Uses cream/gold/navy brand tokens (D055 + LB-023). */
.bg-picker-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(3, 27, 131, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000000;
    font-family: 'Nunito Sans', sans-serif;
}
.bg-picker-modal {
    position: relative;
    background: #FFFFFF;
    border: 2px solid #CC9900;
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(3, 27, 131, 0.2);
    padding: 24px;
    width: min(520px, calc(100vw - 32px));
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    color: #031B83;
}
.bg-picker-modal-close {
    position: absolute;
    top: 10px;
    right: 14px;
    background: transparent;
    border: none;
    font-size: 24px;
    color: #031B83;
    cursor: pointer;
    line-height: 1;
    padding: 4px 8px;
}
.bg-picker-modal-close:hover { color: #CC9900; }
.bg-picker-modal-title {
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 18px;
    color: #031B83;
    margin: 0 0 16px 0;
    text-align: center;
}
.bg-picker-modal-section { margin-bottom: 14px; }
.bg-picker-modal-label {
    display: block;
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #031B83;
    margin-bottom: 6px;
    /* S76-006 Rob: centre labels above each input. */
    text-align: center;
}
.bg-picker-modal-url-row {
    display: flex;
    gap: 8px;
}
.bg-picker-modal-url-input {
    flex: 1;
    padding: 8px 12px;
    border: 2px solid #CC9900 !important;
    border-radius: 8px;
    font-size: 13px;
    font-family: 'Nunito Sans', sans-serif;
    background: #fff;
    color: #031B83;
}
.bg-picker-modal-url-input:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(204, 153, 0, 0.3);
}
.bg-picker-modal-url-apply {
    background: #FFFBE6;
    border: 2px solid #CC9900;
    color: #031B83;
    border-radius: 20px;
    padding: 6px 18px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 12px;
    cursor: pointer;
    transition: background 160ms ease, color 160ms ease;
}
.bg-picker-modal-url-apply:hover {
    background: #CC9900;
    color: #031B83;
}
.bg-picker-modal-upload-btn {
    width: 100%;
    padding: 10px 16px;
    background: #FFFBE6;
    border: 2px solid #CC9900;
    color: #031B83;
    border-radius: 10px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: background 160ms ease, color 160ms ease;
}
.bg-picker-modal-upload-btn:hover { background: #CC9900; color: #031B83; }
.bg-picker-modal-upload-btn .dashicons {
    font-size: 16px; width: 16px; height: 16px; line-height: 1;
}
/* S76 Rob: Uploading state no longer dim/grey — stays on-brand with a navy
   fill + gold text (D055 invert) so it reads as "in progress" not "disabled". */
.bg-picker-modal-upload-btn[disabled] { opacity: 1; cursor: wait; background: #031B83; color: #CC9900; }
.bg-picker-modal-upload-btn[disabled] .dashicons { animation: bg-picker-upload-spin 1s linear infinite; }
@keyframes bg-picker-upload-spin { to { transform: rotate(360deg); } }
.bg-picker-modal-divider {
    text-align: center;
    color: #031B83;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin: 10px 0;
    position: relative;
}
.bg-picker-modal-divider::before,
.bg-picker-modal-divider::after {
    content: '';
    position: absolute;
    top: 50%;
    width: calc(50% - 24px);
    height: 1px;
    background: rgba(204, 153, 0, 0.6);
}
.bg-picker-modal-divider::before { left: 0; }
.bg-picker-modal-divider::after { right: 0; }
.bg-picker-modal-divider span {
    background: #FFFBE6;
    padding: 0 8px;
    position: relative;
    z-index: 1;
}
.bg-picker-modal-gallery {
    /* S76-006 Rob: force true centring with flex-wrap + centered justification
     instead of auto-fill grid which packs left. */
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: flex-start;
    gap: 8px;
    max-height: 340px;
    overflow-y: auto;
    padding: 10px;
    border: 2px solid #CC9900;
    border-radius: 8px;
    background: #fff;
}
.bg-picker-modal-thumb {
    flex: 0 0 90px;
}
.bg-picker-modal-thumb {
    aspect-ratio: 1;
    padding: 0;
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
    overflow: hidden;
    background: #fff;
    transition: border-color 120ms ease, transform 120ms ease;
}
.bg-picker-modal-thumb:hover {
    border-color: #CC9900;
    transform: scale(1.04);
}
.bg-picker-modal-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.bg-picker-modal-loading,
.bg-picker-modal-empty {
    grid-column: 1 / -1;
    padding: 24px 12px;
    text-align: center;
    /* S198 30/08/26, Rob: was #666. No greys - navy. */
    color: #031B83;
    font-size: 12px;
    font-family: 'Nunito Sans', sans-serif;
}

/* S76 Rob pt2: Public profile — hide widget header/title bar on ALL widgets.
   Public profile shows content only; chrome (icon + label + minimize) is
   Customise-only. Photo panels already render without a header. Sigils / party
   logos have their own handle rules further down. */
.profile-grid-public .profile-widget .widget-drag-handle.widget-header-public {
    display: none !important;
}
.profile-grid-public .profile-widget .widget-body {
    padding-top: 0;
}

/* S76 Rob pt2: Social-link buttons on public profile — branded cream pill
   with gold border, navy text, dashicon + label vertically centred. Hover
   flips to gold bg + navy text per D055. */
.profile-grid-public .widget-social-links .social-links-list,
.widget-social-links .social-links-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 0;
    margin: 0;
}
.widget-social-links .social-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 10px 16px;
    background: #FFFBE6;
    border: 2px solid #CC9900;
    border-radius: 10px;
    color: #031B83;
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 13px;
    text-decoration: none;
    transition: background 160ms ease, color 160ms ease, transform 120ms ease;
    line-height: 1;
}
.widget-social-links .social-link .dashicons {
    color: #CC9900;
    width: 18px;
    height: 18px;
    font-size: 18px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color 160ms ease;
}
.widget-social-links .social-link-label {
    line-height: 1;
    display: inline-flex;
    align-items: center;
}
.widget-social-links .social-link:hover {
    background: #CC9900;
    color: #031B83;
    transform: translateY(-1px);
}
.widget-social-links .social-link:hover .dashicons {
    color: #031B83;
}

/* S76 Rob pt2: Photo-panel placeholder on-brand. Previously dashicon +
   "Click to choose photo" both rendered grey. Now: gold camera icon, navy
   text, cream background. Also vertically centre the "PHOTO" corner label. */
.profile-widget[data-is-photo-panel="1"] .widget-drag-handle.photo-panel-handle {
    display: flex;
    align-items: center;
}
.profile-widget[data-is-photo-panel="1"] .photo-corner-label,
.profile-widget[data-is-photo-panel="1"].dragging .photo-corner-label,
.widget-fly-clone[data-is-photo-panel="1"] .photo-corner-label,
.profile-widget-ghost[data-is-photo-panel="1"] .photo-corner-label,
.widget-fly-clone .photo-corner-label,
.profile-widget-ghost .photo-corner-label {
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.5px;
    color: #031B83;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    /* S199 31/08/26: was `translateY(6px)`, tuned in S77 when this header was a small
       absolute tab whose label needed pushing down onto the photo. S198 made the header a
       full-height bar with `align-items: center`, so the flex centring already places the
       label and the old nudge simply dropped it 6px below its own siblings, under the
       icons. This selector outranks the S198 rule below it (0,3,0 against 0,2,0), so the
       value is corrected HERE rather than fought further down. */
    transform: none !important;
}
.photo-panel-placeholder,
.photo-panel-content.photo-panel-empty {
    display: flex !important;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 100%;
    background: #FFFFFF;
    color: rgba(3, 27, 131, 0.65);
    border: 2px dashed rgba(204, 153, 0, 0.6);
    /* S199 31/08/26, Rob: "make sure the corners are square rectangles matching the actual
       widget itself so you don't see those rounded corners and the colour behind if they
       change the background colour, because it just looks shit and amateur." The panel's own
       16px radius already clips the outer corners, so the child needs none of its own - its
       rounding was leaving four crescents where the widget's body background showed through. */
    border-radius: 0 !important;
}
/* S77 Rob item 7 rounded these children to 16px so their corners matched the widget in both
   the static and drag-ghost states.
   S199 31/08/26, ROB REPLACES THAT: they are SQUARE now. "make sure the corners are square
   rectangles matching the actual widget itself so you don't see those rounded corners and the
   colour behind if they change the background colour, because it just looks shit and amateur."
   The panel's own 16px radius plus overflow:hidden already clips the outer corners, so the
   child's own rounding only ever left four crescents of the body background showing through.
   The value is swapped here rather than overridden further down. */
.photo-panel-placeholder,
.photo-panel-content,
.photo-panel-content img,
.widget-fly-clone .photo-panel-placeholder,
.profile-widget-ghost .photo-panel-placeholder {
    border-radius: 0 !important;
}
.photo-panel-placeholder,
.photo-panel-content.photo-panel-empty {
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.3px;
}
.photo-panel-placeholder .dashicons,
.photo-panel-content.photo-panel-empty .dashicons {
    color: #CC9900 !important;
    font-size: 32px !important;
    width: 32px;
    height: 32px;
}

/* S76 Rob pt2: Social-field save tick — instant toggle feedback, not a
   delayed flash. Saved state = filled gold bg (until dirty again). */
.social-link-save-field {
    transition: background 60ms ease, color 60ms ease, transform 80ms ease;
}
.social-link-save-field.saved {
    background: #CC9900 !important;
    color: #fff !important;
}
.social-link-save-field:active {
    transform: scale(0.92);
}

/* S77 Rob item 18: Visibility popover — white bg (was cream), gold border,
   navy text. Header row uses flex so title + X are vertically centred and
   symmetrically aligned. */
.visibility-popover {
    position: absolute;
    z-index: 999999;
    background: #ffffff;
    border: 2px solid #CC9900;
    border-radius: 12px;
    box-shadow: 0 4px 12px rgba(3, 27, 131, 0.15);
    padding: 14px;
    display: none;
    width: 200px;
    font-family: 'Nunito Sans', sans-serif;
    color: #031B83;
}
.visibility-popover.open {
    display: block;
}
/* Header row: title on the left, X on the right, vertically centred,
   consistent 4px gap above the options below. */
.visibility-popover-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}
.visibility-popover-close {
    background: transparent;
    border: none;
    color: #031B83;
    font-size: 18px;
    line-height: 1;
    padding: 0;
    width: 22px;
    height: 22px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.visibility-popover-close:hover { color: #CC9900; }
.visibility-popover-label {
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #031B83;
    margin: 0;
    line-height: 1.3;
    flex: 1;
}

/* S76: Colour reset-dial — sits on the presets row after the colour chips.
   Resets the section's colour to #FFFFFF. Half-circle-arc-with-arrow icon. */
.color-reset-btn {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid #e0e0e0;
    background: #fff !important;
    cursor: pointer;
    padding: 0 !important;
    margin: 0 !important;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #031B83;
    transition: border-color 0.2s, transform 0.15s, color 0.2s;
}
.color-reset-btn .dashicons {
    font-size: 11px;
    width: 11px;
    height: 11px;
    line-height: 1;
}
.color-reset-btn:hover {
    transform: scale(1.15);
    border-color: #CC9900;
    color: #CC9900;
}

.popover-drag-bar {
    cursor: grab;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 0;
    margin: 0;
    user-select: none;
    min-height: 0;
    line-height: 1;
}
.popover-drag-bar:active {
    cursor: grabbing;
}
.popover-close-btn {
    background: none;
    border: none !important;
    font-size: 13px;
    line-height: 1;
    color: var(--color-text-muted, rgba(3,27,131,.55));      /* S199, Rob: no greys */
    cursor: pointer;
    padding: 0 2px !important;
    margin: 0 !important;
    border-radius: 3px;
    transition: all 0.15s;
}
.popover-close-btn:hover {
    color: #031B83;   /* S199, Rob: no greys */
    background: #f0f0f0;
}

/* Empty widget tooltip */
.widget-empty-tooltip {
    position: absolute;
    background: #fff;
    color: #031B83;
    font-family: 'Montserrat', sans-serif;
    font-size: 12px;
    font-weight: 600;
    padding: 8px 14px;
    border-radius: 6px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
    border: 1px solid #CC9900;
    white-space: nowrap;
    z-index: 999999;
    transition: opacity 0.3s;
    pointer-events: none;
}


/* ============================================================================
   S198 30/08/26 — BRANDED LABELS FOR EVERY EDITOR CONTROL (Rob).
   The rail got these in S185; the widget headers, the photo panel and the
   reposition control were all still on `title`, which draws the browser's own
   black OS box. It ignores the brand, cannot be screenshotted, and sat right
   next to branded ones. Same shape as the rail's: white, gold border, navy
   text, and it never intercepts a click.
   The rail keeps its own copy (profile-system.php) because it positions
   differently - to the left in the column, below in the top rail.
   ============================================================================ */
/* S198 30/08/26 - SCOPED, not blanket. The first version of this rule set
   `position: relative` on every [data-tip] in the editor, which overrode the
   `position: absolute` that .color-swatch-btn / .widget-visibility-btn /
   .widget-minimize-btn are laid out with (each pinned to its own `right` offset).
   Their offsets stopped anchoring and became relative shifts, and the whole header
   spread out - that was my doing, not the theme's. An absolutely positioned element
   already forms a containing block for its own ::after, so those three need nothing
   here; only the genuinely static controls do. */
.profile-editor-wrapper .drag-grip[data-tip],
.profile-editor-wrapper .photo-panel-content [data-tip],
.profile-editor-wrapper .photo-corner-label[data-tip] { position: relative; }
.profile-editor-wrapper .widget-drag-handle [data-tip]::after,
.profile-editor-wrapper .photo-panel-handle [data-tip]::after,
.profile-editor-wrapper .photo-panel-content [data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    left: 50%;
    top: calc(100% + 8px);
    transform: translateX(-50%);
    background: #fff;
    color: #031B83;
    border: 2px solid #CC9900;
    border-radius: 8px;
    padding: 6px 10px;
    font-family: 'Nunito Sans', sans-serif;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    box-shadow: 0 2px 8px rgba(0,0,0,.12);
    opacity: 0;
    visibility: hidden;
    transition: opacity .15s ease;
    pointer-events: none;
    z-index: 10000;
}
.profile-editor-wrapper .widget-drag-handle [data-tip]:hover::after,
.profile-editor-wrapper .widget-drag-handle [data-tip]:focus-visible::after,
.profile-editor-wrapper .photo-panel-handle [data-tip]:hover::after,
.profile-editor-wrapper .photo-panel-handle [data-tip]:focus-visible::after,
.profile-editor-wrapper .photo-panel-content [data-tip]:hover::after,
.profile-editor-wrapper .photo-panel-content [data-tip]:focus-visible::after {
    opacity: 1;
    visibility: visible;
}
/* A widget header is only as tall as its controls, so the label would be clipped
   by the widget's own `overflow: hidden`. Raise the hovered control and let the
   header show what overflows it while a label is up. */
.profile-editor-wrapper .widget-drag-handle [data-tip]:hover,
.profile-editor-wrapper .photo-panel-handle [data-tip]:hover,
.profile-editor-wrapper .photo-panel-content [data-tip]:hover { z-index: 10001; }
.profile-editor-wrapper .profile-widget:has([data-tip]:hover) { overflow: visible; }


/* ============================================================================
   S198 30/08/26 — WIDGET HEADER BAR, to Rob's spec (30/08/26):
     "maybe 10% space above and below the icons, they need to all be the blue and
      clear, the headers need to be the light cream with gold border, and the icons
      need to be neatly positioned next to each other up to the right corner with
      the minimise icon last."

   THE CAUSE OF THE SPREAD, and it was never the gap. Seeko's own stylesheet puts
   `margin-bottom: 18px` on every <button>, so each control in this header carried
   18px of dead margin. Measured on a live header: the bar rendered 55px tall for a
   20px icon, and the controls sat 32px and 44px apart against a declared 8px gap.
   That is the same parent-theme margin that inflated the section-nav in S89 and is
   named in the global brief's Rule 2. Zeroing it is the fix; adjusting the gap
   around it would only have moved the symptom.

   Icons are pushed to the right as one block by an auto left margin on the first
   control, so they stay together against the corner whatever the title's length,
   and the minimise button keeps the last slot from the markup order.
   ============================================================================ */
/* S199 31/08/26, Rob: "The colour picker doesn't work for the header anymore."
   `!important` on this background outranked the inline `style="background:..."` the
   per-widget colour picker writes, so a member could pick a header colour, see it stored
   on the element, and watch the cream paint straight over it - on EVERY widget, not just
   photo panels. The cream is still the default (this rule sits after the base
   `.widget-drag-handle` and wins on order alone) but an inline choice now beats it. */
.widget-drag-handle,
.photo-panel-handle {
    background: var(--color-cream, #FFFBE6);
    border-bottom: 1px solid var(--color-gold, #CC9900) !important;
    box-sizing: border-box !important;
    min-height: 28px !important;
    padding: 4px 10px !important;
    display: flex !important;
    align-items: center !important;
}
/* The controls are absolutely positioned by the original design, each pinned to its
   own `right` offset with the minimise button last - that is what keeps them tight in
   the corner. Nothing here touches their flow; only the parent theme's stray button
   margin is cleared, which is what inflated the bar to 55px for a 20px icon (the same
   Seeko `button { margin-bottom: 18px }` named in Rule 2 of the brief). */
.widget-drag-handle button,
.photo-panel-handle button,
.widget-drag-handle > span,
.photo-panel-handle > span {
    margin-bottom: 0 !important;
}
.widget-drag-handle .widget-title {
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
}
/* Every control reads navy, on the cream.
   S199 31/08/26: header colours left the picker entirely (Rob - no widget header is ever
   visible on the public profile, verified on three profiles), so headers are fixed cream and
   gold and this navy is unconditional again. It was briefly scoped to
   `:not([data-font-color])` while the picker still offered header text; with the picker gone
   that scoping would have stranded any widget carrying an old stored value on whatever the
   parent theme felt like. */
.widget-drag-handle button,
.widget-drag-handle .widget-title,
.widget-drag-handle > span,
.photo-panel-handle button,
.photo-panel-handle > span {
    color: #031B83 !important;
    opacity: 1 !important;
}
.widget-drag-handle svg,
.photo-panel-handle svg {
    stroke: #031B83;
    color: #031B83;
}
/* S199 31/08/26, Rob: "the icons, including the heart icon, are maybe a pixel too low. Look at
   the label in the header ... The icons are all maybe one pixel too low compared to that, and
   that is global as well."
   MEASURED IN PAINT at 6x, not from properties (LB-334). Against the header's centre line the
   label's ink sits 0.93px HIGH - it is all-caps, so it has no descenders and its ink rides high
   in its line box - while the swatch and eye land on the centre and the minus glyph sits 1.41px
   LOW. So the icons really are about a pixel and a half below the label, exactly as he saw.
   The boxes are all perfectly aligned; it is the INK inside them that is not, which is why no
   amount of box measurement ever showed it. Whole-pixel nudges only - a half-pixel here is the
   parity trap in /da rule 21b. */
/* S200 01/09/26, Rob, correcting the S199 attempt: "A one pixel height horizontal center line
   ... that's the center line of the header, obviously. So then you take the same center line ...
   of the icons, the ink of the icons, not the boundar boxes, and the ink of the the text label.
   And you make sure they're all on the same line."
   S199 measured everything against the LABEL's ink and moved the controls to meet it. The label
   was itself 1px high, so that pulled the whole row a pixel above the header's own centre - which
   is exactly the fault he photographed. The reference is the HEADER's centre line and nothing
   else. MEASURED IN PAINT at 6x, ink only, cookie bar dismissed first (it had been sitting over
   one of the headers and poisoning that reading):
     label  -1.08   swatch -0.91   eye -1.08   minus -0.58   type glyph -0.08
   all above the line. The header is 29px, an ODD number, so it HAS a centre pixel row and the
   values below are reachable (/da rule 21b). Each nudge is the measured offset, added back. */
.widget-drag-handle .widget-title,
.photo-panel-handle .photo-corner-label {
    position: relative;
    top: 1px;
}
/* Per-glyph corrections. Every widget-type glyph was measured on all three account types,
   41 headers in total; all but two land within 0.41px of the header's centre line once the
   row above is corrected. These two do not, because the ink sits off-centre inside the glyph's
   own em box, which no box-level rule can reach:
     dashicons-format-quote   -0.91  (a quotation mark has no lower ink at all)
     icon-wishlist-fingers    +1.34
   Whole pixels only: a fractional `top` moves the box and does NOT move the paint (proven at
   6x on the minimise button), and Rob's screen is 1x where fractions do not exist. */
.widget-drag-handle .dashicons-format-quote,
.widget-header-public .dashicons-format-quote {
    position: relative;
    top: 1px;
}
.widget-drag-handle .icon-wishlist-fingers,
.widget-header-public .icon-wishlist-fingers {
    position: relative;
    top: -1px;
}
.widget-drag-handle .color-swatch-btn,
.widget-drag-handle .widget-visibility-btn,
.photo-panel-handle .color-swatch-btn,
.photo-panel-handle .widget-visibility-btn {
    position: relative;
    top: 0;
}
/* The minus glyph sits lower again inside its own em box, so it keeps part of its offset.
   S200: it measured -0.58 with the old -2px. A -1.42px top moves the BOX by 0.58 (proven with
   getBoundingClientRect at four values) but the painted glyph did not move by a single device
   pixel at 6x - text paint here only responds to WHOLE pixel offsets, which is also all that
   exists on Rob's 1x screen. So the choice is -0.58 or +0.42, and +0.42 is the closer of the
   two to the header's centre line. */
.widget-drag-handle .widget-minimize-btn,
.photo-panel-handle .widget-minimize-btn,
.photo-panel-handle .widget-delete-btn {
    position: relative;
    top: -1px;
}
/* The photo panel's own reset uses !important on these controls, so the nudge is repeated at
   matching weight rather than left to lose silently. */
.photo-panel-handle .color-swatch-btn,
.photo-panel-handle .widget-visibility-btn { top: 0 !important; }
.photo-panel-handle .widget-minimize-btn,
.photo-panel-handle .widget-delete-btn { top: -1px !important; }

/* The minimise button was rendering as a faint dash. Same weight as its neighbours. */
.widget-drag-handle .widget-minimize-btn,
.photo-panel-handle .widget-minimize-btn,
.photo-panel-handle .widget-delete-btn {
    font-size: 16px !important;
    font-weight: 700 !important;
    line-height: 1 !important;
    background: none !important;
    border: none !important;
    padding: 0 !important;
    width: 20px !important;
    height: 20px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}



/* ============================================================================
   S198 30/08/26 — THE PHOTO PANEL GETS AN ORDINARY HEADER (Rob).
   It was absolutely positioned as a small tab floating over the top-left of the
   photo, which is why it looked nothing like its neighbours, why the paintbrush
   sat proud of it, and why the panel needed a separate circular control to be
   moved at all. Put back in normal flow it is the same bar as every other widget,
   so it drags the same way and needs no bespoke control.
   ============================================================================ */
.profile-widget[data-is-photo-panel="1"] .widget-drag-handle.photo-panel-handle,
.photo-panel-handle {
    /* RELATIVE, not static. The colour / visibility / change-photo controls are absolutely
       positioned against their own right offsets; with the header static they anchored to
       the WIDGET instead and floated in the middle of the photo, which is what Rob saw. */
    position: relative !important;
    width: 100% !important;
    border-radius: 14px 14px 0 0 !important;
    padding: 4px 10px !important;
    justify-content: flex-start !important;
    cursor: grab !important;
}
.profile-widget[data-is-photo-panel="1"] .photo-panel-handle:active {
    cursor: grabbing !important;
}
/* THE PUBLIC PROFILE KEEPS NO HEADER ON A PHOTO PANEL AT ALL - the photo is the
   whole point of the widget and chrome over it is editor-only furniture. */
.profile-grid-public .photo-panel-handle,
.profile-widget-public .photo-panel-handle,
.profile-public-wrapper .photo-panel-handle {
    display: none !important;
}


/* The PHOTO label takes the slack so the in-flow minimise button lands at the right end of
   the bar instead of immediately after the word - it was rendering inside "PHOTO", between
   the H and the O. */
.photo-panel-handle .photo-corner-label {
    flex: 1 1 auto !important;
    text-align: left !important;
}
.photo-panel-handle .widget-minimize-btn {
    margin-left: auto !important;
}


/* ============================================================================
   S198 30/08/26 — PHOTO PANEL HEADER CONTROLS (Rob).
   The colour and visibility buttons are absolutely positioned against fixed right
   offsets, which is fine on an ordinary widget header but put the change-photo X
   straight on top of the minimise button here, because this header carries FOUR
   controls where the others carry three. Taken out of absolute flow for this header
   only, so the four sit in source order - X, brush, eye, minimise - evenly spaced
   and hard against the right edge.
   ============================================================================ */
.photo-panel-handle .widget-delete-btn,
.photo-panel-handle .color-swatch-btn,
.photo-panel-handle .widget-visibility-btn,
.photo-panel-handle .widget-minimize-btn {
    /* S199: RELATIVE, not static. Relative still flows exactly like static - the box keeps its
       place in the row - but it lets the one-pixel ink nudge above actually apply here too.
       With `static !important` the nudge was silently dropped on photo panels only. */
    position: relative !important;
    right: auto !important;
    left: auto !important;
    margin: 0 !important;
    flex: 0 0 auto !important;
    /* S199 31/08/26, Rob ("minimise is detached"): the base rules pair `top: 50%` with
       `transform: translateY(-50%)` to centre these while absolutely positioned. S198 took
       the position away and left the transform, so the brush and the eye were lifted a flat
       10px (half their own 20px height) while the minimise button, which never had the
       transform, stayed put. Measured live: brush and eye at y=1165.6, minimise at 1175.6.
       Clearing the transform is what makes align-items:center do the centring. */
    transform: none !important;
}
.photo-panel-handle {
    gap: 10px !important;
}
.photo-panel-handle .photo-corner-label {
    flex: 1 1 auto !important;
    /* S198, Rob: "the word photo needs to be nudged up maybe a pixel because it's below
       the vertical centre line". Overrides the S77 translateY(6px), which was tuned when
       this header was a small absolute tab rather than a full-height bar. */
    transform: translateY(-1px) !important;
}
.photo-panel-handle .widget-minimize-btn { margin-left: 0 !important; }

/* S198, Rob: "once you hover over one of the icons they have a slight grey box ... it
   should be the same light cream." Seeko paints a grey on button:hover; these controls
   sit on cream and should stay on it. */
.widget-drag-handle button:hover,
.photo-panel-handle button:hover,
.widget-drag-handle button:focus,
.photo-panel-handle button:focus {
    background: transparent !important;
    box-shadow: none !important;
    color: #031B83 !important;
}

/* ============================================================
   Grid min-height — ensures background has a sensible minimum
   ============================================================ */

.profile-grid {
    min-height: 600px;
}

/* ============================================================
   Height Pin — thin full-width widget in normal grid flow.
   Draggable and minimisable like any other widget.
   Size fixed at w=12 h=1 — resize handle hidden.
   Minimize button centred.
   ============================================================ */

.widget-spacer-bar {
    display: none;
}

/* S77 Rob item 12: spacer \u2014 gold border (was grey), remove the grey top
   separator line inside the spacer header, reduce overall height by ~70%.
   S80 T559: `grid-row-end: span 2 !important` clamps the cell to 2 rows
   (~30px including gap) regardless of saved h, so existing user layouts
   with h=6 / h=11 render as a thin pin too. Resize handle is already
   hidden at line ~1977 so users can't expand it manually. */
.profile-widget[data-widget-id="spacer"],
.profile-widget-ghost[data-widget-id="spacer"] {
    grid-row-end: span 2 !important;
    min-height: unset !important;
    max-height: 22px !important;
    background: #ffffff !important;
    border: 2px solid #CC9900 !important;
    box-shadow: 0 1px 4px rgba(0,0,0,0.08) !important;
    border-radius: 6px;
    overflow: hidden;
    margin: 0 !important;
    padding: 0 !important;
}

/* S108 11/06/26 — Spacer (height pin) = single full-area drag bar.
   - widget-drag-handle fills the entire widget so the whole pin is the
     grab target (was just a 2px strip — fiddly to grab).
   - Every descendant inside the handle hidden so no "HEIGHT PIN" label,
     icons or buttons leak through.
   - Selectors include `.profile-widget-ghost[data-widget-id="spacer"]`
     because the drag library deep-clones the widget then overwrites the
     className to "profile-widget-ghost", dropping ".profile-widget" and
     making rules scoped to `.profile-widget[...]` stop matching the ghost.
   - Resize handle also hidden so its clone doesn't draw a second bar. */
.profile-widget[data-widget-id="spacer"] .widget-drag-handle,
.profile-widget-ghost[data-widget-id="spacer"] .widget-drag-handle {
    background: #ffffff !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 0 !important;
    height: 100% !important;
    width: 100% !important;
    box-sizing: border-box !important;
    display: block !important;
    cursor: grab;
    border: 0 !important;
    font-size: 0 !important;
    line-height: 0 !important;
    color: transparent !important;
}
.profile-widget[data-widget-id="spacer"] .widget-drag-handle:active,
.profile-widget-ghost[data-widget-id="spacer"] .widget-drag-handle:active {
    cursor: grabbing;
}
.profile-widget[data-widget-id="spacer"] .widget-drag-handle *,
.profile-widget[data-widget-id="spacer"] .widget-drag-handle::before,
.profile-widget[data-widget-id="spacer"] .widget-drag-handle::after,
.profile-widget-ghost[data-widget-id="spacer"] .widget-drag-handle *,
.profile-widget-ghost[data-widget-id="spacer"] .widget-drag-handle::before,
.profile-widget-ghost[data-widget-id="spacer"] .widget-drag-handle::after {
    display: none !important;
    content: none !important;
}
.profile-widget[data-widget-id="spacer"] .widget-body,
.profile-widget[data-widget-id="spacer"] .resize-handle,
.profile-widget-ghost[data-widget-id="spacer"] .widget-body,
.profile-widget-ghost[data-widget-id="spacer"] .resize-handle {
    display: none !important;
}

.profile-widget[data-widget-id="spacer"] .resize-handle {
    display: none;
}

/* S79 Rob: spacer ("Height Pin") is rendered on public but invisible —
   `visibility: hidden` keeps the grid space (so the workspace size matches
   customise), `display: none` was removing it entirely and shoving every
   widget up over the iframe etc.
   S80 T559: `grid-row-end: span 2 !important` mirrors the customise clamp
   so the public cell is the same thin pin too. (The real "widgets pushed
   up onto iframe" symptom Rob saw in S79 was the music widget's row-span
   inflation in profile_system_render_profile_public — fixed in collect_visible
   so the breakpoint JSON used by the public render's resize handler reflects
   the inflated h, not the saved h.) */
.profile-widget-public[data-widget-id="spacer"] {
    grid-row-end: span 2 !important;
    visibility: hidden;
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
}

/* Glass mode styling */
.glass-on .profile-widget[data-widget-id="spacer"] {
    background: rgba(235, 240, 255, 0.7) !important;
    border-color: rgba(200, 215, 255, 0.4) !important;
}
.glass-on .profile-widget[data-widget-id="spacer"] .widget-drag-handle {
    background: rgba(220, 230, 255, 0.5) !important;
}

/* ============================================================
   Photo Panels — decorative image blocks
   ============================================================ */

.photo-panel-content {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;
    /* S199 31/08/26, Rob: square. Was `0 0 8px 8px`, which never matched the widget's own
       curve anyway and left the body background showing in the gap. */
    border-radius: 0;
}

.photo-panel-content img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.photo-panel-placeholder {
    text-align: center;
    /* S77 Rob: navy not grey. Was overriding the on-brand colour from the
       earlier rule via source-order (same specificity, later in file). */
    color: rgba(3, 27, 131, 0.65);
    cursor: pointer;
    padding: 8px;
    transition: color 0.2s;
    box-sizing: border-box;
}

.photo-panel-placeholder:hover {
    color: #CC9900;
}

.photo-panel-placeholder .dashicons {
    font-size: 28px;
    width: 28px;
    height: 28px;
    line-height: 28px;
    display: block;
    margin: 0;
    flex-shrink: 0;
}

.photo-panel-placeholder span:not(.dashicons) {
    font-family: 'Montserrat', sans-serif;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.2;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex-shrink: 1;
    min-width: 0;
}

/* Short panel — drop the text, keep only the icon so nothing clips the edges. */
@container photopanel (max-height: 90px) {
    .photo-panel-placeholder span:not(.dashicons) { display: none; }
    .photo-panel-placeholder .dashicons { font-size: 24px; width: 24px; height: 24px; line-height: 24px; }
}
/* Very short panel — shrink the icon too. */
@container photopanel (max-height: 60px) {
    .photo-panel-placeholder .dashicons { font-size: 18px; width: 18px; height: 18px; line-height: 18px; }
    .photo-panel-placeholder { padding: 4px; }
}

/* Photo panel header — compact */
.profile-widget[data-is-photo-panel="1"] .widget-drag-handle {
    padding: 4px 8px;
}

.profile-widget[data-is-photo-panel="1"] .widget-body {
    flex: 1;
    padding: 0;
    overflow: hidden;
}

/* Photo panel delete button (replaces minimize) */
.widget-delete-btn {
    background: none;
    border: none;
    color: #dc3545;
    font-size: 16px;
    cursor: pointer;
    padding: 0 4px;
    line-height: 1;
    opacity: 0.6;
    /* S187: same Seeko margin-bottom:1rem on <button> as the minimize control above — this
       one sits in the photo-panel header, which centres its children the same way, so it
       was riding equally high. Reset here rather than in a shared bump, so each control
       carries its own correction where its styling lives. */
    margin: 0;
    transition: opacity 0.2s;
}

.widget-delete-btn:hover {
    opacity: 1;
}

/* ============================================================
   Background Images — independent of glass effect
   Applied via data-bg attribute on .profile-grid, always active.
   ============================================================ */

.profile-grid[data-bg] {
    border-radius: 12px;
    padding: 10px;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    min-height: 800px;
}

/* Pre-made background textures (applied via data-bg attribute) */
.profile-grid[data-bg="mountains"] {
    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 600"><defs><linearGradient id="sky" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%23091428"/><stop offset="40%25" stop-color="%23142952"/><stop offset="100%25" stop-color="%231a3a6c"/></linearGradient><linearGradient id="mtn1" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%23162a50"/><stop offset="100%25" stop-color="%230a1a35"/></linearGradient><linearGradient id="mtn2" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%231e3460"/><stop offset="100%25" stop-color="%23122040"/></linearGradient></defs><rect fill="url(%23sky)" width="1200" height="600"/><circle cx="900" cy="120" r="40" fill="%23d4d4e8" opacity="0.15"/><polygon fill="url(%23mtn1)" points="0,600 200,280 400,380 600,220 800,340 1000,260 1200,320 1200,600"/><polygon fill="url(%23mtn2)" points="0,600 100,380 300,420 500,350 700,400 900,330 1100,380 1200,360 1200,600"/><polygon fill="%230d1830" points="0,600 150,450 350,480 550,440 750,470 950,430 1200,460 1200,600"/></svg>');
}

.profile-grid[data-bg="ocean"] {
    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 600"><defs><linearGradient id="osky" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%23a8d5e2"/><stop offset="50%25" stop-color="%236bb7c8"/><stop offset="100%25" stop-color="%23156b8a"/></linearGradient></defs><rect fill="url(%23osky)" width="1200" height="600"/><circle cx="200" cy="100" r="60" fill="%23fff8e1" opacity="0.4"/><ellipse cx="600" cy="500" rx="800" ry="200" fill="%231a6b8a" opacity="0.3"/><ellipse cx="600" cy="540" rx="700" ry="150" fill="%23145a75" opacity="0.4"/></svg>');
}

.profile-grid[data-bg="sunset"] {
    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 600"><defs><linearGradient id="ssky" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%231a0a2e"/><stop offset="30%25" stop-color="%234a1942"/><stop offset="60%25" stop-color="%23c94b4b"/><stop offset="85%25" stop-color="%23e8a87c"/><stop offset="100%25" stop-color="%23f7d794"/></linearGradient></defs><rect fill="url(%23ssky)" width="1200" height="600"/><circle cx="600" cy="420" r="70" fill="%23f7d794" opacity="0.6"/><polygon fill="%231a0a20" points="0,600 100,480 250,500 400,460 550,490 700,450 850,480 1000,440 1150,470 1200,450 1200,600"/></svg>');
}

.profile-grid[data-bg="forest"] {
    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 600"><defs><linearGradient id="fsky" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%23e8f5e9"/><stop offset="100%25" stop-color="%23a5d6a7"/></linearGradient></defs><rect fill="url(%23fsky)" width="1200" height="600"/><polygon fill="%232e7d32" opacity="0.3" points="0,600 60,350 120,600"/><polygon fill="%231b5e20" opacity="0.3" points="100,600 180,300 260,600"/><polygon fill="%232e7d32" opacity="0.25" points="220,600 310,320 400,600"/><polygon fill="%231b5e20" opacity="0.3" points="360,600 440,280 520,600"/><polygon fill="%232e7d32" opacity="0.25" points="480,600 560,310 640,600"/><polygon fill="%231b5e20" opacity="0.3" points="600,600 690,290 780,600"/><polygon fill="%232e7d32" opacity="0.25" points="740,600 820,300 900,600"/><polygon fill="%231b5e20" opacity="0.3" points="860,600 950,280 1040,600"/><polygon fill="%232e7d32" opacity="0.25" points="1000,600 1080,310 1160,600"/><rect fill="%231b5e20" opacity="0.15" y="500" width="1200" height="100"/></svg>');
}

.profile-grid[data-bg="city"] {
    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 600"><defs><linearGradient id="csky" x1="0" y1="0" x2="0" y2="1"><stop offset="0%25" stop-color="%23070b1a"/><stop offset="100%25" stop-color="%231a1a3e"/></linearGradient></defs><rect fill="url(%23csky)" width="1200" height="600"/><circle cx="100" cy="80" r="1.5" fill="%23fff" opacity="0.6"/><circle cx="300" cy="50" r="1" fill="%23fff" opacity="0.4"/><circle cx="500" cy="90" r="1.5" fill="%23fff" opacity="0.5"/><circle cx="700" cy="40" r="1" fill="%23fff" opacity="0.4"/><circle cx="900" cy="70" r="1.5" fill="%23fff" opacity="0.6"/><circle cx="1100" cy="55" r="1" fill="%23fff" opacity="0.3"/><rect fill="%230d0d2b" x="50" y="350" width="80" height="250"/><rect fill="%23111133" x="160" y="300" width="60" height="300"/><rect fill="%230d0d2b" x="260" y="380" width="100" height="220"/><rect fill="%23111133" x="400" y="280" width="70" height="320"/><rect fill="%230d0d2b" x="510" y="320" width="90" height="280"/><rect fill="%23111133" x="640" y="250" width="80" height="350"/><rect fill="%230d0d2b" x="760" y="340" width="70" height="260"/><rect fill="%23111133" x="870" y="290" width="100" height="310"/><rect fill="%230d0d2b" x="1010" y="360" width="80" height="240"/><rect fill="%23111133" x="1120" y="310" width="60" height="290"/></svg>');
}

/* Custom image background (set via inline style on .profile-grid) */
.profile-grid[data-bg="custom"] {
    /* background-image set via inline style */
}

/* ============================================================
   Glass Toggle Effect — frosted glassmorphism on widget cards
   Independent of background. Adds translucent blur to cards.
   ============================================================ */

.glass-on .profile-widget {
    background: rgba(255, 255, 255, 0.35);
    backdrop-filter: blur(16px) saturate(1.2);
    -webkit-backdrop-filter: blur(16px) saturate(1.2);
    border: 1px solid rgba(255, 255, 255, 0.4);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

.glass-on .widget-drag-handle {
    background: rgba(255, 255, 255, 0.25);
    border-bottom-color: rgba(255, 255, 255, 0.2);
}

/* S76 Rob: glass mode was washing body text out — the white halo text-shadow
   was combining with 0.7-opacity labels to make "MEMBERSHIP" and questionnaire
   text nearly invisible. Remove the halo; force brand navy + full opacity on
   the low-contrast labels so everything stays readable when glass is on. */
.glass-on .widget-body {
    /* intentionally no text-shadow */
}
.glass-on .tier-label,
.glass-on .quest-label {
    color: #031B83 !important;
    opacity: 1 !important;
}
.glass-on .quest-pct {
    color: #031B83 !important;
}

/* When glass is on WITHOUT a background, use subtle fallback tint */
.glass-on .profile-grid:not([data-bg]) {
    background: linear-gradient(135deg, rgba(200, 220, 255, 0.25) 0%, rgba(220, 230, 255, 0.15) 100%);
    border-radius: 12px;
    padding: 10px;
}

/* Glass text adjustments for readability on translucent cards */
.glass-on .widget-title {
    text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6);
}

/* When background is dark + glass is on, boost card visibility slightly */
.glass-on .profile-grid[data-bg="mountains"] .profile-widget,
.glass-on .profile-grid[data-bg="city"] .profile-widget,
.glass-on .profile-grid[data-bg="sunset"] .profile-widget {
    background: rgba(255, 255, 255, 0.2);
    border-color: rgba(255, 255, 255, 0.25);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

/* Dark background glass — light text for contrast */
.glass-on .profile-grid[data-bg="mountains"] .widget-title,
.glass-on .profile-grid[data-bg="city"] .widget-title,
.glass-on .profile-grid[data-bg="sunset"] .widget-title {
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.glass-on .profile-grid[data-bg="mountains"] .widget-drag-handle .dashicons,
.glass-on .profile-grid[data-bg="city"] .widget-drag-handle .dashicons,
.glass-on .profile-grid[data-bg="sunset"] .widget-drag-handle .dashicons {
    color: #f0c040;
}

.glass-on .profile-grid[data-bg="mountains"] .widget-body,
.glass-on .profile-grid[data-bg="city"] .widget-body,
.glass-on .profile-grid[data-bg="sunset"] .widget-body {
    color: rgba(255, 255, 255, 0.9);
}

/* ============================================================
   Icon Sidebar Tray (editor only)
   ============================================================ */

.widget-sidebar {
    width: 48px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px 4px;
    background: #f5f5f5;
    border-radius: 10px;
    border: 2px solid #CC9900;
    box-shadow: -2px 0 8px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.04);
    min-height: 200px;
    align-self: stretch;
}

/* S76-006: Custom wish-list fingers-crossed icon — dashicons has no
   fingers emoji, so we use unicode 🤞 via ::before with its own emoji
   font. Renders white background + gold icon per Rob. */
.icon-wishlist-fingers {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    color: #CC9900;
    border-radius: 50%;
    /* S78 Rob: fixed 20px to match dashicons alongside in sidenav. */
    width: 20px;
    height: 20px;
}
.icon-wishlist-fingers::before {
    content: "🤞";
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
    font-style: normal;
    font-weight: normal;
    font-size: 1em;
    line-height: 1;
}

/* S77 Interests = question mark emoji — same emoji-class pattern as wishlist.
   White bg + gold bubble. translateY(1px) nudge because emoji glyphs render
   upper in em-box (/da rule 23a).
   S158 29/07/26 (T594): `.icon-reputation-mouth` REMOVED from all three rules.
   The Reputation glyph is now an SVG megaphone emitted by
   profile_system_reputation_icon(), and this class was emitted by nothing at all
   anyway - the sidenav has taken its glyph from the $group2 array since S77, so
   these rules had been dead for months (D-243 principle 4: dead code is deleted,
   not hidden). `.icon-wishlist-fingers` IS still live (venue-organiser-widgets.php)
   and `.icon-interests-question` is left untouched as out of scope. */
.icon-wishlist-fingers,
.icon-interests-question {
    transform: translateY(1px);
}
.icon-interests-question {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    color: #CC9900;
    border-radius: 50%;
    /* S78 Rob: fixed even px (was 1.4em → 19.6px fractional on 14px base) so
       the bubble lines up pixel-perfectly with the 18px dashicons alongside
       them in the sidenav. Same treatment for wishlist-fingers below. */
    width: 20px;
    height: 20px;
}
.icon-interests-question::before {
    content: "❓";
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
    font-style: normal;
    font-weight: normal;
    font-size: 1em;
    line-height: 1;
}

.sidebar-icon {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: #f8f8f8;
    cursor: pointer;
    transition: all 0.2s ease;
    border: 1px solid transparent;
}

.sidebar-icon:hover {
    background: #CC9900;
    border-color: #b8860b;
}

.sidebar-icon .dashicons {
    font-size: 18px;
    width: 18px;
    height: 18px;
    color: var(--color-text-secondary, rgba(3,27,131,.75));   /* S199, Rob: no greys */
    transition: color 0.2s;
}

.sidebar-icon:hover .dashicons {
    color: #031B83;
}

/* ============================================================
   S185 Rob — Reputation WIDGET empty state, sized for a widget.
   `.rep-empty` in page-polish.css carries `padding: var(--sp-4xl) var(--sp-xl)`,
   which is right for the full-page Reputation TAB it also serves, but inside a
   grid widget it produced a 257px block holding a glyph and four words. Rob:
   "the amount of space the actual body of text takes up is massive... it can be
   what, a couple of lines tall."
   So this is scoped to the widget only and the tab keeps its generous spacing.
   Not a scope-bump over a broken rule: two genuinely different contexts.
   ============================================================ */
.profile-widget[data-widget-id="reputation"] .rep-empty {
    padding: 18px 16px;
    max-width: none;
}
.profile-widget[data-widget-id="reputation"] .rep-empty__glyph {
    margin-bottom: 10px;
}
.profile-widget[data-widget-id="reputation"] .rep-empty__title {
    margin-bottom: 0;
}

/* ============================================================
   S185 Rob — Height Pin lock toggle (first item in the rail).
   Not a widget spawner: it never adds anything to the grid, it flips
   whether the pin may be budged. It reuses `.sidebar-icon` for the
   48px gold-bordered white circle so it sits in the rail as one of the
   family, and only overrides what a <button> needs on top of a <div>.
   `margin: 0` is deliberate: Seeko's theme puts `margin-bottom: 18px`
   on bare <button> elements, which would break the rail's 6px gap and
   push every icon below it out of alignment (the S89 class of bug).
   ============================================================ */
/* The toggle's SIZE, COLOUR and LOCKED STATE are NOT set here. They live in the
   inline <style> block in profile-system.php §14 that defines the whole rail,
   because those rules are `!important` on an id-scoped selector and would beat
   anything written in this file. Putting half the styling here and half there is
   how the locked state came out white on the first attempt. Only the focus ring,
   which nothing else sets, stays in this file. */
.pin-lock-toggle:focus-visible {
    outline: 2px solid #031B83;
    outline-offset: 2px;
}

/* Shrink-to-sidebar animation clone */
/* S199 31/08/26: the shell that drag ghosts and minimise clones live in. It carries the
   editor wrapper's classes so wrapper-scoped rules reach the clones, and is pinned to the
   viewport with no pointer events and no max-width, so it can never add scroll or shift the
   page - the fault Rob hit as "the whole page shifts left and there's a grey bar down the
   right hand side". */
.uks-clone-layer {
    position: fixed !important;
    inset: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
    width: 100% !important;
    height: 100% !important;
    overflow: visible !important;
    pointer-events: none !important;
    background: none !important;
    z-index: 1000;
}
.widget-fly-clone {
    position: fixed;
    pointer-events: none;
    z-index: 2000;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
    transition: transform 0.4s ease-in-out, opacity 0.4s ease-in-out,
                width 0.4s ease-in-out, height 0.4s ease-in-out,
                left 0.4s ease-in-out, top 0.4s ease-in-out;
}

.widget-fly-clone.flying {
    opacity: 0.4;
}

/* ============================================================
   Widget Content Styles
   ============================================================ */

.widget-empty {
    color: #031B83;
    font-style: italic;
    text-align: center;
    padding: 16px 8px;
    margin: 0;
    font-weight: 500;
}
/* S77 Rob item 22: on glass mode the grey was invisible against the
   transparent sand backdrop. Navy with subtle text-shadow reads cleanly
   over any custom background. */
.profile-editor-wrapper.glass-on .widget-empty,
body.bp-user .profile-grid-public.glass-on .widget-empty {
    color: #031B83 !important;
    text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6);
}

/* Bio widget */
/* S185 21/08/26 Rob: "the layout ... is shit and bland and too close to the top
   border". The content had no spacing of its own and sat on `.widget-body`'s bare
   12px, so on the public profile it touched the card edge, and the details were a
   cramped 4px stack of small grey text under a big empty box.
   Centring the details against the avatar instead of top-aligning them stops the
   block reading as top-heavy, and the widened gap gives the avatar room to be the
   anchor of the card rather than something crammed into a corner. */
.widget-bio-content {
    display: flex;
    gap: 20px;
    align-items: center;
    padding: 6px 4px;
}

/* S199 31/08/26, Rob: "when you shrink the about me ... the sigil is now a vertically
   elongated oval. The sigil should never change shape."
   `.widget-bio-content` is a flex row, so `.bio-avatar` was a shrinkable flex item: the 80px
   was a starting width, not a floor, and the image squashed horizontally while its height held.
   Pinning the wrapper stops the flex algorithm touching it at all. The resize floor added in
   profile-grid.js is the other half - the widget can no longer get narrow enough to try. */
.bio-avatar {
    flex: 0 0 auto;
}
.bio-avatar img {
    border-radius: 50%;
    /* S199: 80px is the floor and the shape is locked square, so the circle can only ever get
       BIGGER with the card, never distort. Width and height use the same expression, which is
       what keeps it a circle at every size. */
    width: max(80px, 22cqw);
    height: max(80px, 22cqw);
    min-width: 80px;
    min-height: 80px;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}

/* S77 Rob item 23: Wish List as a grid of circular sigils, not a list of
   names. Each badge is a 60x60 circle with the target's logo/featured image.
   Hover reveals the name as a tooltip below; clicking goes to the target. */
.widget-wishlist-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
    gap: 12px;
    padding: 8px;
    justify-items: center;
}
.wishlist-sigil {
    position: relative;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    overflow: visible;
    border: 2px solid #CC9900;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none !important;
    transition: transform 0.15s ease, border-color 0.15s ease;
    flex-shrink: 0;
}
.wishlist-sigil img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}
.wishlist-sigil .dashicons {
    font-size: 28px;
    width: 28px;
    height: 28px;
    color: #CC9900;
}
.wishlist-sigil:hover {
    transform: scale(1.08);
    border-color: #031B83;
}
.wishlist-sigil-name {
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: #031B83;
    color: #CC9900;
    font-family: 'Montserrat', sans-serif;
    font-size: 11px;
    font-weight: 700;
    padding: 4px 8px;
    border-radius: 6px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
    z-index: 10;
}
.wishlist-sigil:hover .wishlist-sigil-name {
    opacity: 1;
}

.bio-details {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.bio-name {
    font-family: 'Montserrat', sans-serif;
    color: #031B83;
    /* S199: 20px floor, grows with the card. */
    font-size: max(20px, 5.6cqw);
    font-weight: 700;
    margin: 0;
    line-height: 1.2;
}

/* S185 Rob: the About Me card needs to breathe. `.widget-body`'s global 12px is
   right for dense widgets and far too tight for the one carrying the member's
   name, avatar and tier, so this is scoped to About Me alone and leaves every
   other widget's padding untouched. */
.profile-widget[data-widget-id="bio"] .widget-body,
.profile-widget-public[data-widget-id="bio"] .widget-body {
    padding: 20px 20px 18px;
}

.bio-gender,
.bio-joined {
    font-size: 13px;
    color: var(--color-text-secondary, rgba(3,27,131,.75));   /* S199, Rob: no greys */
}

/* S63 Phase 1c — bio-level pill (T455 C1-C4): per-tier tint, Admin exception (D089),
   16px radius (D090), Montserrat heading font (LB-024 on-brand). */
.bio-level {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: 'Montserrat', sans-serif;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 4px 12px 5px;
    border-radius: 9999px; /* pill — stays 9999 per D090 pill exception */
    margin-top: 4px;
    width: fit-content;
    line-height: 1;
    text-align: center;
    border: 0 none;
}

/* Per-tier tint + matching text + no border (B23/B24/B25 sign-off; canonical
   palette from BRAND_GUIDE.md §11 Membership Level Badges).
   Admin exception per D089 — solid green bg + navy text + navy border.
   Note: PHP profile-system.php:595 emits `badge-<level-lowercased>`.
   Note: page-polish.css §13.5 defines a DIFFERENT legacy palette for
   `#buddypress #members-list .member-card-level.level-*` (gold-family only).
   Those rules are scoped to #members-list so they do not collide with
   `.bio-level` on /profile/. */
.badge-free,       .bio-level.level-free       { background: rgba(107, 114, 128, 0.08); color: #6B7280; border: 0 none; }
.badge-standard,   .bio-level.level-standard   { background: rgba(3, 27, 131, 0.06);     color: #031B83; border: 0 none; }
.badge-premium,    .bio-level.level-premium    { background: rgba(204, 153, 0, 0.08);    color: #CC9900; border: 0 none; }
.badge-organiser,  .bio-level.level-organiser  { background: var(--color-success-bg);    color: var(--color-success); border: 0 none; }
.badge-venue,      .bio-level.level-venue      { background: rgba(111, 66, 193, 0.08);   color: #6f42c1; border: 0 none; }
.badge-admin,      .bio-level.level-admin      { background: rgb(74, 222, 128);          color: #031B83; border: 1px solid #031B83; }

/* Photos grid */
.widget-photos-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}

.photo-thumb {
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 4px;
}

.photo-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* BUG-17: Interest / music tags — compact branded pills (D055) */
.widget-interests-list,
.widget-music-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    line-height: 1.4;
}

/* AMENDMENT S58 2026-04-14: interest pills white bg + gold border + navy text (Rob 2026-04-14).
   S63 Phase 1c T455 C10: Montserrat font override (was inheriting Seeko Muli).
   S63 Phase 1c T455 C12: .interest-tag-personality visually distinct from generic .interest-tag
   (D055 invert — navy bg + gold text + gold border) to mark the primary personality indicator. */
.interest-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #ffffff !important;
    color: #031B83 !important;
    font-family: 'Montserrat', sans-serif !important;
    padding: 5px 12px;
    border-radius: 9999px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.2px;
    line-height: 1;
    border: 1.5px solid #CC9900 !important;
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Personality-primary pill — D055 invert for visual distinction (S63 Phase 1c C12). */
.interest-tag.interest-tag-personality,
span.interest-tag-personality {
    background: #031B83 !important;
    color: #CC9900 !important;
    border: 1.5px solid #031B83 !important;
}

/* .music-tag rule DELETED 06/09/26 (S210) on Rob's word: nothing in the codebase emits a
   music-tag element any more, so this was styling for a feature that no longer exists. */

/* BUG-17: Personality chip — visually distinct, leads the interests widget */
/* AMENDMENT S58 2026-04-14: unify to white bg + gold border + navy text (Rob 2026-04-14). */
.interest-tag-personality {
    background: #ffffff !important;
    color: #031B83 !important;
    border: 1.5px solid #CC9900 !important;
    padding: 5px 14px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-size: 11px;
}
.interest-tag-personality .interest-tag-emoji {
    font-size: 14px;
    line-height: 1;
}

/* Spotify embed + search — height left to default flow (Rob S79: do not
   shorten container; let iframe HTML height attribute govern). */
.widget-spotify-embed {
    margin-bottom: 8px;
    position: relative;
    line-height: 0;
}
.widget-spotify-embed iframe {
    border-radius: 8px;
    display: block;
    width: 100%;
    height: 100%;
}

/* S79 Rob — Quote widget ALWAYS chrome-strips on public; only the visible
   bubble shows, no widget rectangle ever. Bubble auto-sizes to content
   so the dead-space rule isn't violated even when the user has resized
   the widget bigger in customise. Bubble bg/text colour comes from CSS
   vars set by the colour popover (so changing "Body Background" paints
   the visible bubble — not the invisible widget-body wrapper). */
body.bp-user .profile-grid-public .profile-widget--quote-autofit,
body.bp-user .profile-grid-public .profile-widget--quote-autofit:hover,
body.bp-user .profile-grid-public .profile-widget--quote-autofit:focus-within {
    width: max-content !important;
    max-width: 100% !important;
    height: max-content !important;
    min-height: 0 !important;
    align-self: start !important;
    justify-self: start !important;
    background: transparent !important;
    border: 0 none !important;
    box-shadow: none !important;
    padding: 0 !important;
    overflow: visible !important;
}
body.bp-user .profile-grid-public .profile-widget--quote-autofit > .widget-header-public {
    display: none !important;
}
body.bp-user .profile-grid-public .profile-widget--quote-autofit > .widget-body {
    padding: 0 !important;
    height: auto !important;
    width: max-content !important;
    max-width: 100% !important;
    background: transparent !important;
    border: 0 none !important;
    /* S202 (VS4 task 46, cust-profile-quote): the public quote MEASURED ZERO WIDE for every
       member - 0px by 959px, the text wrapping one character per line - since S199 put
       `container-type: inline-size` on every .widget-body (the content-scaling work). A size
       container cannot resolve `max-content` from its own contents, so this body, and the
       autofit widget sized from it, collapsed to nothing. The same cause was found and fixed
       on the pickable pills in S199 (pickable-buttons.php, LB-337 / D-427's correction), and
       this is the same one-line remedy: the quote body is a plain block again, so max-content
       is the bubble's real width. Found by the viewer LOOK leg after two DOM reads had passed
       on the invisible element (R5b). */
    container-type: normal !important;
}
/* The quote bubble — the only visible element on public for a quote
   widget. Bubble bg and text colour read from CSS vars set by the colour
   popover (or default white if no popover colour saved). Rendered as a
   <div>, not <blockquote>, to sidestep the Seeko-parent
   `theme-dynamic.css` rule that paints a 4px left "eyebrow" on every
   blockquote site-wide. With the bubble being a <div>, no override is
   needed — it inherits normal widget rules. */
body.bp-user .profile-grid-public .profile-widget--quote-autofit .widget-quote,
.profile-widget[data-widget-id="quote"] .widget-quote {
    margin: 0;
    padding: 12px 18px;
    max-width: 360px;
    white-space: normal;
    word-break: break-word;
    background-color: var(--quote-bg-color, #FFFFFF);
    background-clip: padding-box;
    color: var(--quote-text-color, #031B83);
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
    font-style: italic;
    font-size: 15px;
    line-height: 1.45;
}

/* S77 Rob — chrome-free Spotify widget on public profiles. Looks like just
   the embedded player + the small login hint underneath. Mirrors the sigil /
   party widgets' chrome-strip pattern. Only the body and its content render —
   no header bar, no border, no card background, no shadow. Widget shrinks to
   content height (auto) so there's no empty whitespace below the hint. */
/* S79 Rob: chrome-strip needs (0,3,1)+ specificity to beat Seeko's
   `body.bp-user .profile-grid-public .profile-widget { border-style: solid
   !important }` rule. Mirrors the sigil chrome-strip specificity pattern. */
.profile-widget.profile-widget--spotify,
body.bp-user .profile-grid-public .profile-widget.profile-widget--spotify,
body .profile-grid-public .profile-widget.profile-widget--spotify {
    background: transparent !important;
    border: 0 none !important;
    border-width: 0 !important;
    border-style: none !important;
    box-shadow: none !important;
    padding: 0 !important;
    align-self: start !important;
    height: auto !important;
    overflow: visible !important;
}
.profile-widget--spotify .widget-drag-handle,
.profile-widget--spotify .widget-header-public {
    display: none !important;
}
body.bp-user .profile-grid-public .profile-widget.profile-widget--spotify .widget-body,
.profile-widget--spotify .widget-body {
    padding: 0 !important;
    background: transparent !important;
    border: 0 none !important;
    overflow: visible !important;
    height: auto !important;
}
.profile-widget--spotify .widget-spotify-embed {
    margin: 0 !important;
}
.profile-widget--spotify .spotify-login-hint {
    /* S77 Rob: hint replaced by a hover-tooltip "i" trigger on the embed.
       Hide the legacy paragraph entirely. */
    display: none !important;
}

/* S79 Rob: stripped all Spotify info-button CSS. Reverted to baseline —
   just the iframe, no overlay button. Will rebuild from clean state. */
.spotify-login-hint {
    font-size: 10px;
    color: #031B83;
    text-align: center;
    margin: 4px 0 0;
    font-style: italic;
    line-height: 1.3;
}

/* S77 — Spotify brand mark for the Music widget's sidebar icon. Official
   green (#1ED760) per Spotify branding guidelines for integrations.
   Sized to match the dashicons-format-audio it replaces (22px square inside
   the 48px circular sidebar button). */
.icon-spotify {
    display: inline-block;
    width: 22px;
    height: 22px;
    background-image: url('../images/spotify-icon.svg');
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
    vertical-align: middle;
    flex-shrink: 0;
}

/* S79 Rob: customise-mode music widget — shrinks to content (no iframe
   on customise, just controls) and the controls inside have symmetric
   spacing. flex column with `gap` gives equal vertical rhythm; height:
   auto on the widget shells stop the grid cell painting empty space
   below the visible controls. */
.profile-widget[data-widget-id="music"]:not(.profile-widget-public) {
    height: auto !important;
    min-height: 0 !important;
    align-self: start !important;
}
.profile-widget[data-widget-id="music"]:not(.profile-widget-public) > .widget-body {
    /* S79 Rob: padding + gap unified at 14px so all 3 vertical spacings
       (above input, between input and selected track, below track) are
       visually equal. */
    padding: 14px !important;
    height: auto !important;
    overflow: visible !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 14px !important;
}
/* Info popup is a sibling of .spotify-search-ui — no own margin so
   the parent flex gap controls all spacing. */
.profile-widget[data-widget-id="music"] .spotify-info-popup {
    margin: 0 !important;
}

/* Spotify search UI (editor only). Single flex column with consistent
   12px gap between every direct child — search bar, results, selected
   track, admin OAuth block. No more ad-hoc margin-top on individual
   children, no margin-bottom on the wrapper. */
.spotify-search-ui {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin: 0;
}
.spotify-search-bar {
    position: relative;
}
.spotify-search-input {
    width: 100%;
    padding: 6px 10px;
    /* S79 Rob: kill Seeko's `input[type=text] { margin-bottom: 1rem }` —
       it was adding 14-16px below the input ON TOP of the flex parent's
       14px gap, doubling the visible distance to the track banner. */
    margin: 0 !important;
    /* S198 30/08/26, Rob: the field and its placeholder were stock grey. Gold hairline,
       navy text, and the placeholder navy at reduced opacity rather than a grey. */
    /* !important because Seeko's own input rule is later in source order and was
       repainting the border grey at equal specificity. */
    border: 1px solid #CC9900 !important;
    border-radius: 8px !important;
    font-size: 12px;
    font-family: 'Nunito Sans', sans-serif;
    color: #031B83 !important;
    background: #fff !important;
    outline: none;
    box-sizing: border-box;
}
.spotify-search-input::placeholder {
    /* S199 31/08/26, Rob: "Spotify is still grey ... you need to verify visually yourself."
       He was right twice over. Lifting the value was not enough: this rule carried NO
       `!important`, so Seeko's own input-placeholder rule beat it and the text kept painting
       rgb(154,147,131), a warm grey. Proven by forcing red through an injected `!important`
       rule - the ink went to rgb(243,1,6), which showed the pseudo-element was reachable and
       that weight, not the selector, was the problem. The three declarations on the input
       itself directly above already carry `!important` for exactly this reason. */
    color: rgba(3, 27, 131, 0.65) !important;
    opacity: 1 !important;
}
.spotify-search-input:focus {
    border-color: #CC9900;
    box-shadow: 0 0 0 2px rgba(204, 153, 0, 0.15);
}
.spotify-results {
    max-height: 200px;
    overflow-y: auto;
    margin-top: 4px;
}
/* S79 Rob: hide empty results so the parent flex `gap` doesn't apply on
   either side of an empty zero-height div — without this, the gap above
   input and below track was 14px while the gap between them was 28px
   (two flex gaps with an invisible 0-height element in the middle). */
.spotify-results:empty {
    display: none !important;
    margin: 0 !important;
}
.spotify-result {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s;
}
.spotify-result:hover {
    background: #f0f7ff;
}
.spotify-result-art {
    width: 36px;
    height: 36px;
    border-radius: 4px;
    flex-shrink: 0;
    object-fit: cover;
}
.spotify-result-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
}
.spotify-result-name {
    font-size: 12px;
    font-weight: 600;
    color: #031B83;   /* S199, Rob: no greys */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spotify-result-artist {
    font-size: 11px;
    color: #888;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spotify-searching,
.spotify-no-results,
.spotify-not-configured {
    font-size: 11px;
    color: var(--color-text-muted, rgba(3,27,131,.55));      /* S199, Rob: no greys */
    text-align: center;
    padding: 8px;
    font-style: italic;
}

/* Current selected track — gap handled by parent .spotify-search-ui flex
   gap, no margin-top needed. */
.spotify-current-track {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: #f0faf0;
    border: 1px solid #c3e6c3;
    border-radius: 6px;
    padding: 6px 8px;
    margin: 0;
}
.spotify-current-info {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    overflow: hidden;
}
.spotify-current-art {
    width: 32px;
    height: 32px;
    border-radius: 4px;
    flex-shrink: 0;
    object-fit: cover;
}
.spotify-current-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.spotify-current-name {
    font-size: 12px;
    font-weight: 600;
    color: #031B83;   /* S199, Rob: no greys */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spotify-current-artist {
    font-size: 11px;
    color: var(--color-text-secondary, rgba(3,27,131,.75));   /* S199, Rob: no greys */
}
.spotify-clear-btn {
    background: none;
    border: none;
    font-size: 18px;
    color: #c00;
    cursor: pointer;
    padding: 0 4px;
    line-height: 1;
    flex-shrink: 0;
}
.spotify-clear-btn:hover {
    color: #900;
}

/* Events list */
.widget-events-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.widget-events-list li {
    display: flex;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid #f0f0f0;
    align-items: baseline;
}

.widget-events-list li:last-child {
    border-bottom: none;
}

/* S181 (18/08/26, D-389): the owner's per-event Hide/Show control on the Upcoming Events widget,
   and the muted look of a row the owner has hidden from everyone else. First pass; Rob's sweep. */
.widget-events-list .widget-event-vis {
    margin-left: auto;
    font-size: 11px;
    padding: 3px 8px;
    white-space: nowrap;
}
.widget-events-list .widget-event-row--hidden .event-title,
.widget-events-list .widget-event-row--hidden .event-date {
    opacity: 0.55;
}

.event-date {
    font-size: 12px;
    font-weight: 600;
    color: #CC9900;
    white-space: nowrap;
    min-width: 70px;
}

.event-title {
    font-size: 13px;
    color: #031B83;   /* S199, Rob: no greys */
}

/* Attendance stats */
.widget-attendance-stats {
    display: flex;
    justify-content: space-around;
    text-align: center;
    padding: 8px 0;
    /* S187: three stat items in a no-gap, no-wrap row could not fit a narrow widget.
       Measured on a 5-column (196px) Attendance widget: the labels ran together with a
       0px gap between all three and "Total RSVPs" was squeezed to 35px and pushed 4px
       past the widget's own right border. There IS a column rule for this further down,
       but it is behind a VIEWPORT media query, and the widget is narrow because of its
       GRID SPAN, not because the screen is small — so on a 1280 desktop it never fired.
       NOT solved with flex-wrap: tried, and it put each stat on its own row, making the
       block 223px tall inside a 113px body — a vertical overflow worse than the horizontal
       one it cured. The three stay on one row and shrink instead. */
    gap: 4px 8px;
}

.stat-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    /* A flex item will not shrink below its content's intrinsic width without this, which
       is what forced the overflow rather than a wrap. */
    min-width: 0;
}

.stat-number {
    font-family: 'Montserrat', sans-serif;
    /* S199: 28px is the spawn size and stays the floor; 9cqw is roughly that at the widget's
       own default width, so it grows from there and never shrinks below it. */
    font-size: max(28px, 9cqw);
    font-weight: 700;
    color: #031B83;
    line-height: 1.1;
}

.stat-label {
    /* S199: same pattern as .stat-number - 11px floor, grows with the widget. */
    font-size: max(11px, 3.4cqw);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    /* S187: was `#999`, a hardcoded grey banned outright by BRAND_GUIDE §1.6.1 and the
       standing never-grey-text rule. The token is navy at 55%, which is the canonical
       muted colour for exactly this kind of meta label. */
    color: var(--color-text-muted);
    font-weight: 600;
    white-space: nowrap;
}

/* S187: "UNCONFIRMED" is a single unbreakable 84px word and its column is only ~57px wide
   on a 5-column Attendance widget, so at 11px it escaped the widget's right border. Two
   earlier attempts were worse and are recorded so they are not retried: flex-wrap put each
   stat on its own row and made the block 223px tall inside a 113px body, and
   overflow-wrap:anywhere kept it inside but broke the words as "UNCONFI / RMED".
   Dropping the type at narrow widths keeps all three on one line, whole, inside the widget
   and with no scrollbar. This is a CONTAINER query, not a media query — the widget is
   narrow because of its grid span, not because the screen is small, which is exactly why
   the existing viewport rule further down never fired on a 1280 desktop. Same pattern as
   event-page.css `@container vp`.
   ⚠️ Whether this widget should simply be WIDER by default, or carry shorter labels, is a
   design decision flagged to Rob — this rule stops it rendering broken in the meantime. */
.profile-widget[data-widget-id="attendance"] .widget-body {
    container-type: inline-size;
}

@container (max-width: 240px) {
    .stat-label {
        font-size: 9px;
        letter-spacing: 0;
    }
    .stat-number {
        font-size: 22px;
    }
}

/* Reputation badges */
.widget-reputation-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.reputation-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #f0f7ff;
    border: 1px solid #d0e3f7;
    padding: 4px 10px;
    border-radius: 16px;
    font-size: 12px;
}

.badge-label {
    color: #031B83;
    font-weight: 600;
}

.badge-count {
    color: var(--color-text-muted, rgba(3,27,131,.55));      /* S199, Rob: no greys */
    font-size: 11px;
}

/* Social links */
.widget-social-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.social-link {
    display: inline-block;
    padding: 6px 14px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    background: #f0f0f0;
    color: #031B83;   /* S199, Rob: no greys */
    transition: background 0.2s;
}

.social-link:hover {
    background: #e0e0e0;
    color: #031B83;   /* S199, Rob: no greys */
    text-decoration: none;
}

/* Wish list */
.widget-wishlist {
    list-style: none;
    padding: 0;
    margin: 0;
}

.widget-wishlist li {
    padding: 5px 0;
    border-bottom: 1px solid #f0f0f0;
    font-size: 13px;
}

.widget-wishlist li:last-child {
    border-bottom: none;
}

.wishlist-type {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    color: #CC9900;
    margin-right: 6px;
}

/* 14.10 Favourite Venues & Organisers widgets */
/* 14.10.1 Widget container — vertical stack */
.widget-favourites {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
/* end of 14.10.1 */
/* 14.10.2 Card row — flex */
.fav-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px;
    border-radius: var(--radius-md, 8px);
    text-decoration: none;
    transition: background 150ms;
    color: inherit;
}
/* end of 14.10.2 */
/* 14.10.3 Card hover — raised bg */
.fav-card:hover {
    background: var(--color-surface-raised, #F8F7F4);
}
/* end of 14.10.3 */
/* 14.10.4 Card sigil — square thumbnail with gold border */
.fav-card-sigil {
    width: 42px;
    height: 42px;
    border-radius: var(--radius-md, 8px);
    object-fit: cover;
    flex-shrink: 0;
    border: 2px solid var(--color-gold, #CC9900);
}
/* end of 14.10.4 */
/* 14.10.5 Round sigil variant — circular */
.fav-card-sigil-round {
    border-radius: 50%;
}
/* end of 14.10.5 */
/* 14.10.6 Placeholder sigil — sunken bg */
.fav-card-sigil-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-surface-sunken, #F3F2EF);
    color: var(--color-text-muted, #9B9BAB);
}
/* end of 14.10.6 */
/* 14.10.7 Placeholder icon */
.fav-card-sigil-placeholder .dashicons {
    font-size: 20px;
    width: 20px;
    height: 20px;
}
/* end of 14.10.7 */
/* 14.10.8 Card info column */
.fav-card-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
/* end of 14.10.8 */
/* 14.10.9 Card name — Montserrat navy */
.fav-card-name {
    font-family: var(--font-heading, 'Montserrat', sans-serif);
    font-weight: 600;
    font-size: 13px;
    color: var(--color-navy, #031B83);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* end of 14.10.9 */
/* 14.10.10 Card detail — secondary text */
.fav-card-detail {
    font-size: 11px;
    color: var(--color-text-secondary, #6B6B7B);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* end of 14.10.10 */
/* 14.10.11 Manage button — corner overlay, hover-revealed */
.fav-manage-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    background: var(--color-surface-raised, #F8F7F4);
    border: 1px solid var(--color-border, rgba(26,26,46,0.08));
    border-radius: var(--radius-sm, 4px);
    padding: 4px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 150ms;
}
/* end of 14.10.11 */
/* 14.10.12 Manage button reveal on widget hover */
.profile-widget:hover .fav-manage-btn,
.profile-widget-public:hover .fav-manage-btn {
    opacity: 1;
}
/* end of 14.10.12 */
/* 14.10.13 Manage button icon */
.fav-manage-btn .dashicons {
    font-size: 14px;
    width: 14px;
    height: 14px;
    color: var(--color-text-muted, #9B9BAB);
}
/* end of 14.10.13 */
/* end of 14.10 */

/* Quote — legacy fallback rule (the §2.x autofit rule above takes
   precedence on the widget render path). Gold eyebrow removed
   per Rob 11/05/26. */
.widget-quote {
    font-style: italic;
    color: #555;
    padding: 8px 16px;
    margin: 8px 0;
    font-size: 15px;
    line-height: 1.5;
}

/* Membership */
.widget-membership-info {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 8px 0;
}

.membership-tier {
    text-align: center;
    padding: 12px;
    border-radius: 8px;
}

.tier-label {
    display: block;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1px;
    opacity: 0.7;
    margin-bottom: 4px;
}

.tier-name {
    display: block;
    font-family: 'Montserrat', sans-serif;
    font-size: 20px;
    font-weight: 700;
}

.membership-questionnaire {
    display: flex;
    align-items: center;
    gap: 10px;
}

.quest-label {
    font-size: 12px;
    color: #031B83; /* brand navy (Rob, 25/08/26: the grey read as off-brand black on the card) */
    white-space: nowrap;
}

.quest-bar {
    flex: 1;
    height: 8px;
    background: #f0f0f0;
    border-radius: 4px;
    overflow: hidden;
}

.quest-fill {
    height: 100%;
    background: linear-gradient(90deg, #CC9900, #b8860b);
    border-radius: 4px;
    transition: width 0.3s ease;
}

.quest-pct {
    font-size: 12px;
    font-weight: 600;
    color: #CC9900;
    min-width: 32px;
}

/* The profile-card instance (questionnaire-system 6.2.7 emits .pf-public__quest above the
   .pf-public card): match the card column exactly - the same 720px cap and 20px side margins -
   so the label, the bar and the cards below read as one neat column (Rob, 25/08/26; measured
   before and after, strip 253-1013 vs cards 273-993 at 1280). This class was the template's own
   hook and had no rules anywhere until now. */
.membership-questionnaire.pf-public__quest {
    max-width: 720px;
    margin: 0 20px;
}

/* ============================================================
   Public Profile — read-only view
   ============================================================ */

.profile-public-wrapper {
    max-width: 100%;
    margin: 0 auto;
    position: relative;
}

.profile-grid-public .profile-widget {
    cursor: default;
}

.profile-grid-public .widget-drag-handle {
    cursor: default;
}

.profile-grid-public .resize-handle,
.profile-grid-public .drag-grip,
.profile-grid-public .widget-minimize-btn,
.profile-grid-public .widget-delete-btn,
.profile-grid-public .color-swatch-btn {
    display: none;
}

/* Public photo panels — borderless, just the image */
.photo-panel-public {
    overflow: hidden;
}

.photo-panel-public .widget-body {
    padding: 0;
    flex: 1;
}

.photo-panel-public .widget-drag-handle {
    display: none;
}

/* "Customise Your Profile" CTA button on own public profile —
   positioned absolute so it doesn't create a grid row */
.profile-customise-cta {
    position: absolute;
    top: 0;
    right: 10px;
    z-index: 10;
    margin: 0;
    padding: 0;
}

.btn-customise-profile {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: linear-gradient(to bottom, #d9a400 0%, #b8860b 100%);
    color: #031B83 !important;
    padding: 10px 22px;
    border-radius: 6px;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 14px;
    text-decoration: none !important;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(184, 134, 11, 0.2);
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    transform: translateY(0);
}

/* AMENDMENT S47: D055 — gold bg = blue text on hover */
.btn-customise-profile:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15), 0 8px 16px rgba(184, 134, 11, 0.25);
    color: #031B83 !important;
}

.btn-customise-profile:active {
    transform: translateY(1px);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(0, 0, 0, 0.1);
}

.btn-customise-profile .dashicons {
    font-size: 18px;
    width: 18px;
    height: 18px;
}

/* ============================================================
   Responsive — hide editor on phones, single column public view
   ============================================================ */

/* Phone: hide the entire editor, show a message instead */
@media (max-width: 767px) {
    /* Hide the Customise (My Profile) tab on mobile — editor doesn't work on small screens */
    #customise-personal-li {
        display: none !important;
    }

    /* Hide editor chrome, show message */
    .profile-editor-wrapper .editor-toolbar,
    .profile-editor-wrapper .editor-hint,
    .profile-editor-wrapper .bg-picker,
    .profile-editor-wrapper .editor-content,
    .profile-editor-wrapper .save-status-row {
        display: none !important;
    }

    .profile-editor-wrapper::before {
        content: 'Profile customisation is available on desktop or tablet only.';
        display: block;
        text-align: center;
        padding: 20px;
        color: #031B83; /* S82 Rob — was #999 grey, brand says navy on copy */
        font-family: 'Montserrat', sans-serif; /* intentional: mobile-only pseudo-element (no base ::before exists) — Phase 2a S65 */
        font-size: 13px;
        font-style: italic;
        line-height: 1.5;
    }

    /* S82 — kill the dashboard "scroll →" hint on the customise page at mobile.
       Customise itself is blocked at this width (the .profile-editor-wrapper::before
       above shows the explanation), so the sidenav-scroll affordance is meaningless. */
    body.profile-editor-active #item-body .col-inner::before {
        display: none !important;
        content: none !important;
    }

    /* Hide "Customise Your Profile" CTA on mobile — editor doesn't work on phones */
    .profile-customise-cta,
    div.profile-customise-cta,
    body .profile-customise-cta,
    body.profile-public-active .profile-customise-cta,
    .btn-customise-profile {
        display: none !important;
    }

    /* Public profile: single column on phones — flexbox for auto-height stacking */
    .profile-public-wrapper {
        max-width: 100% !important;
        padding: 0 16px !important;
        overflow-x: hidden;
        box-sizing: border-box;
    }

    /* Keep all content within viewport on mobile */
    body.profile-public-active .bp-member-layout > .container,
    body.profile-dashboard-active .bp-member-layout > .container {
        max-width: 100% !important;
        padding: 0 !important;
        overflow-x: hidden;
    }
    body.profile-public-active .row.sidebar-single,
    body.profile-dashboard-active .row,
    body.profile-dashboard-active #item-body,
    body.profile-public-active #item-body,
    body.profile-dashboard-active #item-body .container,
    body.profile-public-active #item-body .container,
    body.profile-dashboard-active #item-body .col-inner,
    body.profile-public-active #item-body .col-inner {
        overflow-x: hidden;
        max-width: 100%;
    }
    /* Kill negative margins that push content beyond viewport on mobile */
    #item-body {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    #item-body > .container {
        padding-left: 12px !important;
        padding-right: 12px !important;
    }

    /* S108 11/06/26 — KEEP the grid intact at narrow viewports.
       Previously this block converted .profile-grid-public to flex-column,
       which threw away every widget's saved grid-column/grid-row span — so
       saved customise dimensions were lost and sigil/party widgets (whose
       images use container-query units min(100cqw, 100cqh)) collapsed to 0
       because their parent had no defined height in flex-column.
       The grid honours the saved w/h and scales proportionally with viewport
       width — exactly what the customise workspace stores. */
    .profile-grid-public {
        min-height: auto !important;
    }

    .profile-grid-public .profile-widget-public {
        min-height: auto !important;
        overflow: visible !important;
    }

    .profile-grid-public .profile-widget-public .widget-body {
        overflow: visible !important;
    }

    .widget-bio-content {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .widget-attendance-stats {
        flex-direction: column;
        gap: 12px;
    }

    .widget-photos-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Tablet: editor works but in compact mode */
@media (min-width: 768px) and (max-width: 1024px) {
    .editor-toolbar {
        flex-wrap: wrap;
    }
}


/* ============================================================================
   15. SECTION: Dashboard Layout (customise page only — see ARCHITECTURE NOTE)
   ============================================================================
   ARCHITECTURE NOTE (S89, 10/05/26):
   The OLD layout where .col-inner was a 2-column CSS grid (sidenav in column 1,
   workspace content in column 2) has been retired for every sidenav-driven page.
   Every sidenav page (account, attendance, invites, messages, settings, etc.)
   now uses the design-agent's .app shell instead — see page-polish.css §42.0.

   Remaining rules in §15 cover the CUSTOMISE PAGE ONLY (`/customise/`), which is
   the widget editor and never appears in the sidenav. Customise has its own
   layout where .col-inner is `display: block` and content is the
   `.profile-editor-wrapper`. Rules scoped to `body.profile-dashboard-active.profile-editor-active`
   are customise-only.

   Inert rules (`.dashboard-sidenav`, `.sidenav-item`, `.sidenav-label`,
   `.sidenav-badge`) below also pre-date the new BEM markup. The new sidenav
   emitted by profile_system_open_app_shell() uses BEM classes (.sidenav,
   .sidenav__item, etc.) styled in page-polish.css §41. The legacy classes
   are kept as dead code for now; they don't match anything in the live DOM.
   ============================================================================ */

/* 15.1 (REMOVED) — Legacy .col-inner grid (sidenav col 1 + content col 2).
   Retired in S89; .app handles its own internal grid. See page-polish.css
   §42.0.1 for the .app rule. */

/* 15.2 Side nav */
/* 15.2.1 Sidenav rail — sticky vertical, gold border, white bg */
.dashboard-sidenav {
    grid-row: 1 / span 50;
    grid-column: 1;
    position: sticky;
    top: 80px;
    align-self: start;
    max-height: calc(100vh - 100px);
    overflow-y: auto;
    padding: var(--space-md, 12px) 0 var(--space-lg, 16px) 0;
    /* S67 Phase 9 sidenav-brand fix (Rob 2026-04-18):
       white bg, navy text (on items), gold border — on-brand across all platforms. */
    border: 2px solid var(--color-gold, #CC9900);
    border-radius: var(--radius-lg, 12px);
    background: #FFFFFF;
}
/* end of 15.2.1 */

/* 15.2.2 Sidenav item — flex row, navy text */
.sidenav-item {
    display: flex;
    align-items: center;
    gap: var(--space-md, 12px);
    padding: var(--space-md, 12px) var(--space-xl, 24px) var(--space-md, 12px) 24px;
    /* S67 Phase 9 sidenav-brand fix: navy text on all platforms per Rob's 2026-04-18 directive */
    color: var(--color-navy, #031B83);
    text-decoration: none;
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: var(--text-sm, 0.875rem);
    font-weight: 500;
    line-height: 1.4;
    border-left: 4px solid transparent;
    transition: all var(--duration-fast, 150ms) var(--ease-out, cubic-bezier(0.25,1,0.5,1));
}
/* end of 15.2.2 */

/* 15.2.3 Sidenav item hover — raised bg */
.sidenav-item:hover {
    color: var(--color-text, #1A1A2E);
    background: var(--color-surface-raised, #F8F7F4);
    text-decoration: none;
}
/* end of 15.2.3 */

/* 15.2.4 Active item — bold navy + gold left border */
.sidenav-item-active {
    color: var(--color-navy, #031B83);
    font-weight: 700;
    border-left-color: var(--color-gold, #CC9900);
    background: var(--color-surface-raised, #F8F7F4);
}
/* end of 15.2.4 */

/* 15.2.5 Sidenav item icon */
.sidenav-item .dashicons {
    font-size: 18px;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}
/* end of 15.2.5 */

/* 15.2.6 Sidenav label — flex grow */
.sidenav-label {
    flex: 1;
}
/* end of 15.2.6 */

/* 15.2.7 Sidenav badge — pill */
.sidenav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: var(--radius-pill, 9999px);
    background: #FFFBE6; /* S207 05/09/26: was a non-brand cream. BRAND_GUIDE (LOCKED) makes #FFFBE6 the one brand cream, #FFF5CC hover only. */ /* Superseded by D-181's green tick, so this paints nothing today. */
    color: var(--color-navy, #031B83);
    border: 1px solid var(--color-gold, #CC9900);
    border-bottom-width: 2px;
    font-size: 11px;
    font-weight: 700;
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    box-shadow: none;
}
/* end of 15.2.7 */

/* 15.2.9 Protect <style>, <script>, and screen-reader elements from wildcard selectors */
#item-body style,
#item-body script,
#item-body .bp-screen-reader-text {
    display: none !important;
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    width: 0 !important;
    height: 0 !important;
    overflow: hidden !important;
}

/* 15.3 (REMOVED) — Legacy workspace-content positioning rules.
   Set padding/grid-column:2/display:flex on every direct child of .col-inner
   except the customise-specific elements. With the new .app shell, the workspace
   IS .app and handles its own content layout. Retired in S89. */
/* 15.3.4 D049 — common workspace wrapper widths so max-width/margin:auto children still centre inside the flex column */
body.profile-dashboard-active .suggestions-container,
body.profile-dashboard-active .questionnaire-complete-panel,
body.profile-dashboard-active .workspace-content {
    width: 100%;
    margin-top: 0;
}
/* Questionnaire CTA banner — JS sets dynamic negative margin based on identity bar height */
/* NOTE (S135, T-S135-003): this z-index is overridden by an inline style set in
   profile_system_position_cta_banner() (profile-system.php §1.4), and raising it
   does not help anyway - the banner is trapped in an ancestor stacking context
   (.container, z-index 3) below .col-header (z-index 4), so the identity bar always
   paints over the banner's "Back to Summary" link. Logged for Rob, not patched here. */
body.profile-dashboard-active .cta-banner {
    position: relative;
    z-index: 2;
}
/* 15.3a Customise editor wrapper — only fires on customise page (where
   .profile-editor-wrapper exists). Now scoped to .profile-editor-active to make
   that explicit. */
body.profile-dashboard-active.profile-editor-active #item-body .col-inner > .profile-editor-wrapper {
    min-width: 0;
}

/* 15.4 Break editor out of dashboard grid — hide sidenav on editor page */
/* 15.4.1 Editor col-inner — block layout (no grid) */
body.profile-dashboard-active.profile-editor-active #item-body .col-inner {
    display: block;
}
/* end of 15.4.1 */
/* 15.4.2 Hide sidenav on editor */
body.profile-dashboard-active.profile-editor-active .dashboard-sidenav {
    display: none;
}
/* end of 15.4.2 */

/* 15.5 Dashboard responsive — tablet: icon-only sidebar */
@media (min-width: 768px) and (max-width: 1023px) {
    /* 15.5.1 (REMOVED) — Legacy narrow grid (48px collapsed sidebar col). Retired S89. */

    /* 15.5.2 Sidenav — tighter padding */
    .dashboard-sidenav {
        padding: var(--space-sm, 8px) 0;
    }
    /* end of 15.5.2 */

    /* 15.5.3 Sidenav item — icon-centred, thicker border */
    .sidenav-item {
        padding: var(--space-md, 12px);
        justify-content: center;
        /* S78 Rob: restored to 4px (was 3px) so the compact sidenav's inner
           width (48 − 4 border − 24 padding = 20px) exactly matches the
           20px icon → pixel-perfect horizontal centering, no "1px off". */
        border-left-width: 4px;
    }
    /* end of 15.5.3 */

    /* 15.5.4 Sidenav label — hidden */
    .sidenav-label {
        display: none;
    }
    /* end of 15.5.4 */

    /* 15.5.5 Sidenav item icon — larger */
    .sidenav-item .dashicons {
        font-size: 20px;
        width: 20px;
        height: 20px;
    }
    /* end of 15.5.5 */

    /* 15.5.6 (REMOVED S89) — Legacy absolute-overlay sidenav badge for the
       768–1023 compact-sidebar layout. Caused the new BEM `.sidenav__badge`
       to render as a top-right corner dot instead of inline next to the
       label at that breakpoint. */
    /* 15.5.7 (REMOVED S89) — Legacy relative-anchor on .sidenav-item paired
       with the deleted absolute badge above. */
}

/* 15.6 Dashboard responsive — mobile: horizontal pill bar */
@media (max-width: 767px) {
    /* 15.6.0 Full-width mobile content — zero ALL Bootstrap padding/margin in the nesting chain.
       Without this: col-12(15) + container(12) + col-12(15) + col-12(15) + row(-15) = 42px per side
       giving only 261px of 360px viewport for content.
       With this: all zeroed, col-inner gets full viewport width, then its own padding creates margins. */
    /* 15.6.0.2 Outer .row — kill horizontal margin */
    /* Outer chain: bp-member-layout > container > row > col-12 */
    body.profile-dashboard-active .bp-member-layout > .container > .row {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    /* end of 15.6.0.2 */
    /* 15.6.0.3 Outer .col-12 — kill horizontal padding */
    body.profile-dashboard-active .bp-member-layout > .container > .row > .col-12 {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
    /* end of 15.6.0.3 */
    /* 15.6.0.4 Inner #item-body container — kill horizontal padding */
    /* Inner chain: #item-body > container > row > col-12 */
    body.profile-dashboard-active #item-body > .container {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
    /* end of 15.6.0.4 */
    /* 15.6.0.5 Inner .row — kill horizontal margin */
    body.profile-dashboard-active #item-body > .container > .row {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    /* end of 15.6.0.5 */
    /* 15.6.0.6 Inner .col-12 — kill horizontal padding */
    body.profile-dashboard-active #item-body > .container > .row > .col-12 {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
    /* end of 15.6.0.6 */
    /* 15.6.0.7 (REMOVED) — Legacy narrow flex column on .col-inner. Retired S89.
       The new .app shell handles its own narrow-width layout via @container vp queries. */

    /* 15.6.0.1 Long text wrapping — prevent email addresses, URLs etc overflowing cards */
    body.profile-dashboard-active #item-body .col-inner,
    body.profile-dashboard-active #item-body .col-inner * {
        word-break: break-word;
        overflow-wrap: break-word;
    }

    /* 15.6.1 T288+T293: Sidenav card — gold border, drop shadow, horizontal pill bar
       S67 Phase 9 fix: justify-content changed from center to flex-start. With overflow-x
       scrolling and items wider than container, "center" put the scroll position at the
       middle of the list so members opened the page seeing "Notifications"/"Reputation"
       (around item 7-8) instead of Dashboard. flex-start shows Dashboard first on load. */
    /* 15.6.1.1 Sidenav card — flex pill bar with gold border + shadow */
    .dashboard-sidenav {
        position: relative;
        top: auto;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        gap: var(--space-sm, 8px);
        padding: var(--space-md, 12px) var(--space-lg, 16px);
        max-height: none;
        scrollbar-width: none;
        white-space: nowrap;
        flex-wrap: nowrap;
        width: 100%;
        left: auto;
        transform: none;
        margin-left: 0;
        margin-right: 0;
        box-sizing: border-box;
        /* Card styling — on-brand */
        /* background removed: duplicated base var(--color-surface, #fff) at L2476 — Phase 2a S65 cascade cleanup */
        border: 2px solid var(--color-gold, #CC9900); /* intentional: mobile card treatment (base sidenav uses right-border only, no full border) — Phase 2a S65 */
        border-radius: var(--radius-lg, 12px); /* intentional: mobile pill-bar card (base is vertical rail, no radius) — Phase 2a S65 */
        box-shadow: 0 2px 8px rgba(3, 27, 131, 0.10), 0 1px 3px rgba(204, 153, 0, 0.08); /* intentional: mobile card elevation (base has no shadow) — Phase 2a S65 */
        margin-bottom: 0;
    }
    /* end of 15.6.1.1 */

    /* 15.6.1.2 Hide WebKit scrollbar */
    .dashboard-sidenav::-webkit-scrollbar {
        display: none;
    }
    /* end of 15.6.1.2 */

    /* 15.6.2 Scroll hint — OUTSIDE the card, below-right.
       col-inner is display:flex, so ::before gets order:1 to sit between sidenav(0) and content(2). */
    /* 15.6.2.1 Sidenav order — first */
    .dashboard-sidenav {
        order: 0;
    }
    /* end of 15.6.2.1 */
    /* 15.6.2.2 (REMOVED S89) — Legacy grey "scroll →" ::before pseudo on .col-inner.
       This was the legacy layout's scroll hint. The new design ships its own
       sidenav scroll-cue (`<div class="sidenav__scroll-cue">…</div>`) emitted by
       profile_system_open_app_shell(); the legacy ::before was a leftover. */
    /* 15.6.2.3 (REMOVED) — Legacy narrow content order. Retired S89. */

    /* 15.6.2.4 (REMOVED S89) — Legacy `.sidenav-item` pill-shape (border-radius: 9999px)
       was fighting the new BEM `.sidenav__item { border-radius: 10px }` at narrow widths,
       producing inconsistent button shapes (default 10px, hover/active 9999px). */
    /* 15.6.2.5 (REMOVED S89) — Legacy `.sidenav-item-active` gold-fill mobile variant.
       Replaced by the BEM `.sidenav__item--active` rule in page-polish.css §41.5. */
    /* 15.6.2.6 (REMOVED S89) — Legacy `.sidenav-item-active:hover` darker-gold variant. */

    /* 15.6.2.7 Sidenav item icon — smaller */
    .sidenav-item .dashicons {
        font-size: 16px;
        width: 16px;
        height: 16px;
    }
    /* end of 15.6.2.7 */

    /* 15.6.2.8 Sidenav badge — static positioning */
    .sidenav-badge {
        position: static;
    }
    /* end of 15.6.2.8 */

    /* 15.6.3.1 (REMOVED) — Legacy narrow workspace-children centring. Retired S89.
       The new .app shell handles its own content width and centring per breakpoint. */
    /* 15.6.3.2 Forms + tables — left-align inside centred content */
    /* T292: Re-allow left-align for form fields and tables inside centered content */
    body.profile-dashboard-active #item-body .standard-form,
    body.profile-dashboard-active #item-body table,
    body.profile-dashboard-active #item-body .suggestion-card-message,
    body.profile-dashboard-active #item-body .account-details-table {
        text-align: left;
    }
    /* end of 15.6.3.2 */

    /* 15.6.4 Hide Customise button + Profile/Customise pills on mobile */
    body.profile-dashboard-active .btn-customise-profile {
        display: none !important;
    }

    /* 15.6.5 Hide photo upload/reposition icons + Profile/Customise nav on mobile */
    .profile-cover-change-btn,
    .profile-cover-reposition-btn,
    .profile-avatar-change-btn,
    .profile-avatar-reposition-btn,
    .btn-view-profile,
    .btn-customise-profile,
    .profile-preview-nav {
        display: none !important;
    }

    /* 15.6.6 Center the main Dashboard/Account nav tabs */
    #item-nav .item-list-tabs ul,
    .item-list-tabs#object-nav ul {
        display: flex;
        justify-content: center;
    }

    /* 15.6.7 Banner image — match content area margins (12px each side) */
    /* 15.6.7.1 Cover image — 24px-margin centred */
    #header-cover-image,
    #item-header-cover-image {
        width: calc(100% - 24px) !important;
        margin: 0 auto !important;
        border-radius: var(--radius-md, 8px);
    }
    /* end of 15.6.7.1 */
    /* 15.6.7.2 #item-header — match horizontal padding */
    /* Also constrain the header container to match */
    #item-header {
        padding-left: 12px;
        padding-right: 12px;
    }
    /* end of 15.6.7.2 */
}

/* end of 15 */

/* ============================================================================
   16. SECTION: Cover Image + Avatar Redesign
   ============================================================================ */

/* 16.1 Cover image container — single full-bleed banner, no white split */
.profile-cover-redesign {
    position: relative;
    margin-bottom: 0;
}

/* 16.1.1 Cover image — full banner, avatar positioned inside.
   S63 Phase 1c T455 C19: radius 16px uniform (D090) — updated fallback + token. */
/* 16.1.1.1 Cover image base */
.profile-cover-image {
    width: 100%;
    height: 240px;
    background-color: var(--color-navy, #031B83);
    background-size: cover;
    background-position: center;
    position: relative;
    border-radius: var(--radius-lg, 16px);
    overflow: visible;
}
/* end of 16.1.1.1 */

/* 16.1.1.2 No-cover state — design-agent placeholder fill (S111 24/06/26).
   Two stacked backgrounds: diagonal navy tint over 45° striped pattern.
   Caption centred via ::before. Live sizes (height/border/radius/gutters)
   are owned by 16.1.1.1 + page-polish §42.0.4a/b — unchanged. */
.profile-cover-redesign.no-cover .profile-cover-image {
    background:
        linear-gradient(135deg, rgba(3, 27, 131, 0.4), rgba(0, 204, 255, 0.2)),
        repeating-linear-gradient(45deg, #2a3556 0 12px, #1f2848 12px 24px);
}
.profile-cover-redesign.no-cover .profile-cover-image::before {
    /* S163: the EM DASH was removed (D-202). S165, D-350: THE STRING IS DELIBERATE AND STAYS.
       Rob, 01/08/26, rejecting both offered replacements: "No that's there to let them know what
       size it should be for when they replace it with their own. The other platforms don't say and
       you have to go googling for it... Amazes me that even now they still haven't put the size of
       the images to help people." It is member-facing guidance, not a leaked spec artefact.
       Do NOT replace it with a pattern or prompt copy, and do not re-raise it as a defect. */
    content: 'IMAGE BANNER 1920x340';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'Courier New', monospace;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: rgba(255, 251, 230, 0.45);
    pointer-events: none;
}
/* end of 16.1.1.2 */
/* end of 16.1.1 */

/* 16.1.2 Gradient overlay — subtle, no text on banner */
.profile-cover-gradient {
    display: none;
}

/* 16.1.3 Cover change button */
/* 16.1.3.1 Button base — translucent circle */
.profile-cover-change-btn {
    position: absolute;
    top: var(--space-md, 12px);
    right: var(--space-md, 12px);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.2);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.3);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
    z-index: 2;
}
/* end of 16.1.3.1 */

/* 16.1.3.2 Button hover — brighter translucent */
.profile-cover-change-btn:hover {
    background: rgba(255, 255, 255, 0.35);
}
/* end of 16.1.3.2 */

/* 16.1.3.3 Button icon */
.profile-cover-change-btn .dashicons {
    font-size: 18px;
    width: 18px;
    height: 18px;
}
/* end of 16.1.3.3 */
/* end of 16.1.3 */

/* 16.2 Identity bar — below banner, name aligned with sidenav center */
/* 16.2.0.1 Identity bar wrapper */
/* T169: Equal whitespace above/below action buttons */
.profile-identity-bar {
    padding: 12px 0 12px 46px;
    background: transparent;
}
/* end of 16.2.0.1 */

/* 16.2.0.2 Identity inner — flex row */
.profile-identity-inner {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0;
    position: relative;
    z-index: 2;
}
/* end of 16.2.0.2 */

/* 16.2.0.3 Identity text block — sidenav-width centred */
/* Name block: width matches sidenav (220px), centered text aligns with avatar + sidenav center */
.profile-identity-text {
    width: 220px;
    flex-shrink: 0;
    text-align: center;
}
/* end of 16.2.0.3 */

/* 16.2.0.4 Header actions — push to right */
.profile-header-actions {
    margin-left: auto;
}
/* end of 16.2.0.4 */

/* 16.2.1 Avatar — inside the banner, vertically centered, center-aligned with sidenav (46px offset + half of 220px sidebar - half of 190px avatar = 61px) */
/* 16.2.1.1 Avatar wrap — absolute positioned */
.profile-avatar-wrap {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: 67px;
    z-index: 5;
    flex-shrink: 0;
}
/* end of 16.2.1.1 */

/* 16.2.1.2 Avatar image — circle + gold border */
.profile-avatar-img {
    width: 190px;
    height: 190px;
    border-radius: 50%;
    border: 5px solid var(--color-gold, #CC9900);
    object-fit: cover;
    background: var(--color-surface, #FFFFFF);
    box-shadow: 0 4px 16px rgba(26, 26, 46, 0.18);
}
/* end of 16.2.1.2 */
/* end of 16.2.1 */

/* 16.2.2 Avatar nav buttons — navigate between Dashboard/Profile/Customise */
/* 16.2.2.1 Preview nav row */
.profile-preview-nav {
    display: flex;
    justify-content: center;
    gap: 2px;
    margin-top: 4px;
    width: 100%;
}
/* end of 16.2.2.1 */
/* 16.2.2.2 Preview nav button base */
.preview-nav-btn {
    display: inline-block;
    padding: 3px 10px;
    font-family: 'Montserrat', sans-serif;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-gold, #CC9900);
    background: var(--color-navy, #031B83);
    border: 1px solid var(--color-gold, #CC9900);
    border-radius: 4px;
    text-decoration: none;
    transition: all 0.2s;
    white-space: nowrap;
    line-height: 1.4;
}
/* end of 16.2.2.2 */
/* 16.2.2.3 Preview nav button hover — gold fill */
.preview-nav-btn:hover {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    text-decoration: none;
}
/* end of 16.2.2.3 */

/* 16.2.2.4 Avatar change button — gold circle, bottom-right */
.profile-avatar-change-btn {
    /* S207 06/09/26, Rob item 29: one pixel to the right. */
    transform: translateX(1px);
    position: absolute;
    bottom: 8px;
    right: 8px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    /* S207 05/09/26, Rob item A4: dark gold FILLED buttons become light cream with a gold border and navy content, darker cream on hover and select. Was a gold fill with a white ring. */
    background: var(--color-cream, #FFFBE6);
    border: 2px solid var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 16.2.2.4 */

/* 16.2.2.5 Avatar change button hover — darker gold */
.profile-avatar-change-btn:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* end of 16.2.2.5 */

/* 16.2.2.6 Avatar change button icon */
.profile-avatar-change-btn .dashicons {
    font-size: 14px;
    width: 14px;
    height: 14px;
}
/* end of 16.2.2.6 */
/* end of 16.2.2 */

/* 16.2.6 Identity text — compact bar, doesn't push content down */
/* 16.2.6.1 Identity text wrapper — compact */
.profile-identity-text {
    min-width: 0;
    padding-top: 2px;
}
/* end of 16.2.6.1 */

/* 16.2.6.2 Display name — Montserrat heading */
.profile-display-name {
    font-family: var(--font-heading, 'Montserrat', sans-serif);
    font-weight: 700;
    font-size: 22px;
    color: var(--color-navy, #031B83);
    letter-spacing: -0.3px;
    margin: 0 0 2px 0;
    line-height: 1.2;
}
/* end of 16.2.6.2 */

/* 16.2.6.3 Meta line — handle only, centred. Joined-date hidden per Rob
   04/05/26 ("remove the joined at entirely because it's pushed everything
   down"). Brand-pass: navy text, NEVER grey (was inheriting #6B7280 grey
   via --color-text-muted; replaced with brand navy #031B83). */
.profile-meta-line {
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 14px;
    color: #031B83;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    margin-bottom: var(--space-sm, 8px);
    text-align: center;
}
.profile-meta-line .profile-username {
    color: #031B83;
}
/* end of 16.2.6.3 */

/* 16.2.6.4 Hidden secondary meta — separator dot + joined-date both removed */
.profile-meta-sep,
.profile-join-date {
    display: none;
}
/* end of 16.2.6.4 */
/* end of 16.2.6 */

/* 16.2.3 Badges */
/* 16.2.3.1 Badges container — flex wrap */
.profile-badges {
    display: flex;
    gap: var(--space-xs, 4px);
    flex-wrap: wrap;
    justify-content: center;
}
/* end of 16.2.3.1 */

/* 16.2.3.2 Badge base — pill shape */
.profile-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 12px 5px;
    border-radius: 9999px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    text-align: center;
}
/* end of 16.2.3.2 */

/* 16.2.3.3 Personality badge — navy bg, gold text */
.profile-badge-personality {
    background: var(--color-navy, #031B83);
    color: var(--color-gold, #CC9900);
}
/* end of 16.2.3.3 */

/* 16.2.3.4 Level badge — gold bg, navy text */
.profile-badge-level {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
}
/* end of 16.2.3.4 */
/* end of 16.2.3 */

/* 16.2.5 T274 (still active): Hide camera/reposition icons on non-Customise pages.
   T456 (S62, 2026-04-17): Reversed T275 — restored 3-button cycle (.profile-preview-nav) and header action buttons (.btn-view-profile, .btn-customise-profile, .profile-header-actions) on ALL workspace pages per Rob's new direction. Only the camera/reposition icons remain gated to /customise. */
body.profile-dashboard-active:not(.profile-editor-active) .profile-cover-change-btn,
body.profile-dashboard-active:not(.profile-editor-active) .profile-cover-reposition-btn,
body.profile-dashboard-active:not(.profile-editor-active) .profile-avatar-change-btn,
body.profile-dashboard-active:not(.profile-editor-active) .profile-avatar-reposition-btn {
    /* S207 06/09/26, Rob item 29: one pixel to the right. */
    transform: translateX(1px);
    display: none !important;
}

/* 16.2.4 Header action buttons */
/* 16.2.4.1 Action row container */
.profile-header-actions {
    display: flex;
    gap: var(--space-sm, 8px);
    justify-content: center;
}
/* end of 16.2.4.1 */

/* 16.2.4.2 Profile button base — visual properties retired S100 (25/05/26).
   Visual (bg, border, font, shadow, hover) now owned by .btn-option per D-174 v2.
   This rule keeps ONLY the layout/grouping properties needed to keep .profile-btn
   instances flowing correctly in the profile header actions row. */
.profile-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs, 4px);
}
/* end of 16.2.4.2 */

/* 16.2.4.3 + 16.2.4.4 — .profile-btn-primary rules retired S100 (25/05/26).
   The Message button now uses class="profile-btn btn-option". All visual
   styling (cream/gold/navy border, hover, etc.) is owned by .btn-option in
   page-polish.css §43. Original CSS preserved in git pre-S100. */
/* end of 16.2.4.3 + 16.2.4.4 */

/* 16.2.4.5 Outline button — transparent + gold border */
.profile-btn-outline {
    background: transparent;
    color: var(--color-gold, #CC9900);
    border-color: var(--color-gold, #CC9900);
}
/* end of 16.2.4.5 */

/* 16.2.4.6 Outline button hover — gold fill */
.profile-btn-outline:hover {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
}
/* end of 16.2.4.6 */

/* 16.2.4.7 Profile button icon */
.profile-btn .dashicons {
    font-size: 16px;
    width: 16px;
    height: 16px;
}
/* end of 16.2.4.7 */
/* end of 16.2.4 */

/* 16.3 Responsive — tablet */
@media (max-width: 1023px) {
    /* 16.3.1 Cover image — slightly shorter */
    .profile-cover-image {
        height: 200px;
    }
    /* end of 16.3.1 */

    /* 16.3.2 Avatar — smaller */
    .profile-avatar-img {
        width: 150px;
        height: 150px;
    }
    /* end of 16.3.2 */

    /* 16.3.3 Display name — smaller font */
    .profile-display-name {
        /* S67 Phase 9 SW4 fix (Rob 2026-04-18): was 24px at ≤1023px — inverted ladder.
           Rob's target: 22px at ≥1024 (base rule L3016), 20px at <1024. */
        font-size: 20px;
    }
    /* end of 16.3.3 */
}

/* 16.4 Responsive — mobile */
@media (max-width: 639px) {
    /* 16.4.1 Cover image — shorter, true full-bleed on small mobile.
       B10 (S85 04/05/26): selector boosted ID+class (1,1,0) to beat §15.6.7.1's
       #item-header-cover-image rule at (1,0,0) which forces width: calc(100% - 24px),
       margin: 0 auto, border-radius: var(--radius-md, 8px). At ≤639px we want
       genuine edge-to-edge: zero radius, zero margin, full width. */
    #item-header-cover-image.profile-cover-image,
    .profile-cover-image {
        height: 160px;
        width: 100% !important;
        margin: 0 !important;
        border-radius: 0 !important;
    }
    /* end of 16.4.1 */

    /* 16.4.2 Avatar wrap — left edge */
    .profile-avatar-wrap {
        top: 50%;
        transform: translateY(-50%);
        left: 10px;
    }
    /* end of 16.4.2 */

    /* 16.4.3 Avatar image — smaller + thinner border */
    .profile-avatar-img {
        width: 110px;
        height: 110px;
        border-width: 4px; /* intentional: border scaled to smaller avatar size on mobile (base uses 5px for 190px avatar) — Phase 2a S65 */
    }
    /* end of 16.4.3 */

    /* 16.4.4 Identity bar — tighter padding */
    .profile-identity-bar {
        padding: var(--space-sm, 8px) var(--space-md, 12px) var(--space-md, 12px);
    }
    /* end of 16.4.4 */

    /* 16.4.5 Identity inner — stack column */
    .profile-identity-inner {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }
    /* end of 16.4.5 */

    /* 16.4.6 Identity text — full width */
    .profile-identity-text {
        width: 100%;
    }
    /* end of 16.4.6 */

    /* 16.4.7 Display name — smaller font */
    .profile-display-name {
        font-size: 20px;
    }
    /* end of 16.4.7 */

    /* 16.4.8 Meta line — centred */
    .profile-meta-line {
        justify-content: center;
    }
    /* end of 16.4.8 */

    /* 16.4.9 Badges — centred */
    .profile-badges {
        justify-content: center;
    }
    /* end of 16.4.9 */

    /* 16.4.10 Header actions — full width centred */
    .profile-header-actions {
        width: 100%;
        justify-content: center;
    }
    /* end of 16.4.10 */

    /* 16.4.11 Profile buttons — flex grow */
    .profile-btn {
        flex: 1;
        justify-content: center;
    }
    /* end of 16.4.11 */

    /* 16.4.12 Hide Customise button on mobile — pill-nav has it */
    /* Hide Customise button on mobile — it's in the pill nav */
    .profile-header-actions .profile-btn-outline[href*="customise"],
    .profile-header-actions .profile-btn-outline:has(.dashicons-admin-customizer) {
        display: none !important;
    }
    /* end of 16.4.12 */
}

/* 16.5 Hide Seeko's default header styling on redesigned profiles */
.profile-cover-redesign + .item-header-content,
.profile-cover-redesign ~ #item-header-avatar {
    display: none !important;
}

/* 16.6 Kill dead space between banner and content below */
/* 16.6.1 #item-header — zero bottom space */
#item-header {
    margin-bottom: 0 !important;
    padding-bottom: 0 !important;
}
/* end of 16.6.1 */
/* 16.6.2 .col-header — zero bottom space */
.col-header {
    padding-bottom: 0 !important;
    margin-bottom: 0 !important;
}
/* end of 16.6.2 */
/* 16.6.3 #item-body — zero top space */
#item-body {
    padding-top: 0 !important;
    margin-top: 0 !important;
}
/* end of 16.6.3 */
/* 16.6.4 BP-member-layout row — zero bottom margin */
/* Seeko adds margin to .bp-member-layout rows */
.bp-member-layout > .container > .row {
    margin-bottom: 0;
}
/* end of 16.6.4 */
/* 16.6.5 BP-member-layout col-12 — zero top padding */
.bp-member-layout > .container > .row > .col-12 {
    padding-top: 0;
}
/* end of 16.6.5 */
/* 16.6.6 Own-profile col-inner — zero top space */
/* Kill inner container spacing between header and content on own-profile pages */
body.profile-editor-active #item-body .col-inner,
body.profile-dashboard-active #item-body .col-inner {
    padding-top: 0 !important;
    margin-top: 0 !important;
}
/* end of 16.6.6 */
/* 16.6.7 Own-profile container — zero top space */
body.profile-editor-active #item-body .container,
body.profile-dashboard-active #item-body .container {
    padding-top: 0 !important;
    margin-top: 0 !important;
}
/* end of 16.6.7 */
/* 16.6.8 Own-profile row — zero top margin */
body.profile-editor-active #item-body .row,
body.profile-dashboard-active #item-body .row {
    margin-top: 0 !important;
}
/* end of 16.6.8 */
/* 16.6.9 Own-profile #item-nav — collapse hidden space */
/* Hidden nav still reserves space — collapse it */
body.profile-editor-active #item-nav,
body.profile-dashboard-active #item-nav {
    margin: 0 !important;
    padding: 0 !important;
}
/* end of 16.6.9 */
/* 16.6.10 Own-profile #subnav — fully hide */
/* Empty subnav still has padding — collapse it on own-profile pages */
body.profile-editor-active #subnav,
body.profile-dashboard-active #subnav {
    display: none !important;
}
/* end of 16.6.10 */
/* end of 16.6 */

/* 16.7 Public profile action buttons — clean layout when viewing another member */
/* 16.7.1 Hide BP's duplicate message + mention buttons */
/* Hide BP's duplicate message button and mention button */
#item-buttons #send-private-message,
#item-buttons #post-mention,
#item-buttons #invite-modal-root {
    display: none !important;
}
/* end of 16.7.1 */

/* 16.7.2 Action buttons container — horizontal row */
/* Action buttons container — horizontal row, vertically centered with name area */
#item-buttons.profile-header-actions {
    display: flex !important;
    /* S187: was `nowrap`, and combined with `flex-shrink: 0` on the children below that put
       the profile's action buttons off both edges of a phone screen. Measured at 360 on a
       real member viewing another member: the row holds ~480px of buttons in a 312px space,
       so Favourite started at left:-60 and "Show interest?" ended at right:420, and because
       nothing on the chain scrolls, neither could be reached at all - two of the three
       actions on the profile were simply unusable on a phone.
       Wrapping changes nothing at widths where the buttons already fit on one line; it only
       replaces "spill off the screen" with "move to the next line" where they do not. */
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    justify-content: center;
    margin-left: auto;
}
/* end of 16.7.2 */

/* 16.7.3 Children — uniform width, kill flex grow + margins */
/* S198 (29/08/26, Rob): the row read as three different buttons of three different widths
   (Favourite 156, "Would like to invite" 140, "Show interest?" 170) plus a fourth on a
   matched profile. Rob: "the three buttons above should all be the exact same shape and
   size and uniform, on all breakpoint sizes." `width: auto` was what let each one size to
   its own label, so it is REPLACED by one shared width. The width is a variable so the
   whole row is retuned from one place; it is set from the widest rendered label, measured
   live, not guessed. Below the stacking breakpoint they stay this width and centre, so a
   phone shows the same three identical buttons rather than a ragged column. */
#item-buttons.profile-header-actions {
    --uks-action-btn-w: 176px;
}
#item-buttons.profile-header-actions > * {
    flex-shrink: 0;
    width: var(--uks-action-btn-w) !important;
    max-width: 100%;
    margin: 0 !important;
}
/* end of 16.7.3 */
/* 16.7.4 Grandchildren — kill margins */
#item-buttons.profile-header-actions > * > * {
    margin: 0 !important;
}
/* end of 16.7.4 */

/* 16.7.5 Identical height for all action buttons/links */
/* Force all action buttons/links to identical height for perfect alignment */
/* S198: .member-fav-btn was never in this list, so it alone rendered 42.2px tall against
   the other two at 40px, on a 22px radius against their 16px, at 13px/600 against their
   12px/700 — the reason the row never looked like a set. It is added here and its shell
   brought onto the same shape. Its cream fill and gold + circle are its designed identity
   (D-084 / D-275) and are deliberately left alone; only shape and size are normalised. */
#item-buttons.profile-header-actions .profile-btn,
#item-buttons.profile-header-actions #invite-btn-holder button,
#item-buttons.profile-header-actions .member-fav-btn,
#item-buttons.profile-header-actions .interest-button-wrap > a {
    height: 40px !important;
    width: 100% !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    box-sizing: border-box !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-radius: 16px !important;
    font-size: 12px !important;
    font-weight: 700 !important;
}
/* S198: THE 8px THAT KNOCKED EVERY LABEL IN THIS ROW OFF CENTRE.
   Seeko's own buddypress.min.css carries
     .bp-member-layout #item-buttons .generic-button:not(.friendship-button) a::before
     { content: ""; margin-right: .5rem; font-family: icon; }
   an EMPTY icon-font slot. It draws nothing, but it is still a flex item on the centred
   line, so it stole 8px at the start of every `.generic-button a` in this row - measured,
   Favourite's word sat 4px right of its button's midpoint and the interest/Message button's
   7px right, while "Would like to invite" (a <button>, not a .generic-button a, so never
   matched) sat dead centre. Killed here for the profile action row only; the members-list
   half of the parent rule is left alone. */
#item-buttons.profile-header-actions .generic-button a::before {
    content: none !important;
    margin-right: 0 !important;
}

/* S198: with .member-fav-btn now exempt from page-polish's legacy BP-button override
   (page-polish.css ~2484), its own colours are stated in a wp_footer <style> at (0,1,0)
   and lose to the parent theme's `#item-buttons .generic-button a` at (1,2,1), which
   painted it a pale grey border on white. Its designed cream/gold identity is restated
   here, at the specificity that actually holds. Border matched to the other two at 1px so
   all three are the same shape; the cream fill and the gold + circle stay as the thing
   that tells it apart. */
#item-buttons.profile-header-actions .member-fav-btn {
    /* S198: Rob, 29/08/26 - "it should be the same as the other buttons". The cream fill
       made it read as a different kind of control sitting next to two transparent ones, so
       the whole row now shares one resting state. The favourited state below keeps the gold
       fill, which is what actually needs to stand out. */
    background: transparent !important;
    border: 1px solid #CC9900 !important;
    color: #031B83 !important;
    /* S198: .btn-option's own navy-tinted lift, copied exactly. The fav button was carrying
       a grey parent-theme shadow instead, which is what made it read as a different control
       sitting between two matching ones. */
    box-shadow: rgba(3, 27, 131, 0.1) 0 2px 0 0, rgba(3, 27, 131, 0.1) 0 3px 6px 0 !important;
    position: relative;
    gap: 5px !important; /* S198, Rob: 5px between the + circle and the word */
    padding-left: 12px !important;
    padding-right: 12px !important;
}
/* S198: the word is centred on the button AND the + circle sits 5px in front of the word
   (Rob, 29/08/26: "move it closer to the word favourite not closer to the border"). Both
   stay in normal flow, 5px apart; a mirror spacer the same width as the circle is added on
   the trailing side, so the flex line is symmetric about the LABEL rather than about
   "circle plus word". No magic offsets, and it holds at every width and for the longer
   "Favourited" text, because the balance is a width the rule owns, not a measured one. */
#item-buttons.profile-header-actions .member-fav-btn .member-fav-label {
    position: static;
    flex: 0 0 auto;
}
/* The mirror spacer belongs ONLY to this row, where the button is a fixed 176px and is
   therefore wider than its content: it balances the + circle so the line centres on the
   WORD. On a button that hugs its content - the Favourites tab card - the same spacer is
   just visible dead space on the right, which reads as off-centre. Hence row-scoped. */
#item-buttons.profile-header-actions .member-fav-btn::after {
    content: "";
    flex: 0 0 18px;
    width: 18px;
    height: 1px;
}
#item-buttons.profile-header-actions .member-fav-btn.is-fav {
    background: #CC9900 !important;
    color: #fffbe6 !important;
}
/* S198: the + circle scales with the smaller type so it stays inside the 40px shell, and it
   is taken OUT OF FLOW (Rob, 29/08/26: "centre the word Favourite and just leave the circle
   with the plus in front of it"). As a flex sibling it shared the centring with the label,
   so the word sat right of the button's midpoint while the other two buttons' labels were
   dead centre. Absolute-positioning the circle leaves the label as the only flow child, so
   `justify-content: center` centres the WORD against the full button width. */
#item-buttons.profile-header-actions .member-fav-btn .member-fav-plus {
    position: static;
    width: 18px;
    height: 18px;
    font-size: 13px;
    flex: 0 0 18px;
    border-width: 1px;
}
#item-buttons.profile-header-actions .member-fav-btn.is-fav .member-fav-plus {
    background: #fffbe6;
    color: #CC9900;
}
/* end of 16.7.5 */

/* 16.7.6 + 16.7.7 — Invite button visual rules retired S100 (25/05/26).
   Now uses class="invite-btn btn-option". All visual styling owned by
   .btn-option in page-polish.css §43. Original CSS preserved in git. */
/* end of 16.7.6 + 16.7.7 */

/* 16.7.8 Interest button wrapper */
/* Interest button — outline style */
#item-buttons .interest-button-wrap {
    position: relative;
}
/* end of 16.7.8 */
/* 16.7.9 + 16.7.10 — Interest button visual rules retired S100 (25/05/26).
   Now uses class="interest-btn ... btn-option". All visual owned by .btn-option. */
/* end of 16.7.9 + 16.7.10 */

/* 16.7.11 Interest reasons popover — position below button */
/* Interest reasons popover — position below button */
#item-buttons .interest-reasons-popover {
    position: absolute;
    top: calc(100% + 5px);
    right: 0;
    margin-top: 0;
    z-index: 100;
    min-width: 240px;
}
/* end of 16.7.11 */

/* 16.7.12 Mobile @media — stack buttons full-width */
/* Mobile: stack buttons vertically */
@media (max-width: 768px) {
    #item-buttons.profile-header-actions {
        width: 100%;
        justify-content: center;
        margin-left: 0;
        margin-top: 8px;
    }
}
/* end of 16.7.12 */
/* end of 16.7 */

/* end of 16 */

/* ============================================================================
   17. SECTION: Messages Panel Redesign
   ============================================================================ */

/* 17.1 Split-panel layout (desktop) */
.messages-split-panel {
    display: flex;
    width: 100%;
    height: calc(100vh - 200px);
    min-height: 500px;
    background: var(--color-surface, #FFFFFF);
    border-radius: var(--radius-lg, 12px);
    box-shadow: var(--shadow-md, 0 4px 12px rgba(26, 26, 46, 0.12));
    overflow: hidden;
}

/* 17.1.1 Conversation list */
/* 17.1.1.1 List panel container */
.messages-list-panel {
    width: 280px;
    flex-shrink: 0;
    border-right: 1px solid var(--color-border, #E5E7EB);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
/* end of 17.1.1.1 */

/* 17.1.1.2 List header row */
.messages-list-header {
    padding: var(--space-lg, 16px);
    border-bottom: 1px solid var(--color-border, #E5E7EB);
    display: flex;
    align-items: center;
    justify-content: space-between;
}
/* end of 17.1.1.2 */

/* 17.1.1.3 List header title */
.messages-list-header h3 {
    font-family: var(--font-heading, 'Montserrat', sans-serif);
    font-weight: 700;
    font-size: 18px;
    color: var(--color-navy, #031B83);
    margin: 0;
}
/* end of 17.1.1.3 */

/* 17.1.1.4 Compose button — gold circle */
.messages-compose-btn {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    /* S207 05/09/26, Rob item A4: gold FILL out, light cream in with a gold border and navy content; darker cream on hover. */
    background: var(--color-cream, #FFFBE6);
    border: 1.5px solid var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 17.1.1.4 */

/* 17.1.1.5 Compose button hover — darker gold */
.messages-compose-btn:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* end of 17.1.1.5 */

/* 17.1.1.6 Thread list scroll container */
.messages-thread-list {
    flex: 1;
    overflow-y: auto;
    list-style: none;
    margin: 0;
    padding: 0;
}
/* end of 17.1.1.6 */
/* end of 17.1.1 */

/* 17.1.2 Thread item */
/* 17.1.2.1 Thread row base — flex */
.messages-thread-item {
    display: flex;
    align-items: center;
    gap: var(--space-sm, 8px);
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    cursor: pointer;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
    border-bottom: 1px solid var(--color-border-light, #F3F4F6);
}
/* end of 17.1.2.1 */

/* 17.1.2.2 Thread hover — raised bg */
.messages-thread-item:hover {
    background: var(--color-surface-raised, #F9F8F5);
}
/* end of 17.1.2.2 */

/* 17.1.2.3 Active thread — gold left border */
.messages-thread-item.active {
    background: var(--color-surface-raised, #F9F8F5);
    border-left: 3px solid var(--color-gold, #CC9900);
    padding-left: calc(var(--space-lg, 16px) - 3px);
}
/* end of 17.1.2.3 */

/* 17.1.2.4 Unread thread — tinted bg */
.messages-thread-item.unread {
    background: var(--color-bg, #FDFCF9);
}
/* end of 17.1.2.4 */

/* 17.1.2.5 Thread avatar */
.messages-thread-avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}
/* end of 17.1.2.5 */

/* 17.1.2.6 Thread info column */
.messages-thread-info {
    flex: 1;
    min-width: 0;
}
/* end of 17.1.2.6 */

/* 17.1.2.7 Thread name */
.messages-thread-name {
    font-weight: 600;
    font-size: 14px;
    color: var(--color-text, #1A1A2E);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* end of 17.1.2.7 */

/* 17.1.2.8 Thread preview text */
.messages-thread-preview {
    font-size: 13px;
    color: var(--color-text-muted, #6B7280);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 2px;
}
/* end of 17.1.2.8 */

/* 17.1.2.9 Thread meta column — time + dot */
.messages-thread-meta {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
}
/* end of 17.1.2.9 */

/* 17.1.2.10 Thread timestamp */
.messages-thread-time {
    font-size: 11px;
    color: var(--color-text-muted, #6B7280);
}
/* end of 17.1.2.10 */

/* 17.1.2.11 Unread dot */
.messages-unread-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-gold, #CC9900);
}
/* end of 17.1.2.11 */
/* end of 17.1.2 */

/* 17.2 Conversation panel */
/* 17.2.0.1 Convo panel container */
.messages-convo-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
/* end of 17.2.0.1 */

/* 17.2.0.2 Convo header row */
.messages-convo-header {
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    border-bottom: 1px solid var(--color-border, #E5E7EB);
    display: flex;
    align-items: center;
    gap: var(--space-sm, 8px);
}
/* end of 17.2.0.2 */

/* 17.2.0.3 Back button — hidden by default (mobile only) */
.messages-convo-back {
    display: none;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--color-navy, #031B83);
    cursor: pointer;
    align-items: center;
    justify-content: center;
}
/* end of 17.2.0.3 */

/* 17.2.0.4 Convo avatar */
.messages-convo-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
}
/* end of 17.2.0.4 */

/* 17.2.0.5 Convo name */
.messages-convo-name {
    font-family: var(--font-heading, 'Montserrat', sans-serif);
    font-weight: 600;
    font-size: 16px;
    color: var(--color-navy, #031B83);
}
/* end of 17.2.0.5 */

/* 17.2.1 Message bubbles */
/* 17.2.1.1 Body scroll container */
.messages-body {
    flex: 1;
    overflow-y: auto;
    padding: var(--space-lg, 16px);
    display: flex;
    flex-direction: column;
    gap: var(--space-sm, 8px);
}
/* end of 17.2.1.1 */

/* 17.2.1.2 Bubble base */
.message-bubble {
    max-width: 70%;
    padding: var(--space-sm, 8px) var(--space-md, 12px);
    border-radius: var(--radius-lg, 12px);
    font-size: 14px;
    line-height: 1.5;
    word-wrap: break-word;
}
/* end of 17.2.1.2 */

/* 17.2.1.3 Sent bubble — navy filled, right-aligned */
.message-bubble.sent {
    align-self: flex-end;
    background: var(--color-navy, #031B83);
    color: var(--color-gold, #CC9900);
    border-bottom-right-radius: var(--radius-xs, 2px);
}
/* end of 17.2.1.3 */

/* 17.2.1.4 Received bubble — raised bg, left-aligned */
.message-bubble.received {
    align-self: flex-start;
    background: var(--color-surface-raised, #F9F8F5);
    color: var(--color-text, #1A1A2E);
    border-bottom-left-radius: var(--radius-xs, 2px);
}
/* end of 17.2.1.4 */

/* 17.2.1.5 Timestamp base */
.message-timestamp {
    font-size: 11px;
    color: var(--color-text-muted, #6B7280);
    margin-top: 2px;
}
/* end of 17.2.1.5 */

/* 17.2.1.6 Sent-bubble timestamp — translucent, right-aligned */
.message-bubble.sent .message-timestamp {
    color: rgba(255, 255, 255, 0.6);
    text-align: right;
}
/* end of 17.2.1.6 */
/* end of 17.2.1 */

/* 17.2.2 Input area */
/* 17.2.2.1 Input row — flex */
.messages-input-area {
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    border-top: 1px solid var(--color-border, #E5E7EB);
    display: flex;
    gap: var(--space-sm, 8px);
    align-items: flex-end;
}
/* end of 17.2.2.1 */

/* 17.2.2.2 Textarea — flex grow + resize cap */
.messages-input-area textarea {
    flex: 1;
    resize: none;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: var(--radius-md, 8px);
    padding: var(--space-sm, 8px) var(--space-md, 12px);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 14px;
    line-height: 1.5;
    max-height: 120px;
    transition: border-color var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 17.2.2.2 */

/* 17.2.2.3 Textarea focus — gold border + halo */
.messages-input-area textarea:focus {
    outline: none;
    border-color: var(--color-gold, #CC9900);
    box-shadow: 0 0 0 3px rgba(204, 153, 0, 0.15);
}
/* end of 17.2.2.3 */

/* 17.2.2.4 Send button — gold circle */
.messages-send-btn {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    /* S207 05/09/26, Rob item A4: gold FILL out, light cream in with a gold border and navy content; darker cream on hover. */
    background: var(--color-cream, #FFFBE6);
    border: 1.5px solid var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 17.2.2.4 */

/* 17.2.2.5 Send button hover — darker gold */
.messages-send-btn:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* end of 17.2.2.5 */
/* end of 17.2.2 */

/* 17.2.3 Empty state */
/* 17.2.3.1 Empty-state container — centred column */
.messages-empty-state {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted, #6B7280);
    gap: var(--space-sm, 8px);
}
/* end of 17.2.3.1 */

/* 17.2.3.2 Empty-state icon — large + faded */
.messages-empty-state .dashicons {
    font-size: 48px;
    width: 48px;
    height: 48px;
    opacity: 0.3;
}
/* end of 17.2.3.2 */
/* end of 17.2.3 */

/* 17.3 Responsive — tablet */
@media (max-width: 1023px) {
    .messages-list-panel {
        width: 240px;
    }
}

/* 17.4 Responsive — mobile */
@media (max-width: 639px) {
    /* 17.4.3 Split panel — full-bleed, no radius */
    .messages-split-panel {
        height: calc(100vh - 160px);
        border-radius: 0; /* intentional: full-bleed chat on small mobile (base has --radius-lg) — Phase 2a S65 */
        position: relative;
        overflow: hidden;
    }
    /* end of 17.4.3 */

    /* 17.4.4 List panel — absolute overlay */
    .messages-list-panel {
        width: 100%;
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 2;
        background: var(--color-surface, #FFFFFF); /* intentional: absolutely-positioned overlay panel needs opaque bg to cover convo panel underneath — Phase 2a S65 */
        transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    /* end of 17.4.4 */

    /* 17.4.5 Convo panel — absolute, slid off-screen */
    .messages-convo-panel {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 3;
        background: var(--color-surface, #FFFFFF); /* intentional: absolutely-positioned overlay panel needs opaque bg to cover list panel underneath — Phase 2a S65 */
        transform: translateX(100%);
        transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    /* end of 17.4.5 */

    /* 17.4.6 Convo-open state — slide in convo panel */
    .messages-split-panel.convo-open .messages-convo-panel {
        transform: translateX(0);
    }
    /* end of 17.4.6 */

    /* 17.4.7 Back button — visible on mobile */
    .messages-convo-back {
        display: flex;
    }
    /* end of 17.4.7 */
}

/* 17.5 BP messages override — restyle existing markup
   BuddyPress uses TABLE > TBODY > TR (not UL > LI). BP core CSS sets display:grid
   on the TR which breaks visual rendering. Override to flex layout. */

/* 17.5.0 Reorder .messages children: form (threads) before pagination */
/* 17.5.0.2 .messages container — flex column */
#buddypress div.messages {
    display: flex;
    flex-direction: column;
}
/* end of 17.5.0.2 */
/* 17.5.0.3 Bulk-management form — order 1 */
#buddypress div.messages > form#messages-bulk-management {
    order: 1;
}
/* end of 17.5.0.3 */
/* 17.5.0.4 Pagination — order 2 */
#buddypress div.messages > .pagination {
    order: 2;
}
/* end of 17.5.0.4 */

/* 17.5.0.5 Message-threads tables — block layout, full width */
#buddypress #message-threads,
#buddypress table.messages-notices {
    display: block !important;
    list-style: none;
    padding: 0;
    margin: 0;
    width: 100%;
}
/* end of 17.5.0.5 */
/* end of 17.5.0 */

/* 17.5.0.1 TBODY must also be block — table-row-group + flex children = no paint */
#buddypress #message-threads tbody,
#buddypress table.messages-notices tbody {
    display: block !important;
    width: 100%;
}

/* 17.5.1 Hide table header — our flex layout replaces it */
#buddypress #message-threads thead,
#buddypress table.messages-notices thead {
    display: none;
}

/* 17.5.2 Override BP display:grid on TR — use flex instead */
/* 17.5.2.1 TR base — flex layout */
#buddypress #message-threads tbody tr,
#buddypress table.messages-notices tbody tr {
    display: flex !important;
    align-items: center;
    gap: var(--space-sm, 8px);
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    border-bottom: 1px solid var(--color-border-light, #F3F4F6);
    cursor: pointer;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 17.5.2.1 */

/* 17.5.2.2 TR hover — raised bg */
#buddypress #message-threads tbody tr:hover,
#buddypress table.messages-notices tbody tr:hover {
    background: var(--color-surface-raised, #F9F8F5);
}
/* end of 17.5.2.2 */

/* 17.5.2.3 TR unread — gold left border */
#buddypress #message-threads tbody tr.unread,
#buddypress table.messages-notices tbody tr.unread {
    background: var(--color-bg, #FDFCF9);
    border-left: 3px solid var(--color-gold, #CC9900);
}
/* end of 17.5.2.3 */
/* end of 17.5.2 */

/* 17.5.3 Message row cell layout */
/* 17.5.3.1 Bulk-select checkbox column */
#buddypress #message-threads tbody tr td.bulk-select-check {
    flex: 0 0 30px;
}
/* end of 17.5.3.1 */
/* 17.5.3.2 Thread-from column */
#buddypress #message-threads tbody tr td.thread-from {
    flex: 0 0 160px;
    font-weight: 600;
}
/* end of 17.5.3.2 */
/* 17.5.3.3 Thread-info column — flex grow + ellipsis */
#buddypress #message-threads tbody tr td.thread-info {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* end of 17.5.3.3 */
/* 17.5.3.4 Thread-info link — navy, no underline */
#buddypress #message-threads tbody tr td.thread-info a {
    color: var(--color-navy, #031B83);
    text-decoration: none;
}
/* end of 17.5.3.4 */
/* 17.5.3.5 Thread-star column */
#buddypress #message-threads tbody tr td.thread-star {
    flex: 0 0 40px;
    text-align: center;
}
/* end of 17.5.3.5 */
/* 17.5.3.6 Thread-options column */
#buddypress #message-threads tbody tr td.thread-options {
    flex: 0 0 80px;
    text-align: right;
}
/* end of 17.5.3.6 */

/* 17.5.3.7 Message metadata row */
#buddypress .message-metadata {
    display: flex;
    align-items: center;
    gap: var(--space-sm, 8px);
    margin-bottom: var(--space-xs, 4px);
}
/* end of 17.5.3.7 */

/* 17.5.3.8 Message bubble box */
#buddypress #message-thread .message-box {
    padding: var(--space-sm, 8px) var(--space-md, 12px);
    margin-bottom: var(--space-sm, 8px);
    border-radius: var(--radius-lg, 12px);
    max-width: 70%;
}
/* end of 17.5.3.8 */

/* 17.5.3.9 Send-reply container */
#buddypress #send-reply {
    border-top: 1px solid var(--color-border, #E5E7EB);
    padding: var(--space-md, 12px) var(--space-lg, 16px);
}
/* end of 17.5.3.9 */

/* 17.5.3.10 Send-reply textarea */
#buddypress #send-reply textarea {
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: var(--radius-md, 8px);
    padding: var(--space-sm, 8px) var(--space-md, 12px);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 14px;
    width: 100%;
    resize: none;
}
/* end of 17.5.3.10 */

/* 17.5.3.11 Send-reply textarea focus — gold halo */
#buddypress #send-reply textarea:focus {
    outline: none;
    border-color: var(--color-gold, #CC9900);
    box-shadow: 0 0 0 3px rgba(204, 153, 0, 0.15);
}
/* end of 17.5.3.11 */

/* 17.5.3.12 Send-reply submit — gold filled */
#buddypress #send-reply input[type="submit"] {
    /* S207 05/09/26, Rob item A4: gold FILL out, light cream in with a gold border and navy content; darker cream on hover. */
    background: var(--color-cream, #FFFBE6);
    color: var(--color-navy, #031B83);
    border: 1.5px solid var(--color-gold, #CC9900);
    border-radius: var(--radius-md, 8px);
    padding: var(--space-sm, 8px) var(--space-xl, 24px);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
    margin-top: var(--space-sm, 8px);
}
/* end of 17.5.3.12 */

/* 17.5.3.13 Send-reply submit hover — darker gold */
#buddypress #send-reply input[type="submit"]:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* end of 17.5.3.13 */
/* end of 17.5.3 */

/* 17.3.1 T257: Hide "notice to all users" checkbox for non-admin */
/* 17.3.1.1 Default — hide for everyone */
#buddypress #send_message_form .form-check:has(#send-notice) {
    display: none;
}
/* end of 17.3.1.1 */
/* 17.3.1.2 Admin override — show for admins only */
body.uks-role-admin #buddypress #send_message_form .form-check:has(#send-notice) {
    display: block;
}
/* end of 17.3.1.2 */
/* end of 17.3.1 */

/* 17.3.3 T255: Hide Send To field for non-admin */
/* 17.3.3.1 Default — hide for everyone */
#buddypress #send_message_form .form-group:has(#send-to-input) {
    display: none;
}
/* end of 17.3.3.1 */
/* 17.3.3.2 Admin override — show for admins only */
body.uks-role-admin #buddypress #send_message_form .form-group:has(#send-to-input) {
    display: block;
}
/* end of 17.3.3.2 */
/* end of 17.3.3 */

/* 17.3.2 T262: Send Reply button brand + larger reply textarea */
#buddypress #send-reply textarea {
    min-height: 100px;
}

/* 17.8 Messages full-width workspace override */
/* 17.8.1 Containers — full-width box */
body.profile-dashboard-active #item-body #message-threads,
body.profile-dashboard-active #item-body #send-reply,
body.profile-dashboard-active #item-body .bp-messages-content,
body.profile-dashboard-active #item-body #send_message_form,
body.profile-dashboard-active #item-body .messages-notices-table {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}
/* end of 17.8.1 */
/* 17.8.2 Form fields + tables — force 100% width */
body.profile-dashboard-active #item-body #send_message_form textarea,
body.profile-dashboard-active #item-body #send_message_form input[type="text"],
body.profile-dashboard-active #item-body #send-reply textarea,
body.profile-dashboard-active #item-body table.messages-notices,
body.profile-dashboard-active #item-body #message-threads table {
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box;
}
/* end of 17.8.2 */

/* 17.9 Content top alignment — kill first-child margins in workspace */
/* 17.9.1 Generic first-child — zero top margin */
body.profile-dashboard-active #item-body .col-inner > *:not(.dashboard-sidenav) > *:first-child {
    margin-top: 0 !important;
}
/* end of 17.9.1 */
/* 17.9.2 First-child h2/h3/div — also zero top padding */
body.profile-dashboard-active #item-body .col-inner > *:not(.dashboard-sidenav):not(.profile-editor-wrapper):not(.profile-customise-cta) > h2:first-child,
body.profile-dashboard-active #item-body .col-inner > *:not(.dashboard-sidenav):not(.profile-editor-wrapper):not(.profile-customise-cta) > h3:first-child,
body.profile-dashboard-active #item-body .col-inner > *:not(.dashboard-sidenav):not(.profile-editor-wrapper):not(.profile-customise-cta) > div:first-child {
    margin-top: 0 !important;
    padding-top: 0 !important;
}
/* end of 17.9.2 */

/* 17.6 Messages sub-navigation (Inbox/Sent/Compose) — show BP native subnav */
/* 17.6.1 Subnav UL — block, no list bullets */
body.profile-dashboard-active #subnav {
    display: block !important;
    margin: 0 0 var(--space-lg, 16px) 0;
    padding: 0;
    list-style: none;
}
/* end of 17.6.1 */
/* 17.6.2 Subnav LI — inline blocks */
body.profile-dashboard-active #subnav li {
    display: inline-block;
    margin-right: var(--space-md, 12px);
}
/* end of 17.6.2 */
/* 17.6.3 Subnav links — base styling */
body.profile-dashboard-active #subnav li a {
    display: inline-block;
    padding: var(--space-xs, 4px) var(--space-md, 12px);
    color: var(--color-text-secondary, #6B6B7B);
    text-decoration: none;
    font-weight: 500;
    font-size: var(--text-sm, 0.875rem);
    border-bottom: 2px solid transparent;
    transition: all var(--duration-fast, 150ms);
}
/* end of 17.6.3 */
/* 17.6.4 Active + hover — navy text + gold underline */
body.profile-dashboard-active #subnav li.current a,
body.profile-dashboard-active #subnav li a:hover {
    color: var(--color-navy, #031B83);
    border-bottom-color: var(--color-gold, #CC9900);
}
/* end of 17.6.4 */
/* end of 17.6 */

/* 17.7 Global dashboard content centering
   Headings, empty-state messages, and descriptions should be centered.
   Content blocks (forms, tables, message threads) stay left-aligned. */

/* 17.7.1 Center page-level headings inside the dashboard body */
body.profile-dashboard-active #item-body .col-inner > h2,
body.profile-dashboard-active #item-body .col-inner > h3,
body.profile-dashboard-active #item-body .col-inner > .profile > h2,
body.profile-dashboard-active #item-body .col-inner > .profile > h3,
body.profile-dashboard-active #item-body h2:first-of-type,
body.profile-dashboard-active .bp-feedback,
body.profile-dashboard-active .info,
body.profile-dashboard-active #message {
    text-align: center;
}

/* 17.7.2 Center empty-state / info messages */
body.profile-dashboard-active #item-body .col-inner p:only-child,
body.profile-dashboard-active .bp-template-notice,
body.profile-dashboard-active #message p {
    text-align: center;
}

/* 17.7.3 Messages sub-nav — tighter spacing so all tabs fit on one line */
/* 17.7.3.1 Subnav items — tighter right margin */
body.profile-dashboard-active #subnav li {
    margin-right: var(--space-sm, 8px);
}
/* end of 17.7.3.1 */
/* 17.7.3.2 Subnav links — tighter padding + smaller font */
body.profile-dashboard-active #subnav li a {
    padding: var(--space-xs, 4px) var(--space-sm, 8px);
    font-size: 0.82rem;
}
/* end of 17.7.3.2 */
/* end of 17.7.3 */

/* 17.7.4 Reduce dead space between sidenav card and page content */
/* 17.7.4.1 Workspace children — kill top margin */
body.profile-dashboard-active #item-body .col-inner > *:not(.dashboard-sidenav):not(.profile-editor-wrapper):not(.profile-customise-cta) {
    margin-top: 0;
}
/* end of 17.7.4.1 */
/* 17.7.4.2 First-of-type h2 — small breathing space */
body.profile-dashboard-active #item-body .col-inner > h2:first-of-type,
body.profile-dashboard-active #item-body .col-inner > .profile > h2:first-of-type {
    margin-top: var(--space-sm, 8px);
}
/* end of 17.7.4.2 */
/* end of 17.7.4 */

/* 17.7.5 Suggestions page — center heading and description */
body.profile-dashboard-active .suggestions-form-wrap h2,
body.profile-dashboard-active .suggestions-form-wrap > p {
    text-align: center;
}

/* 17.7.9 SW4 h2 font-size ladder (S67 Phase 9, Rob 2026-04-18):
   22px for laptop/desktop (≥1024), 20px for tablet/mobile (<1024).
   Scoped to workspace content h2 (inside .col-inner) — banner h2 in
   cover-image-header.php is outside .col-inner so this rule doesn't touch it. */
body.profile-dashboard-active #item-body .col-inner h2 {
    font-size: 22px;
}
@media (max-width: 1023px) {
    body.profile-dashboard-active #item-body .col-inner h2 {
        font-size: 20px;
    }
}

/* 17.7.6 Notifications — center empty messages */
body.profile-dashboard-active .notifications-empty,
body.profile-dashboard-active .bp-feedback.bp-messages.info {
    text-align: center;
    padding: 24px 16px;
}

/* 17.7.7 Mark All Read button fix — apply brand styling */
body.profile-dashboard-active .notification-actions .mark-read-btn,
body.profile-dashboard-active .action.mark-read a,
body.profile-dashboard-active a[href*="action=read"],
body.profile-dashboard-active .generic-button a.mark-read {
    background: var(--color-navy, #031B83) !important;
    color: var(--color-gold, #CC9900) !important;
    border: 2px solid var(--color-navy, #031B83) !important;
    border-radius: 9999px;
    padding: 6px 16px;
    font-weight: 600;
    text-decoration: none;
}

/* 17.7.8 Mobile: Messages sub-nav — horizontal scroll, no wrapping */
@media (max-width: 767px) {
    /* 17.7.8.1 Subnav container — flex scroll row */
    body.profile-dashboard-active #subnav,
    body.profile-dashboard-active #subnav ul {
        display: flex !important;
        flex-wrap: nowrap !important;
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch;
        gap: 0;
        padding-bottom: 4px;
    }
    /* end of 17.7.8.1 */
    /* 17.7.8.2 Subnav items — no shrink, nowrap */
    body.profile-dashboard-active #subnav li {
        margin-right: 2px;
        flex-shrink: 0;
        white-space: nowrap;
    }
    /* end of 17.7.8.2 */
    /* 17.7.8.3 Subnav links — tight padding, smaller font */
    body.profile-dashboard-active #subnav li a {
        padding: 3px 6px;
        font-size: 0.78rem;
    }
    /* end of 17.7.8.3 */
    /* 17.7.8.4 Hide WebKit scrollbar */
    /* Hide scrollbar but keep scroll functional */
    body.profile-dashboard-active #subnav::-webkit-scrollbar,
    body.profile-dashboard-active #subnav ul::-webkit-scrollbar {
        display: none;
    }
    /* end of 17.7.8.4 */
    /* 17.7.8.5 Hide IE/Firefox scrollbar */
    body.profile-dashboard-active #subnav,
    body.profile-dashboard-active #subnav ul {
        -ms-overflow-style: none;
        scrollbar-width: none;
    }
    /* end of 17.7.8.5 */
}
/* end of 17.7.8 */

/* end of 17 */

/* ============================================================================
   18. SECTION: Notifications Feed Redesign
   ============================================================================ */

/* 18.1 Notifications container */
.notifications-feed {
    background: var(--color-surface, #FFFFFF);
    border-radius: var(--radius-lg, 12px);
    box-shadow: var(--shadow-sm, 0 1px 3px rgba(26, 26, 46, 0.08));
    overflow: hidden;
}

/* 18.1.1 Time group headers */
.notifications-group-header {
    font-family: var(--font-heading, 'Montserrat', sans-serif);
    font-weight: 700;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-muted, #6B7280);
    padding: var(--space-md, 12px) var(--space-lg, 16px) var(--space-xs, 4px);
    background: var(--color-surface, #FFFFFF);
    position: sticky;
    top: 0;
    z-index: 1;
}

/* 18.1.2 Notification item */
/* 18.1.2.1 Item base — flex row */
.notification-item {
    display: flex;
    align-items: flex-start;
    gap: var(--space-md, 12px);
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    border-bottom: 1px solid var(--color-border-light, #F3F4F6);
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 18.1.2.1 */

/* 18.1.2.2 Item hover — raised bg */
.notification-item:hover {
    background: var(--color-surface-raised, #F9F8F5);
}
/* end of 18.1.2.2 */

/* 18.1.2.3 Unread item — gold left border */
.notification-item.unread {
    background: var(--color-bg, #FDFCF9);
    border-left: 4px solid var(--color-gold, #CC9900);
    padding-left: calc(var(--space-lg, 16px) - 4px);
}
/* end of 18.1.2.3 */

/* 18.1.2.4 Read item — fade */
.notification-item.read {
    opacity: 0.75;
}
/* end of 18.1.2.4 */

/* 18.1.2.5 Icon circle */
.notification-icon {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--color-surface-raised, #F9F8F5);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--color-navy, #031B83);
}
/* end of 18.1.2.5 */

/* 18.1.2.6 Unread icon — gold filled */
.notification-item.unread .notification-icon {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
}
/* end of 18.1.2.6 */

/* 18.1.2.7 Content column */
.notification-content {
    flex: 1;
    min-width: 0;
}
/* end of 18.1.2.7 */

/* 18.1.2.8 Text */
.notification-text {
    font-size: 14px;
    color: var(--color-text, #1A1A2E);
    line-height: 1.4;
}
/* end of 18.1.2.8 */

/* 18.1.2.9 Strong emphasis — navy */
.notification-text strong {
    font-weight: 600;
    color: var(--color-navy, #031B83);
}
/* end of 18.1.2.9 */

/* 18.1.2.10 Timestamp */
.notification-time {
    font-size: 12px;
    color: var(--color-text-muted, #6B7280);
    margin-top: 2px;
}
/* end of 18.1.2.10 */
/* end of 18.1.2 */

/* 18.1.3 Mark all as read */
/* 18.1.3.1 Mark-all container */
.notifications-mark-all {
    display: flex;
    justify-content: center;
    padding: var(--space-md, 12px);
    border-top: 1px solid var(--color-border, #E5E7EB);
}
/* end of 18.1.3.1 */

/* 18.1.3.2 Mark-all button */
.notifications-mark-all button {
    background: transparent;
    border: none;
    color: var(--color-gold, #CC9900);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    padding: var(--space-xs, 4px) var(--space-md, 12px);
    border-radius: var(--radius-md, 8px);
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
}
/* end of 18.1.3.2 */

/* 18.1.3.3 Mark-all button hover — gold tint */
.notifications-mark-all button:hover {
    background: rgba(204, 153, 0, 0.1);
}
/* end of 18.1.3.3 */
/* end of 18.1.3 */

/* 18.2 BP notifications override */
/* 18.2.1 List container — strip default styling */
#buddypress .notification-list,
#buddypress #notifications-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
/* end of 18.2.1 */

/* 18.2.2 List items — flex row layout */
#buddypress .notification-list li,
#buddypress #notifications-list li {
    display: flex;
    align-items: flex-start;
    gap: var(--space-md, 12px);
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    border-bottom: 1px solid var(--color-border-light, #F3F4F6);
}
/* end of 18.2.2 */

/* 18.2.3 Unread items — gold left border */
#buddypress .notification-list li.unread,
#buddypress #notifications-list li.unread {
    background: var(--color-bg, #FDFCF9);
    border-left: 4px solid var(--color-gold, #CC9900);
}
/* end of 18.2.3 */

/* 18.2.4 Mark-read links — gold text */
#buddypress .mark-read,
#buddypress .mark-all-read {
    color: var(--color-gold, #CC9900);
    font-weight: 600;
}
/* end of 18.2.4 */
/* end of 18.2 */

/* end of 18 */

/* ============================================================================
   19. SECTION: Messages Toolbar — Search, Sort, Mark Read
   ============================================================================ */

/* 19.1 Toolbar container */
.messages-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-md, 12px);
    padding: var(--space-md, 12px) var(--space-lg, 16px);
    background: var(--color-surface, #FFFFFF);
    border: 1px solid var(--color-border-light, #F3F4F6);
    border-radius: var(--radius-lg, 12px);
    margin-bottom: var(--space-md, 12px);
    flex-wrap: wrap;
}

/* 19.1.1 Search input */
/* 19.1.1.1 Search wrapper */
.messages-toolbar-search {
    position: relative;
    flex: 1;
    min-width: 180px;
}
/* end of 19.1.1.1 */

/* 19.1.1.2 Search input */
.messages-toolbar-search input {
    width: 100%;
    padding: 8px 12px 8px 36px;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: var(--radius-md, 8px);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 14px;
    color: var(--color-text, #1A1A2E);
    background: var(--color-bg, #FDFCF9);
    transition: border-color var(--motion-fast, 150ms);
    box-sizing: border-box;
}
/* end of 19.1.1.2 */

/* 19.1.1.3 Search input focus — gold border + halo */
.messages-toolbar-search input:focus {
    outline: none;
    border-color: var(--color-gold, #CC9900);
    box-shadow: 0 0 0 3px rgba(204, 153, 0, 0.15);
}
/* end of 19.1.1.3 */

/* 19.1.1.4 Search icon — absolute positioned */
.messages-search-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-text-muted, #6B7280);
    font-size: 16px;
    pointer-events: none;
}
/* end of 19.1.1.4 */
/* end of 19.1.1 */

/* 19.1.2 Sort button */
/* 19.1.2.1 Sort toggle base */
.messages-sort-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 8px 12px;
    background: var(--color-surface-raised, #F9F8F5);
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: var(--radius-md, 8px);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 13px;
    font-weight: 600;
    color: var(--color-navy, #031B83);
    cursor: pointer;
    transition: all var(--motion-fast, 150ms);
    white-space: nowrap;
}
/* end of 19.1.2.1 */

/* 19.1.2.2 Sort toggle hover — gold fill */
.messages-sort-toggle:hover {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83); /* D055 */
    border-color: var(--color-gold, #CC9900);
}
/* end of 19.1.2.2 */

/* 19.1.2.3 Sort toggle icon */
.messages-sort-toggle .dashicons {
    font-size: 16px;
    width: 16px;
    height: 16px;
}
/* end of 19.1.2.3 */
/* end of 19.1.2 */

/* 19.1.3 Mark all read button */
/* 19.1.3.1 Mark-read button base */
.messages-mark-read {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 8px 12px;
    background: var(--color-navy, #031B83);
    border: 2px solid var(--color-navy, #031B83);
    border-radius: var(--radius-md, 8px);
    font-family: var(--font-body, 'Nunito Sans', sans-serif);
    font-size: 13px;
    font-weight: 600;
    color: var(--color-gold, #CC9900);
    cursor: pointer;
    transition: all var(--motion-fast, 150ms);
    white-space: nowrap;
}
/* end of 19.1.3.1 */

/* 19.1.3.2 Mark-read button hover — invert to gold */
.messages-mark-read:hover {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    border-color: var(--color-gold, #CC9900);
}
/* end of 19.1.3.2 */

/* 19.1.3.3 Mark-read button icon */
.messages-mark-read .dashicons {
    font-size: 16px;
    width: 16px;
    height: 16px;
}
/* end of 19.1.3.3 */

/* 19.1.3.4 Mark-read button disabled */
.messages-mark-read:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}
/* end of 19.1.3.4 */
/* end of 19.1.3 */

/* 19.2 Mobile responsive */
@media (max-width: 600px) {
    /* 19.2.1 Toolbar — stack column */
    .messages-toolbar {
        flex-direction: column;
        align-items: stretch;
    }
    /* end of 19.2.1 */
    /* 19.2.2 Search — drop min-width */
    .messages-toolbar-search {
        min-width: unset;
    }
    /* end of 19.2.2 */
    /* 19.2.3 Sort + mark-read — left-aligned */
    .messages-toolbar-sort,
    .messages-mark-read {
        align-self: flex-start;
    }
    /* end of 19.2.3 */
}
/* end of 19.2 */

/* end of 19 */

/* ============================================================================ */
/* 20. Image Reposition Mode (T171) */
/* ============================================================================ */

/* 20.1 Cover reposition button — next to camera button */
/* 20.1.1 Cover reposition button base */
.profile-cover-reposition-btn {
    position: absolute;
    top: var(--space-md, 12px);
    right: 60px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.2);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.3);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
    z-index: 2;
}
/* end of 20.1.1 */
/* 20.1.2 Cover reposition button hover */
.profile-cover-reposition-btn:hover {
    background: rgba(255, 255, 255, 0.35);
}
/* end of 20.1.2 */
/* 20.1.3 Cover reposition button icon */
.profile-cover-reposition-btn .dashicons {
    font-size: 18px;
    width: 18px;
    height: 18px;
}
/* end of 20.1.3 */
/* end of 20.1 */

/* 20.2 Avatar reposition button — next to camera button */
/* 20.2.1 Avatar reposition button base */
.profile-avatar-reposition-btn {
    position: absolute;
    bottom: 8px;
    right: 48px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    /* S207 05/09/26, Rob item A4: dark gold FILLED buttons become light cream with a gold border and navy content, darker cream on hover and select. Was a gold fill with a white ring. */
    background: var(--color-cream, #FFFBE6);
    border: 2px solid var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--motion-fast, 150ms) var(--motion-ease, cubic-bezier(0.16, 1, 0.3, 1));
    z-index: 6;
}
/* end of 20.2.1 */
/* 20.2.2 Avatar reposition button hover */
.profile-avatar-reposition-btn:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* end of 20.2.2 */
/* 20.2.3 Avatar reposition button icon */
.profile-avatar-reposition-btn .dashicons {
    font-size: 14px;
    width: 14px;
    height: 14px;
}
/* end of 20.2.3 */
/* end of 20.2 */

/* 20.3 Reposition mode — active state */
/* 20.3.1 Active z-index */
.reposition-mode {
    z-index: 100;
}
/* end of 20.3.1 */
/* 20.3.2 Cover image active outline */
#item-header-cover-image.reposition-mode {
    outline: 3px solid var(--color-gold, #CC9900);
    outline-offset: -3px;
}
/* end of 20.3.2 */
/* 20.3.3 Disable text selection while dragging */
.reposition-active {
    user-select: none;
    -webkit-user-select: none;
}
/* end of 20.3.3 */
/* end of 20.3 */

/* 20.4 Reposition toolbar — save/cancel buttons */
/* 20.4.1 Toolbar container */
/* T276: Cover reposition bar at top of banner, not overlapping content */
.reposition-toolbar {
    position: absolute;
    bottom: 16px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    padding: 8px 16px;
    border-radius: 8px;
    z-index: 110;
    white-space: nowrap;
}
/* end of 20.4.1 */
/* 20.4.2 Hint text */
.reposition-hint {
    font-family: 'Montserrat', sans-serif;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    margin-right: 8px;
}
/* end of 20.4.2 */
/* 20.4.3 Save + cancel button base */
.reposition-save-btn,
.reposition-cancel-btn {
    font-family: 'Montserrat', sans-serif;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 6px 16px;
    border-radius: 4px;
    border: none;
    cursor: pointer;
    transition: opacity 0.15s;
}
/* end of 20.4.3 */
/* 20.4.4 Save button — gold filled */
.reposition-save-btn {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
}
/* end of 20.4.4 */
/* 20.4.5 Save button hover — fade */
.reposition-save-btn:hover {
    opacity: 0.85;
}
/* end of 20.4.5 */
/* 20.4.6 Cancel button — translucent outline */
.reposition-cancel-btn {
    background: transparent;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.4);
}
/* end of 20.4.6 */
/* 20.4.7 Cancel button hover — translucent fill */
.reposition-cancel-btn:hover {
    background: rgba(255, 255, 255, 0.1);
}
/* end of 20.4.7 */
/* end of 20.4 */

/* 20.5 Photo reset button — S76 Rob: always visible (no hover-gate), white
   circle with gold border + navy icon so it reads on any image. Click = reset
   photo position to 50/50 centre. Drag the image itself to reposition (no
   toolbar mode). */
/* 20.5.1 Reset button base */
.photo-reposition-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 28px;
    height: 28px;
    min-width: 28px;
    min-height: 28px;
    max-width: 28px;
    max-height: 28px;
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    line-height: 1;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    background: #FFFFFF;
    border: 2px solid #CC9900;
    color: #031B83;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
    opacity: 1;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
    transition: background 0.15s, color 0.15s;
}
/* end of 20.5.1 */
/* 20.5.2 Reset button hover — invert to navy */
.photo-reposition-btn:hover {
    background: #031B83;
    color: #CC9900;
}
/* end of 20.5.2 */
/* 20.5.3 Reset button icon */
.photo-reposition-btn .dashicons {
    font-size: 14px;
    width: 14px;
    height: 14px;
    line-height: 1;
}
/* end of 20.5.3 */
/* end of 20.5 */

/* 20.6 Photo panel reposition mode */
/* 20.6.1 (removed S199 31/08/26, Rob) the active outline.
   "When you click to reposition, it gains a new gold border. Doesn't have to do that. The
   reposition bubble changes to a 'revert' icon and that'll do as an indicator."
   It was a 2px gold outline inset over the widget's own 2px gold border, so entering
   reposition mode read as the panel growing a second, thicker frame. The icon swap is the
   indicator now. */
/* end of 20.6.1 */
/* 20.6.2 Drag cursor */
.photo-panel-content.reposition-active img {
    cursor: grab;
}
/* end of 20.6.2 */
/* 20.6.3 Active drag cursor */
.photo-panel-content.reposition-active img.dragging {
    cursor: grabbing;
}
/* end of 20.6.3 */
/* 20.6.4 Reposition toolbar container */
/* S76 Rob feedback — reposition toolbar: cream bg (not navy — too heavy and
   dark), slimmer, sits directly BELOW the panel (outside it, top:100%+6px),
   so it never overlays the photo. Buttons vertically centred via flex. */
.photo-reposition-toolbar {
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--color-cream, #FFFBE6);
    border: 2px solid var(--color-gold, #CC9900);
    box-shadow: 0 2px 8px rgba(3, 27, 131, 0.15);
    padding: 4px 8px;
    border-radius: 9999px;
    z-index: 10;
    white-space: nowrap;
}
/* end of 20.6.4 */
/* 20.6.5 Toolbar button base */
.photo-reposition-toolbar button {
    font-family: 'Montserrat', sans-serif;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    padding: 3px 10px;
    border-radius: 9999px;
    border: 2px solid transparent;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    line-height: 1.2;
}
/* end of 20.6.5 */
/* 20.6.6 Save button — gold filled */
.photo-reposition-toolbar .reposition-save-btn {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
    border-color: var(--color-gold, #CC9900);
}
/* end of 20.6.6 */
/* 20.6.7 Save button hover — invert to navy */
.photo-reposition-toolbar .reposition-save-btn:hover {
    background: var(--color-navy, #031B83);
    color: var(--color-gold, #CC9900);
}
/* end of 20.6.7 */
/* 20.6.8 Reset button — gold outline */
.photo-reposition-toolbar .reposition-reset-btn {
    background: transparent;
    color: var(--color-gold, #CC9900);
    border-color: var(--color-gold, #CC9900);
}
/* end of 20.6.8 */
/* 20.6.9 Reset button hover — gold fill */
.photo-reposition-toolbar .reposition-reset-btn:hover {
    background: var(--color-gold, #CC9900);
    color: var(--color-navy, #031B83);
}
/* end of 20.6.9 */
/* 20.6.10 Cancel button — navy outline */
.photo-reposition-toolbar .reposition-cancel-btn {
    background: transparent;
    color: var(--color-navy, #031B83);
    border-color: var(--color-navy, #031B83);
}
/* end of 20.6.10 */
/* 20.6.11 Cancel button hover — navy fill */
.photo-reposition-toolbar .reposition-cancel-btn:hover {
    background: var(--color-navy, #031B83);
    color: var(--color-gold, #CC9900);
}
/* end of 20.6.11 */
/* end of 20.6 */

/* 20.7 T190 S53-036 — Reposition toolbar small-viewport polish
   At narrow mobile widths (<480px), the nowrap toolbar with hint text + two
   buttons pushes off-screen. Allow wrap, cap width to the container, shrink
   hint text, and tighten padding so it stays usable down to the 360px floor. */
@media (max-width: 480px) {
    /* 20.7.1 Cover reposition toolbar — wrap + tighten padding */
    .reposition-toolbar {
        max-width: calc(100% - 24px);
        flex-wrap: wrap;
        justify-content: center;
        padding: 6px 12px;
        gap: 6px;
    }
    /* end of 20.7.1 */
    /* 20.7.2 Reposition hint — full-row centred, smaller text */
    .reposition-hint {
        flex-basis: 100%;
        text-align: center;
        margin-right: 0;
        font-size: 11px;
    }
    /* end of 20.7.2 */
    /* 20.7.3 Save/cancel buttons — smaller font + tighter padding */
    .reposition-save-btn,
    .reposition-cancel-btn {
        font-size: 11px;
        padding: 5px 12px;
    }
    /* end of 20.7.3 */
    /* 20.7.4 Photo reposition toolbar — wrap + tighter padding */
    .photo-reposition-toolbar {
        max-width: calc(100% - 8px);
        flex-wrap: wrap;
        padding: 3px 6px;
    }
    /* end of 20.7.4 */
    /* 20.7.5 Photo reposition toolbar buttons — smaller font + tighter padding */
    .photo-reposition-toolbar button {
        font-size: 9px;
        padding: 2px 6px;
    }
    /* end of 20.7.5 */
}
/* end of 20.7 */

/* end of 20 */

/* S158 29/07/26 (D-326) — the party picker's consent note. Political affiliation is
   Article 9 special-category data, so the member has to be told what turning it on does
   BEFORE they turn it on. Two sentences, inside the popup, above the list. */
/* S213 08/09/26, Rob on the Political Party picker: "The gold section at the top doesn't have a
   top border and doesn't go full to the sides." Both true when measured: it carried a gold rule on
   the BOTTOM only, and it sat inset by the popup's own 10px padding on each side, so it read as a
   floating block instead of a band across the card. The negative margins cancel that padding so it
   runs edge to edge, and the horizontal padding is raised to keep the text off the border. */
.sigil-chooser-note {
    margin: 0 -10px;
    padding: 10px 24px 12px;
    font-family: 'Nunito Sans', sans-serif;
    font-size: 12px;
    line-height: 1.5;
    color: #031B83;
    background: #FFFBE6;
    text-align: center;   /* S213 08/09/26, Rob: the description should be centred. */
    border-top: 1px solid #CC9900;
    border-bottom: 1px solid #CC9900;
}

/* ============================================================================
   THE STANDARD FIRST-VISIT WELCOME POPUP
   S188 23/08/26 Rob (T-S187-018). Its own styling rather than borrowed classes.

   It first shipped reusing the .uks-dialog-* classes from mu-plugins/uksocials-dialog.php,
   which look right and are already this editor's branded overlay. Driven as cold_std18, the
   card rendered at top:626 left:93 - static flow, not centred - because that helper injects
   its stylesheet inside build(), which only runs when the API actually opens a dialog. The
   page had the helper's script five times over and window.uksDialog defined, and still no
   #uks-dialog-style element, because nothing had opened a dialog. Markup that borrows classes
   whose injection it does not control is styled by luck; LB-315 in a new costume.

   Values are copied from that helper deliberately, so the two overlays stay identical to look
   at, but this component now owns them and cannot be un-styled by something else's timing.
   ============================================================================ */
.uks-std-intro{
    position: fixed;
    inset: 0;
    z-index: 2147483000;
    display: none;              /* the inline script flips this to flex */
    align-items: center;
    justify-content: center;
    background: rgba(3, 27, 131, 0.35);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    padding: 20px;
    opacity: 0;
    transition: opacity .18s ease;
}
.uks-std-intro.is-open{ opacity: 1; }
.uks-std-intro .uks-dialog-card{
    background: #fff;
    border: 1.5px solid #CC9900;
    border-radius: 16px;
    box-shadow: 0 8px 24px rgba(3, 27, 131, 0.18);
    /* Wider than the 420px confirm card: this one carries two lists, and at 420 the
       longer lines wrapped to three rows each and the card ran past a short laptop. */
    max-width: 520px;
    width: 100%;
    max-height: calc(100vh - 40px);
    overflow-y: auto;
    padding: 26px 24px 22px;
    font-family: "Nunito Sans", sans-serif;
    text-align: center;
    transform: translateY(8px);
    transition: transform .18s ease;
}
.uks-std-intro.is-open .uks-dialog-card{ transform: none; }
.uks-std-intro .uks-dialog-title{
    font-family: "Montserrat", sans-serif;
    font-weight: 700;
    font-size: 16px;
    color: #031B83;
    margin: 0 0 8px;
}
.uks-std-intro .uks-dialog-msg{
    font-family: "Nunito Sans", sans-serif;
    font-size: 14.5px;
    line-height: 1.5;
    color: #031B83;
    margin: 0 0 20px;
}
.uks-std-intro .uks-dialog-msg li{ margin: 0 0 4px; }
/* align-items:center, not the default stretch: the theme's margin on <button> makes that
   item's MARGIN box the tallest thing on the line, and stretch then pulls the <a> to match it. */
.uks-std-intro .uks-dialog-actions{
    display: flex;
    gap: 10px;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
}
/* Rob, 23/08/26: "the buttons should be the same dimensions".
   They were not, and it was not the padding: one is an <a> and one is a <button>, so they
   disagreed on line-height, on default font, and on box-sizing. Matching the padding alone
   leaves them different heights. Made identical by taking every size decision away from the
   element type: inline-flex centring, an explicit line-height, border-box, and a shared
   min-width so the shorter label cannot make a narrower button. */
.uks-std-intro .uks-dialog-btn{
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 170px;
    min-height: 44px;
    padding: 9px 20px;
    font-family: "Montserrat", sans-serif;
    font-weight: 700;
    font-size: 14px;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    border: 1.5px solid #CC9900;
    border-radius: 10px;
    background: #FFFBE6;
    color: #031B83;
    cursor: pointer;
    /* Seeko's own stylesheet puts margin-bottom:1rem on EVERY <button>, so the button's
       margin box was 62px against the anchor's 44px and the flex row stretched the anchor to
       match - measured 18px of height difference and 9px of midpoint offset, which is the S89
       margin-box signature exactly (same class as the minimize buttons fixed in S187). Zeroing
       the margin here is what makes the two boxes genuinely identical. */
    margin: 0;
    transition: background .15s ease, color .15s ease;
}
.uks-std-intro .uks-dialog-btn:hover{ background: #031B83; color: #CC9900; }
.uks-std-intro .uks-dialog-btn--ghost{ background: #fff; }
