/**
 * 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;
    }
}

/* S222 14/09/26 (T-S216-073). Rob, by AskUserQuestion: "Editor preview to 1318". The Widescreen
   workspace drew its grid 22px wider than the public profile, so a layout built here did not land
   in the same pixels publicly. Measured live at 1920 on cold_prem19: editor grid CONTENT 1340.00px,
   public .profile-grid-public content 1318.00px. The grid's width itself is calc(100% - 76px) in
   profile-system.php's inline block (the other lane's file), so this caps the BOX instead: 1342
   less 2x10px padding and 2x2px border leaves the content at exactly 1318. It binds only at
   Widescreen, because the Desktop, Tablet and Mobile preview sizes cap .editor-content at 1280,
   768 and 360, all far below it. The cover banner above stays 1440px, which is the same
   relationship the public profile page already has (banner 1440, grid 1318). */
.profile-editor-wrapper #profile-grid {
    max-width: 1342px;
}

.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. */
/* S217 (CUST-27, Rob): the JS matches this bar's width to the preview-size bar above it, and
   `space-between` then throws the buttons to opposite ends whenever there are fewer of them
   than the width was sized for. On Standard that is two buttons totalling 199px inside 439px,
   so they sat 240px apart. Sizing to content and centring fixes every tier at once: the
   five-button tiers already filled the bar, so they move by under half a pixel. */
.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;
    width: auto !important;
    justify-content: center !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. */
/* S220 14/09/2026, T-S218-057. Rob: "Those top knobs all look terrible. Let's do this
   properly. Let's give them all the white backgrounds and the buttons are all also white
   backgrounds and light cream on hover or select." So the three panels are white, every
   button in them is white at rest, and the one cream is the LIGHT cream on hover and on the
   selected state. The dark cream #FFF5CC is gone from this family. Gold borders throughout,
   per D-484. Changed at source in each rule, not stacked on top. */
.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: #ffffff;
    border: 2px solid #CC9900;
    border-radius: 10px;
}
.device-selector > * {
    align-self: center;
}
/* S217 (CUST-31, Rob: "the preview-size buttons are not aligned with the words Preview
   size"). Measured as painted ink in ONE frame at eight times scale: the label sat 0.125px
   above the row centre, the buttons 0.5px below, so the two were 0.625px out of line with
   each other. Each is corrected to the row centre by its own measured amount. */
.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;
    transform: translateY(0.125px);
}
/* 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: 10px;
    background: #ffffff;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: 'Montserrat', sans-serif;
    font-size: 12px;
    font-weight: 700;
    color: #031B83;
    outline: none;
    transform: translateY(-0.5px);
}
.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: #FFFBE6;
}
.device-btn:hover .dashicons {
    color: #031B83;
}
html[data-nav="kbd"] .device-btn:focus,
html[data-nav="kbd"] .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: #FFFBE6 !important;
    border-color: #CC9900 !important;
    color: #031B83 !important;
}
.device-btn:active .dashicons {
    color: #031B83 !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: #FFFBE6 !important;
    color: #031B83 !important;
    box-shadow: none !important;
}
.device-selector .device-btn.active .dashicons,
.device-btn.active .dashicons {
    color: #031B83 !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;
}

/* S222 14/09/26 (T-S221-010 F4, D-503 and D-535): the preview frames above set the DEVICE width,
   which is right, but the grid inside them did not match what the public profile actually gives a
   widget at that width, so a layout built at Desktop, Tablet or Mobile did not land in the same
   pixels. The column carries 24px of its own padding and the grid is calc(100% - 76px) of it
   (profile-system.php's inline block, the other lane's), which left the grid 178px too wide at
   Desktop and 46px and 53px too narrow at Tablet and Mobile.

   MEASURED on cold_prem19's live PUBLIC profile, .profile-grid-public content width:
       1280 -> 978    768 -> 690    360 -> 289    (1920 -> 1318, already matched by section 56's
   sibling rule below). Each frame's grid is therefore pinned to its own public figure plus the
   grid's 2x10 padding and 2x2 border, and each still fits inside its frame's content box
   (1256 / 744 / 336). Widescreen is untouched.

   The ID is in each selector on purpose, and so is !important: the rule these outrank is
   `.profile-editor-wrapper .editor-content > #profile-grid { width: calc(100% - 76px) !important }`
   in profile-system.php's inline block (the other lane's), so specificity alone cannot win it.
   Read off the live page, not assumed. */
.profile-editor-wrapper.device-desktop .editor-content > #profile-grid {
    width: 1002px !important;
    max-width: 100%;
}
.profile-editor-wrapper.device-tablet .editor-content > #profile-grid {
    width: 714px !important;
    max-width: 100%;
}
.profile-editor-wrapper.device-mobile .editor-content > #profile-grid {
    width: 313px !important;
    max-width: 100%;
}
/* 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: #ffffff !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 10px;
    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;
/* S232 21/09/2026, Rob correction row 13: "Those buttons should also all have a drop shadow in
   the static pre-pressed state now too, and if it's a gold border, then it should be the gold drop
   shadow - that standard is already used somewhere else." The standard copied here, unchanged, is
   page-polish.css 30.3.2 and 30.7.2.2: 0 4px 12px rgba(204, 153, 0, 0.18). The gold edge on this
   toolbar is an INSET box-shadow rather than a border, so every state that wants an edge must
   restate it. Rest and hover carry edge plus drop shadow; press and busy keep the edge, drop the
   shadow and take the cream. */
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    transform: translateY(-1px) !important;
}

.btn-save:hover {
    transform: translateY(-1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}

.btn-save:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !important;
    background: #FFFBE6 !important;
    color: #031B83 !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 {
    /* S222 item 3 (Rob, 14/09/2026): "Now the spacing is fine, but it just looks greyed out, and
       I do not like that on the saving." MEASURED BEFORE, from the painted pixels while a real
       save was in flight: the label painted rgb(90,107,154) on white, 5.24 to 1. That passes AA
       and still reads grey, which is what he was looking at, so the mute itself is the fault and
       not its weight. Item 43 settles what replaces it: "Saving should be shown the same
       everywhere and it should not grey out. You can use whatever has been verified somewhere
       else in the site as the token styling." That token is 46.Z in page-polish.css: the disabled
       look is visually identical to the active one and the label text change is the feedback.
       MEASURED AFTER: rgb(3,27,131) on white, 14.11 to 1, the same as the resting button.
       opacity stays pinned at 1: Seeko's own button:disabled fades to .65 and opacity applies to
       the whole group, which is what washed out the status text below this button (LB-334).
       The shadow stays off so an in-flight button does not read as pressable. */
    /* S229 16/09/26 (T-S229-033), Rob with his own screenshot: "the state of the saving button
       is broken to the point where it literally disappears when you click save". The cause was
       here: the resting button's gold edge is an INSET box-shadow (see .btn-save above), and
       this rule cleared box-shadow outright, so a white button lost its only edge on a white
       bar. The edge is kept and the face takes the platform's busy cream (his rule on the Get a
       new code button: a busy button shows light cream and no lift), so the button stays
       visible, reads as pressed in, and the label still says Saving. */
    opacity: 1 !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
    box-shadow: inset 0 0 0 2px #CC9900 !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: #C41C1C !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: #ffffff !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 10px;
    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;
    /* S232 row 13: same states as .btn-save above. */
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    transform: translateY(-1px) !important;
}

.btn-reset:hover {
    transform: translateY(-1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}

.btn-reset:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}

/* Toolbar buttons. S219 (Rob 10/09/26): light cream at rest, dark cream on hover, press and when on,
   gold ring and navy text, the same family as the Background chips and the Preview size buttons. */
/* Glass toggle */
.btn-glass {
    background: #ffffff !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 10px;
    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;
    /* S232 row 13: same states as .btn-save above. */
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    transform: translateY(-1px) !important;
}

.btn-glass:hover {
    transform: translateY(-1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}

.btn-glass:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}

.btn-glass.active {
    background: #FFFBE6 !important;
    color: #031B83 !important;
    border: none !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    transform: translateY(-1px) !important;
}

/* S232 row 13: the on state's hover and press painted a black and navy shadow with no gold edge
   at all, so the toggle lost its border the moment it was touched. Both now hold the edge. */
.btn-glass.active:hover {
    transform: translateY(-1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
}

.btn-glass.active:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !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: #ffffff !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 10px;
    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;
    /* S232 row 13: same states as .btn-save above. */
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    transform: translateY(-1px) !important;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.btn-color-picker .dashicons {
    font-size: 13px;
    width: 13px;
    height: 13px;
    line-height: 13px;
}
.btn-color-picker:hover {
    transform: translateY(-1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}
.btn-color-picker:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}
.btn-color-picker.active {
    background: #FFFBE6 !important;
    color: #031B83 !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
}
/* S232 row 13: the on state's press painted a black inner shadow with no gold edge. */
.btn-color-picker.active:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !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;
}
html[data-nav="kbd"] .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: 9px !important;
    padding-bottom: 9px !important;
}

/* Add Photo Panel button */
.btn-add-photo {
    background: #ffffff !important;
    color: #031B83 !important;
    border: none !important;
    padding: 9px 18px;
    border-radius: 10px;
    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;
    /* S232 row 13: same states as .btn-save above. */
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    transform: translateY(-1px) !important;
}

.btn-add-photo:hover {
    transform: translateY(-1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900, 0 4px 12px rgba(0, 0, 0, 0.16) !important;
    background: #FFFBE6 !important;
    color: #031B83 !important;
}

.btn-add-photo:active {
    transform: translateY(1px) !important;
    box-shadow: inset 0 0 0 2px #CC9900 !important;
    background: #FFFBE6 !important;
    color: #031B83 !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: #ffffff;
    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 #ffffff at rest and
   --color-cream-hover #FFFBE6 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, #ffffff);
    color: #031B83;
    cursor: pointer;
    font-family: 'Montserrat', sans-serif;
    transition: all 0.2s ease;
    line-height: 1 !important;
    margin: 0 !important;
    /* D-651 (S235 FIXER-SHADOWS-3, 24/09/26): the gold rest shadow. */
    box-shadow: var(--shadow-gold-hover);
}

/* D-651: pressed = cream-hover, no shadow. .active (the persistent "this one is chosen" state)
   already carries no box-shadow of its own, so it already meets "selected keeps its look, no
   shadow" without an edit. */
/* Scoped #buddypress: a bare .bg-chip:active is specificity (0,2,0), which LOSES to Seeko's
   site-wide button:not([disabled]):not(.disabled):active at (0,3,1) - confirmed live on the
   sibling button.pf-badge:active fix, background painted grey #eee not cream-hover. This page
   has no .workspace wrapper (unlike the classic BuddyPress panes), so #buddypress alone (an id,
   beating any number of classes) is the scope-bump here. */
#buddypress .bg-chip:active {
    background: var(--color-cream-hover, #FFF5CC);
    box-shadow: none;
}

.bg-chip:hover {
    border-color: #CC9900;
    background: var(--color-cream-hover, #FFFBE6);
    color: #031B83;
}

.bg-picker .bg-chip.active,
.bg-chip.active {
    background: var(--color-cream-hover, #FFFBE6) !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, #ffffff);
    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: #C41C1C; }

/* ============================================================
   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. */
/* S224 14/09/26, item 218. Rob: "the workspace on the customize page should be white with a
   gold border, and then the profile on the public-facing page should be white with a gold
   border - They should be the same and they should not be this bluey grey." The border and
   radius were already here; the workspace was TRANSPARENT, so it took the page's own
   rgb(248,248,248) and read as grey. Scoped away from a member's chosen background. */
.profile-editor-wrapper .profile-grid {
    border: 2px solid #CC9900;
    border-radius: 12px;
    padding: 28px 12px 12px;
}
.profile-editor-wrapper .profile-grid:not([data-bg]) {
    background: #FFFFFF;
}
/* S224 14/09/26, item 218, the public half of the same ruling. The border and padding stay at
   ZERO on purpose: the grid is box-sizing border-box and its width is pinned to the editor's
   own figures (1318 / 978 / 690 / 289, T-S221-010 F4), so a real 2px border would take 4px off
   the content and break that match. An OUTLINE draws the same gold edge at the same 12px radius
   and takes part in no layout at all, so the measured content width does not move. */
/* S231 18/09/26 (triage item 22), Rob: "If the profile is blank, then just show the warning on its
   own card, don't show the blank profile... drop the outer outline when the grid is empty." The
   frame and the white fill are excluded when the grid carries the not-customised state, so the
   nudge card stands alone instead of sitting in a gold box inside a gold box. */
.profile-public-wrapper .profile-grid:not(.profile-grid--not-customised),
body.bp-user .profile-grid-public:not(.profile-grid--not-customised) {
    border: 0 !important;
    padding: 0 !important;
    outline: 2px solid #CC9900;
    border-radius: 12px;
}
.profile-public-wrapper .profile-grid:not([data-bg]):not(.profile-grid--not-customised),
body.bp-user .profile-grid-public:not([data-bg]):not(.profile-grid--not-customised) {
    background: #FFFFFF;
}

.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 */
    /* S217 09/09/2026 (D-503, Rob: the design grid is the same 48 columns at every screen size,
       proportionally thinner). The row height and the gap now come from custom properties the
       public breakpoint script sets from the grid's own measured width, using the editor's own
       formula, so a visitor sees the proportions the member designed rather than a flat 10px at
       every width. The fallbacks are today's values, so nothing moves anywhere the properties
       are absent, including the editor itself until it sets them. */
    grid-auto-rows: var(--uks-grid-row, 10px);
    gap: var(--uks-grid-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;
    /* 25/09/2026 D-166 amendment, Rob: an invisible border must show nothing. This shadow was
       the only thing painting when a member's chosen border colour (D-166 picker) is white or
       otherwise matches the background - it read as the same faint border the quote bubble had
       (S235, this file). Removed at its source (Rule of one). */
    box-shadow: none;
    /* 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,
/* S231 18/09/26 (triage item 12): the organiser Specialities and venue Type pills used to be
   solid navy blocks with gold text and were exempted from this rule. They now take the platform
   pill - cream fill, gold border, navy text - so navy text is correct and no exemption is needed. */
/* 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-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;
}

/* S217 (CUST-12, Rob repeatedly: "they are not on the vertical center. Remember you're
   supposed to measure"). Measured as painted INK at eight times scale against the header
   box centre, every control in this row sat below the line and by a different amount, the
   minimise dash worst. The values below are the CONVERGED ones, reached by measuring the whole
   header in a single frame at eight times scale and correcting until every ink landed on the
   centre: dash 0.000, swatch 0.000, title 0.063, eye 0.063, all within a sixteenth of a pixel.
   The glyphs sit low inside their own line boxes, which is why symmetric padding on the header
   never fixed this. An earlier pass measured each control in its OWN screenshot and read every
   offset at roughly double: do not trust that method here, measure the row in one frame. */
.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;
    transform: translateY(-0.016px);
}

/* 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;
    /* S227 row 14 (C8 + T-S199-046 + CUST-12). Rob: "they are not on the vertical center.
       Remember you're supposed to use overlays and measure the ink, not the bounding box."
       MEASURED AT dpr 8 on /customise/ as cold_prem19 at 1280, from the PAINTED rows at 50
       per cent coverage, not from boxes. The header's content box centre is 449.031 and the
       three sibling glyphs paint on it: type icon 448.940, colour swatch 449.186, eye
       449.045, a spread of 0.245px. The minus painted at 446.313, so 2.744px HIGH of them,
       because U+2212 sits on the maths axis, above its own em box centre. With both of the
       old nudges removed it is 1.369px high, and that is the real intrinsic offset the
       "1.31px high" in the backlog row names. The correction belongs to the GLYPH, so it
       lives on this rule and the container nudge below is dropped with it - one owner.
       MEASURED AFTER, same drive: dpr 8 +0.006, dpr 4 +0.159, dpr 2 +0.140, dpr 1 +0.876.
       dpr 1 can only reach whole rows, and +0.876 is its nearest one; every ratio is closer
       than it was, which was -1.124 at dpr 1 and -2.860 at dpr 2. */
    /* S229 16/09/26, Rob on the live picture: "the minimize icon is not in the underscore
       position like it should be... None of the widgets show the icon at the bottom of the
       character space like an underscore where the minimize icon should be." The glyph is no
       longer centred on the header's own centre line: it is placed where an underscore paints,
       with its bar sitting ON the header label's baseline. MEASURED at dpr 8 on /customise/ as
       cold_prem19 at 1280, from the painted navy rows, not from boxes: the label's cap band ends
       (its baseline) at 457.250 and the minus bar painted 449.750 to 451.750, so 5.500px high of
       it. With translateY(6.875px) the bar paints 455.250 to 457.250, its bottom edge exactly on
       the baseline, +0.000. The other three glyphs are untouched and keep the centre line (eye
       450.062, swatch 450.000, calendar 450.250 against a header centre of 450.281). */
    transform: translateY(6.875px);
}

.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;
}

/* Standard chooses widgets but uses the automatic grid: do not advertise controls its
   client and server permissions deliberately refuse. Colour, visibility and minimise stay. */
.editor-tier-colours .drag-grip,
.editor-tier-colours .resize-handle,
.editor-tier-colours .quote-scale-lock-btn {
    display: none !important;
}
.editor-tier-colours .widget-drag-handle {
    cursor: default;
}

/* ============================================================
   Per-Widget Color Picker
   ============================================================ */

.quote-scale-lock-btn {
    width: 20px;
    height: 20px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: #031B83;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    line-height: 1;
}
.quote-scale-lock-btn:hover { color: #CC9900; transform: scale(1.15); }

/* 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;
    transform: translateY(-0.188px);
}

.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;
    transform: translateY(0.063px);
}

.widget-visibility-btn:hover {
    color: #CC9900;
    transform: scale(1.15);
}

/* Hide on the public-facing grid */
.profile-grid-public .widget-visibility-btn {
    display: none;
}
.profile-grid-public .quote-scale-lock-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;
    /* D-651 (S235 FIXER-SHADOWS-3, 24/09/26): "a selected chip keeps its selected look with no
       shadow" - was a gold ring (0 0 0 2px rgba(204,153,0,.3)); the border-colour above still
       carries the selected look. */
    box-shadow: none;
}

.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;
}
html[data-nav="kbd"] .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;
}
html[data-nav="kbd"] .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[data-widget-id="org_reputation"] > .widget-drag-handle.widget-header-public {
    display: flex !important;
}
/* S232 (Rob correction 24): "Organiser Reputation must retain its header and must not produce
   a border extending beyond the visible widget content." The header is the rule directly
   above. The border is this one: a public widget is a grid item that STRETCHES to the rows
   and columns the member's span claims, so a Reputation card whose content is one summary
   line and a few trait pills still draws its full gold card around a large empty area.
   MEASURED on the live site, 20/09/2026: every public business card on cold_ven30 ended
   about 62px below its own last painted pixel, and Venue Header ended 71px to the right of
   its own last painted pixel. Wrapping the card to its content is the treatment this file
   already gives the other content-sized public variants (the quote autofit and the sigil and
   party chrome strips), and it is scoped to the one widget Rob named so no other card in the
   row changes shape.
   The card wraps its content DOWNWARD only. A `width: max-content` was measured first and
   rejected: on a widget whose body lays its content out across the full width (the Attendance
   stats row, used as the stand-in because no organiser on the site has review data yet) the
   card came back 129.97px wide and the three labels overlapped each other. The Reputation body
   is block-level - a summary line and a row of trait pills - so it fills the width it is given
   and the only empty band is the one below it. */
.profile-grid-public .profile-widget[data-widget-id="org_reputation"] {
    align-self: start;
    height: auto;
}
.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: #031B83 !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 .quote-scale-lock-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. */
/* S227 row 14: the -1px is dropped for the ordinary widget header's minimise control, because
   the whole optical correction now sits on .widget-minimize-btn's own transform (see there),
   where it belongs: it is a property of the minus glyph, not of the container. Measured at
   dpr 8 with this -1px still in place the minus painted 2.744px high of its three siblings;
   without it, and with the transform corrected, it paints +0.006px. The photo panel's own
   controls are UNAFFECTED by either half: they keep the -1px, and the corrected transform
   cannot reach them because .photo-panel-handle .widget-minimize-btn pins transform to none
   with !important further down this file. .widget-delete-btn is untouched either way. The
   pickable pills DO take the transform (nothing there sets one) and it corrects them too. */
.widget-drag-handle .widget-minimize-btn {
    position: relative;
}
.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;
}
/* S229: the photo panel's own minimise takes the same underscore position as every other widget
   header (Rob: "None of the widgets show the icon at the bottom of the character space"). Its
   siblings keep the centre line and the panel's own -1px nudge above. */
.photo-panel-handle .widget-minimize-btn {
    transform: translateY(6.875px) !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;
}

/* S227 15/09/26, item 218. The spacer's glass override painted it rgba(235,240,255,0.7) with a
   rgba(200,215,255,0.4) edge and its grab bar rgba(220,230,255,0.5) - pale BLUE, measured on
   Rob's own profile at 360 and 1280, and the literal "bluey grey" of item 218. It was also
   beating the S79 rule that keeps the spacer invisible on the PUBLIC profile, because
   .glass-on .profile-widget[data-widget-id="spacer"] outranks .profile-widget-public[...].
   Removed, so S77's white pin with its 2px gold border is what shows on the customise page and
   S79's transparent, invisible pin is what shows on the public one. */

/* ============================================================
   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: #C41C1C;
    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.
   ============================================================ */

/* S217 (S217-V5, Rob 09/09/26 asked for a grid audit across every tier and breakpoint): the
   column count is 48 everywhere, but this rule was quietly undoing item 94. It sits after
   `.profile-editor-wrapper .profile-grid` with equal specificity, so its padding won on source
   order and any member who set a workspace background lost the 28px of top clearance the pill
   controls need. The public grid forces `padding: 0 !important` anyway, so this declaration only
   ever reached the editor, where it was never wanted. Removed rather than out-specified. */
.profile-grid[data-bg] {
    border-radius: 12px;
    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.
   ============================================================ */

/* S227 15/09/26, item 218, the half S224 did not do. Rob: "Why do the widgets look like that?
   Why are they not white backgrounds, gold borders, etcetera? ... They should be the same and
   they should not be this bluey grey." Glass mode was overriding his own S199 rule for the
   widget card - #fff with a 2px solid #CC9900 edge, which he asked for in the words "It should
   be the same border as the workspace itself" - with a 35 percent white fill and a 1px WHITE
   border, which over a white workspace is invisible. MEASURED on his own profile at 360 and
   1280: background rgba(255,255,255,0.35), border 1px rgba(255,255,255,0.4) on the customise
   page against 1px rgba(204,153,0,0.35) on the public page, so the two surfaces did not match
   either. The two declarations are REMOVED rather than overridden, so the base rule applies
   again and both surfaces read white with the same 2px gold edge. The blur and the glass
   shadow are untouched. */
.glass-on .profile-widget {
    backdrop-filter: blur(16px) saturate(1.2);
    -webkit-backdrop-filter: blur(16px) saturate(1.2);
    /* 25/09/2026 D-166 amendment, Rob: an invisible border must show nothing, same rule as the
       base .profile-widget wrapper above (line ~1127). The OUTER layer of this compound shadow
       painted a soft rectangle past the true edge, which is exactly the halo a white/invisible
       border must not show; the inset top highlight is kept because inset shadows are clipped
       to the padding box and can never paint outside the widget, so it was never the fault. */
    box-shadow: 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 questionnaire text out. Remove the halo and
   force brand navy + full opacity so the label stays readable when glass is on. */
.glass-on .widget-body {
    /* intentionally no text-shadow */
}
.glass-on .quest-label {
    color: #031B83 !important;
    opacity: 1 !important;
}
.glass-on .quest-pct {
    color: #031B83 !important;
}

/* When glass is on WITHOUT a background the S76 fallback painted a pale BLUE tint here,
   rgba(200,220,255,.25) to rgba(220,230,255,.15). That is the bluey grey Rob named in item 218
   on 14/09/26, and it is why HIS profile showed it and most test profiles did not: glass is a
   per-member setting and he has it on. It is now the same white as every other case. */
.glass-on .profile-grid:not([data-bg]) {
    background: #FFFFFF;
    border-radius: 12px;
}

/* 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);
    /* 25/09/2026 D-166 amendment, Rob: an invisible border must show nothing - same treatment as
       the .glass-on default variant above (line ~2993): the outer layer removed (it haloed past
       a white/invisible border on the dark background images this rule targets), the inset top
       highlight kept (inset shadows are clipped inside the box and cannot cause a halo). */
    box-shadow: 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: #ffffff;
    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, because dashicons has no
   fingers glyph. White disc, gold icon, per Rob.
   S227 15/09/2026: this used to draw the crossed-fingers EMOJI through the system's own emoji
   font, which D-332 bans and which looks different on every platform. It now draws the
   platform's OWN fingers glyph, the one uks_icon_fingers() already paints on the customise rail.
   See the ::before rule below. */
.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;
}
/* S227 15/09/2026, D-332: this drew a RAW EMOJI (U+1F91E, crossed fingers) through the
   system's own emoji font, which D-332 bans from the interface and which renders a different
   picture on every platform. Replaced with the platform's OWN crossed-fingers drawing, the one
   `uks_icon_fingers()` already paints on the customise rail, so nothing here is new artwork: it
   is the same glyph the member already sees two inches away. Painted at 14px inside the 20px
   white disc, which is the same ratio the rail uses. The emoji font stack goes with it. */
.icon-wishlist-fingers::before {
    content: "";
    width: 14px;
    height: 14px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M7.0 13.6 L14.4 4.0%22 stroke=%22%23031B83%22 stroke-width=%226.0%22 stroke-linecap=%22round%22/%3E%3Cpath d=%22M7.0 13.6 L14.4 4.0%22 stroke=%22%23CC9900%22 stroke-width=%223.4%22 stroke-linecap=%22round%22/%3E%3Cpath d=%22M14.0 13.6 L8.2 4.0%22 stroke=%22%23031B83%22 stroke-width=%226.0%22 stroke-linecap=%22round%22/%3E%3Cpath d=%22M14.0 13.6 L8.2 4.0%22 stroke=%22%23CC9900%22 stroke-width=%223.4%22 stroke-linecap=%22round%22/%3E%3Cpath d=%22M5.0 12.8h11.4c1.1 0 2.0.9 2.0 2.0v2.6c0 2.2-1.8 4.0-4.0 4.0H8.4c-1.9 0-3.4-1.5-3.4-3.4z%22 fill=%22%23CC9900%22 stroke=%22%23031B83%22 stroke-width=%221.5%22 stroke-linejoin=%22round%22/%3E%3Cpath d=%22M5.0 15.4c-1.2 0-2.1-.9-2.1-2.0s.9-2.0 2.1-2.0%22 fill=%22%23CC9900%22 stroke=%22%23031B83%22 stroke-width=%221.5%22 stroke-linejoin=%22round%22/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
}

/* 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 .uks-icon-pin-lock {
    transform: translate(-0.5px, -0.688px);
}
/* S217 (CUST-18, continued): the rail is eight circles, not two - six of them are
   .sigil-chooser-trigger and were never covered by the .sidebar-icon rules above. Measured the
   same way, one frame per circle at eight times scale, ink against the painted ring:
   store 0.063 high, megaphone 0.5 low and 0.063 left, awards 1.063 low (the one Rob saw),
   share 0.5 low and 0.25 left, star 0.5 low. Each corrected by its own amount. */
.sigil-chooser-trigger .dashicons-store { transform: translateY(0.063px); }
.sigil-chooser-trigger .dashicons-megaphone { transform: translate(0.063px, -0.5px); }
.sigil-chooser-trigger .dashicons-awards { transform: translateY(-1.063px); }
.sigil-chooser-trigger .dashicons-share { transform: translate(0.25px, -0.5px); }
.sigil-chooser-trigger .dashicons-star-filled { transform: translateY(-0.5px); }
.sigil-chooser-trigger .uks-icon-fingers { transform: translate(0.188px, 0.25px); }


.sidebar-icon:hover {
    background: #CC9900;
    border-color: #b8860b;
}

/* S217 (CUST-18, Rob: "rail icons are about 1px off horizontal centre"). Measured as painted
   ink against the painted circle at eight times scale: the pin-lock glyph sat 0.5px right and
   0.688px low, the interests star 0.563px low. Corrected by their own measured amounts. */
.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;
    transform: translateY(-0.563px);
}

.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. */
html[data-nav="kbd"] .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
   ============================================================ */

/* S222 item 5, Rob 14/09/2026: "We are now going for a standard 15 pixel padding
   around any text". Measured live on the customise page as cold_ven30 (three real
   empty widget bodies): the box had 16px top and bottom but only 8px each side, so
   no edge was 15. One symmetric 15px round the message. Measured after: gap from the
   box edge to the ink 15 / 15 / 16 / 17.4 at 1280, and .widget-body scrollHeight fell
   from 123 to 121 against a 92 clientHeight, so nothing new is clipped. */
.widget-empty {
    color: #031B83;
    font-style: italic;
    text-align: center;
    /* S232 (Rob correction 25): "Freely enlarged widgets must scale or reflow their content
       with the resized container." MEASURED on the live site, 20/09/2026, across three
       accounts: every widget with real content already grows - About Me 20 to 22.3px, the
       Attendance numbers 31.3 to 65.2px, Upcoming Events' rows 12 to 15.1px - and this one
       line does not. It held 14px at every size in six widgets: Upcoming Events and
       Reputation on cold_org24a, Capacity, Amenities, Price & Dress and Upcoming Events on
       cold_ven30, whose bodies ran from 207 to 289px at spawn and up to 23,000px enlarged.
       The pattern is S199's, above: max(<the size it spawns at>, <n>cqw), so 14px and 15px
       stay the floor and nothing renders smaller than it does on the day it is dropped
       (D-488, D-535). The percentages are taken against the WIDEST spawn body measured
       (289px), so the floor still wins at every spawn size and growth starts past it. */
    font-size: max(14px, 4.8cqw);
    padding: max(15px, 5.1cqw);
    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: max(20px, 8.824cqw);
    align-items: center;
    padding: max(6px, 2.647cqw) max(4px, 1.765cqw);
}

/* 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, 35.294cqw);
    height: max(80px, 35.294cqw);
    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: var(--wl-sigil, 60px);
    height: var(--wl-sigil, 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: max(28px, 13.249cqw);
    width: max(28px, 13.249cqw);
    height: max(28px, 13.249cqw);
    color: #CC9900;
}
.wishlist-sigil:hover {
    transform: scale(1.08);
    border-color: #CC9900;
}
.wishlist-sigil-name {
    position: absolute;
    top: calc(100% + max(6px, 2.839cqw));
    left: 50%;
    transform: translateX(-50%);
    background: #031B83;
    color: #CC9900;
    font-family: 'Montserrat', sans-serif;
    font-size: max(11px, 5.205cqw);
    font-weight: 700;
    padding: max(4px, 1.893cqw) max(8px, 3.785cqw);
    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: max(7px, 3.088cqw);
    /* S234 21/09/2026 (F-019, F-027): a flex item will not shrink below the widest unbreakable
       word inside it unless it is told it may, which is why a member whose name is one long word
       pushed this column, and the name with it, straight out through the right border of the
       About Me widget. Measured on n19 before the fix: the name ended 293px past the widget. */
    min-width: 0;
}

.bio-name {
    font-family: 'Montserrat', sans-serif;
    color: #031B83;
    /* S199: 20px floor, grows with the card. */
    font-size: max(20px, 8.824cqw);
    font-weight: 700;
    margin: 0;
    line-height: 1.2;
    /* S234 21/09/2026 (F-019, F-027, Rob): every display name the platform holds is a single
       unbroken word until a member sets one with a space in it, so the name has to be allowed to
       break inside a word. `anywhere` rather than `break-word` so the break is taken into account
       when the box is measured, which is what stops the column widening in the first place. */
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* 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: max(13px, 5.735cqw);
    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). */
/* D-652 25/09/2026, FIXER-SHADOWS-4: bottom padding was max(5px,2.206cqw), 1px more than the
   top - measured by ink at dpr 8 (Standard and Admin both -0.938px, text sitting HIGH, beyond
   the 0.5px tolerance). Symmetric top/bottom padding centres the label by ink. */
.bio-level {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: 'Montserrat', sans-serif;
    font-size: max(11px, 4.853cqw);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: max(4px, 1.765cqw) max(12px, 5.294cqw) max(4px, 1.765cqw);
    border-radius: 9999px; /* pill — stays 9999 per D090 pill exception */
    margin-top: max(4px, 1.765cqw);
    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/. */
/* D-652 25/09/2026, Rob: "all tier pills cream and gold." Replaces the per-tier tint palette
   above (B23/B24/B25 sign-off is superseded by this later, more specific ruling) with the same
   cream/gold-border/navy recipe as .tier-badge--free (page-polish.css 42.7). .badge-free was
   still the OLD grey (Rob, R3-06: "never agreed to grey anywhere") - this family was never
   touched by that earlier fix, only .tier-badge was. .badge-dating is added (was missing
   outright - Rule 13, a Dating member had bare text where the pill should be). */
.badge-free,       .bio-level.level-free       { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }
.badge-standard,   .bio-level.level-standard   { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }
.badge-premium,    .bio-level.level-premium    { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }
.badge-organiser,  .bio-level.level-organiser  { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }
.badge-venue,      .bio-level.level-venue      { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }
.badge-admin,      .bio-level.level-admin      { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }
.badge-dating,     .bio-level.level-dating     { background: var(--color-cream); color: var(--color-navy); border: 1px solid var(--color-gold); }

/* 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;
}

.widget-interests-list {
    gap: max(6px, 1.574cqw);
}

.widget-interests-list .interest-tag {
    gap: max(4px, 1.049cqw);
    padding: max(5px, 1.312cqw) max(12px, 3.149cqw);
    font-size: max(12px, 3.149cqw);
}

.widget-interests-list .interest-tag-personality {
    padding-inline: max(14px, 3.674cqw);
    font-size: max(11px, 2.887cqw);
}

.widget-interests-list .interest-tag-personality .interest-tag-emoji {
    font-size: max(14px, 3.674cqw);
}

/* 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: var(--quote-pad-y, 12px) var(--quote-pad-x, 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: var(--quote-radius, 12px);
    /* S235 25/09/26 Rob: this shadow was the only thing painting when no border
       colour is set (or one is set to white) - it read as the faint border he should
       never see (S79: no surrounding widget rectangle ever). Removed at its source
       (Rule of one); the bubble now shows nothing at all when invisible, same as the
       wrapper it sits inside. A member-chosen border colour still paints via the
       [data-border-color] rule above (line 1174), unaffected by this removal. */
    box-shadow: none;
    font-style: italic;
    font-size: var(--quote-font-size, 15px);
    line-height: 1.45;
}

/* The quote starts as a freely shaped text box. Once its padlock is closed,
   profile-grid.js preserves that shape and increases these variables while scaling. */
.profile-widget[data-widget-id="quote"] .widget-quote-input {
    font-size: var(--quote-font-size, 14px) !important;
    border-radius: var(--quote-radius, 12px) !important;
}
body.bp-user .profile-grid-public .profile-widget--quote-autofit.profile-widget--quote-sized,
body.bp-user .profile-grid-public .profile-widget--quote-autofit.profile-widget--quote-sized:hover,
body.bp-user .profile-grid-public .profile-widget--quote-autofit.profile-widget--quote-sized:focus-within {
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    align-self: stretch !important;
    justify-self: stretch !important;
    overflow: hidden !important;
}
body.bp-user .profile-grid-public .profile-widget--quote-sized > .widget-body {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    display: flex !important;
    container-type: inline-size !important;
}
body.bp-user .profile-grid-public .profile-widget--quote-sized .widget-quote {
    width: 100%;
    height: 100%;
    max-width: none;
    box-sizing: border-box;
    overflow: hidden;
}

/* 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;
}

/* The Spotify mark's painted circle is centred at y=83.75 inside a 168px
   viewBox, so a 0.25px downward optical correction centres its ink in the
   36px rail destination without affecting the widget-header copy. */
#widget-sidebar > .sidebar-icon .icon-spotify {
    transform: translateY(0.25px);
}

/* 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):not(.widget-fly-clone) {
    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: max(14px, 3.459cqw);
    margin: 0;
}
.spotify-search-bar {
    position: relative;
}
.spotify-search-input {
    width: 100%;
    padding: max(6px, 1.483cqw) max(10px, 2.471cqw);
    /* 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: max(12px, 2.965cqw);
    font-family: 'Nunito Sans', sans-serif;
    color: #031B83 !important;
    background: #fff !important;
    outline: none;
    box-sizing: border-box;
    text-align: center;
}
.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;
    text-align: center;
}
html[data-nav="kbd"] .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: max(8px, 1.977cqw);
    padding: max(6px, 1.483cqw) max(8px, 1.977cqw);
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s;
}
.spotify-result:hover {
    background: #f0f7ff;
}
.spotify-result-art {
    width: max(36px, 8.896cqw);
    height: max(36px, 8.896cqw);
    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: max(12px, 2.965cqw);
    font-weight: 600;
    color: #031B83;   /* S199, Rob: no greys */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spotify-result-artist {
    font-size: max(11px, 2.718cqw);
    color: #888;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spotify-searching,
.spotify-no-results,
.spotify-not-configured {
    font-size: max(11px, 2.718cqw);
    color: var(--color-text-muted, rgba(3,27,131,.55));      /* S199, Rob: no greys */
    text-align: center;
    padding: max(8px, 1.977cqw);
    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: #EAF4EC;
    border: 1px solid #2F7D4F;
    border-radius: 6px;
    padding: max(6px, 1.483cqw) max(8px, 1.977cqw);
    margin: 0;
}
.spotify-current-info {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: max(8px, 1.977cqw);
    min-width: 0;
    overflow: hidden;
    flex: 1 1 auto;
}
.spotify-current-art {
    width: max(32px, 7.908cqw);
    height: max(32px, 7.908cqw);
    border-radius: 4px;
    flex-shrink: 0;
    object-fit: cover;
}
.spotify-current-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    text-align: center;
}
.spotify-current-name {
    font-size: max(12px, 2.965cqw);
    font-weight: 600;
    color: #031B83;   /* S199, Rob: no greys */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spotify-current-artist {
    font-size: max(11px, 2.718cqw);
    color: var(--color-text-secondary, rgba(3,27,131,.75));   /* S199, Rob: no greys */
}
.spotify-clear-btn,
.spotify-unpin-playlist {
    width: 28px;
    height: 28px;
    min-width: 28px;
    min-height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #FFFBE6;
    border: 1.5px solid #CC9900;
    border-radius: 50%;
    color: #031B83;
    cursor: pointer;
    padding: 0;
    margin: 0 !important;
    box-sizing: border-box;
    box-shadow: none;
    appearance: none;
    line-height: 1;
    flex-shrink: 0;
}
.spotify-clear-btn:hover,
.spotify-unpin-playlist:hover {
    background: #FFF6CC;
    border-color: #CC9900;
    color: #031B83;
}
html[data-nav="kbd"] .spotify-clear-btn:focus-visible,
html[data-nav="kbd"] .spotify-unpin-playlist:focus-visible {
    outline: 2px solid #031B83;
    outline-offset: 2px;
}
.spotify-remove-icon {
    display: block;
    width: 14px;
    height: 14px;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
}

.spotify-admin-oauth {
    text-align: center;
}
.spotify-current-playlist {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr) 36px;
    align-items: center;
    gap: 8px;
    background: #FFFBE6;
    border: 1px solid #CC9900;
    border-radius: 8px;
    padding: 6px 8px;
    /* S233: the card used to sit inside .spotify-admin-oauth, where this margin separated it
       from the button below. It is now a direct child of the .spotify-search-ui flex column,
       whose own gap does that job, and the margin only made one gap wider than the rest. */
    margin-bottom: 0;
}
.spotify-current-playlist__art {
    width: 36px;
    height: 36px;
    border-radius: 4px;
    object-fit: cover;
}
.spotify-current-playlist__copy {
    min-width: 0;
    text-align: center;
}
.spotify-current-playlist__name {
    color: #031B83;
    font-size: 12px;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.spotify-current-playlist__owner {
    color: rgba(3, 27, 131, 0.68);
    font-size: 10px;
}
.spotify-current-playlist .spotify-unpin-playlist {
    justify-self: center;
}

/* Spotify playlist controls. The picker was originally emitted almost entirely as
   inline styling, including a full-width solid-gold button and native grey scrollbar.
   These rules use the platform's existing option-button and Add Event dropdown tokens. */
/* S233 21/09/2026: the Use this link button is the same gold CTA in the same place as the
   retired Pin a playlist button, so it shares the rule rather than getting one of its own. */
.spotify-pick-playlist-btn.btn-option.btn-option--cta,
.spotify-use-link-btn.btn-option.btn-option--cta {
    display: flex !important;
    align-items: center;
    justify-content: center;
    width: max-content !important;
    min-width: 0 !important;
    padding-left: 15px !important;
    padding-right: 15px !important;
    margin-left: auto !important;
    margin-right: auto !important;
}

.spotify-playlist-picker {
    max-height: 280px;
    margin-top: 8px;
    overflow-y: auto;
    scrollbar-color: #DDB94B #FFFBE6;
    scrollbar-width: auto;
}
.spotify-playlist-picker::-webkit-scrollbar {
    width: 12px;
}
.spotify-playlist-picker::-webkit-scrollbar-track {
    margin: 2px 0;
    background: #FFFBE6;
    border: 1.5px solid #CC9900;
    border-radius: 999px;
}
.spotify-playlist-picker::-webkit-scrollbar-thumb {
    background: #DDB94B;
    background-clip: content-box;
    border: 3px solid transparent;
    border-radius: 999px;
}
.spotify-playlist-picker::-webkit-scrollbar-button {
    display: block;
    height: 13px;
    background: #FFFBE6 no-repeat center;
    background-size: 9px 9px;
}
.spotify-playlist-picker::-webkit-scrollbar-button:vertical:decrement {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23CC9900' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 15l6-6 6 6'/%3E%3C/svg%3E");
}
.spotify-playlist-picker::-webkit-scrollbar-button:vertical:increment {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23CC9900' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
.spotify-playlist-picker::-webkit-scrollbar-button:vertical:start:increment,
.spotify-playlist-picker::-webkit-scrollbar-button:vertical:end:decrement {
    display: none;
}

.spotify-playlist-status {
    margin: 0;
    padding: 8px 12px;
    color: #031B83;
    font-size: 11px;
    font-style: italic;
    text-align: center;
    background: #FFFBE6;
    border: 1px solid #CC9900;
    border-radius: 8px;
}
.spotify-playlist-status--error {
    color: var(--color-error, #C41C1C);
    background: var(--color-error-bg, rgba(196, 28, 28, 0.06));
    border-color: var(--color-error, #C41C1C);
}
.spotify-playlist-status--loading {
    background: #FFFFFF;
}

.spotify-customise-preview {
    width: 100%;
    line-height: 0;
}
.spotify-customise-preview iframe {
    display: block;
    width: 100%;
    border: 0;
    border-radius: 8px;
}

/* Events list */
.widget-events-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.widget-events-list li {
    display: flex;
    gap: max(12px, 4.026cqw);
    padding: max(6px, 2.013cqw) 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: max(11px, 3.691cqw);
    padding: max(3px, 1.006cqw) max(8px, 2.684cqw);
    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 */
}

.widget-events-list .event-date {
    font-size: max(12px, 4.026cqw);
    min-width: max(70px, 23.489cqw);
}

.widget-events-list .event-title {
    font-size: max(13px, 4.362cqw);
}

/* 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, rgba(3, 27, 131, 0.55));
}
/* 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, rgba(3, 27, 131, 0.75));
    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, rgba(3, 27, 131, 0.55));
}
/* 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-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 {
    /* S229 16/09/26 (T-S229-005), Rob: "this should just be copied exactly from the preferences
       pages because it's already been done just copy the styling exactly and replace this shit."
       The reference is .pf-progress in page-polish.css (the Preferences questionnaire card): the
       same white face, 1.5px gold edge, 12px radius, small shadow and 12px/20px padding, the
       label in the heading face uppercase, the percent in gold, and a 7px pill track with the
       gold fill, so a below-100 state reads exactly as it does there. */
    max-width: 720px;
    margin: 0 auto 15px;
    background: var(--color-surface, #FFFFFF);
    border: 1.5px solid var(--color-gold, #CC9900);
    border-radius: var(--radius-md, 12px);
    box-shadow: var(--shadow-sm, 0 1px 3px rgba(3, 27, 131, 0.08));
    padding: 12px 20px;
    gap: 12px;
    align-items: center;
}
.membership-questionnaire.pf-public__quest .quest-label {
    font-family: var(--font-heading, 'Montserrat'), sans-serif;
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-navy, #031B83);
}
.membership-questionnaire.pf-public__quest .quest-bar {
    position: relative;
    display: flex;
    align-items: center;
    align-self: center;
    height: 12px;
    background: #FFFFFF;
    border: 1.5px solid #E0C56A;
    border-radius: 999px;
    overflow: hidden;
    padding: 1px;
    margin-top: 0;
    transform: translateY(-1px);
}
.membership-questionnaire.pf-public__quest .quest-fill {
    display: block;
    height: 8px;
    min-width: 16px;
    background: #DDB94B;
    border-radius: 999px;
}
.membership-questionnaire.pf-public__quest .quest-pct {
    font-family: var(--font-heading, 'Montserrat'), sans-serif;
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--color-gold, #CC9900);
}
.membership-questionnaire.pf-public__quest .quest-seg {
    display: none;
}

/* ============================================================
   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;
}

/* S217 09/09/2026: the editor rows wrap from 1023 down, not just below 768. Measured after the
   phone block was removed: at 390 the toolbar wanted 459px in 375 and the background picker 485px,
   and AT 768 the toolbar still measured 798px in a 768 screen, so Save Design sat off the edge on
   an iPad in portrait too. One band, every narrow width, rather than a phone-only patch. */
@media (max-width: 1023px) {
    .editor-toolbar,
    .editor-actions,
    .bg-picker,
    #widget-sidebar,
    .widget-sidebar {
        flex-wrap: wrap !important;
        justify-content: center !important;
        row-gap: 8px !important;
        /* S224 15/09/26. Rob, twice, the second time plainly cross: "The background option menu
           and the widget rail on mobile are touching the edge of the screen. In fact, the widget
           rail looks like it's overlapping off the side of the screen. They are both incorrect
           and I've asked you to fix them loads of times." THIS LINE IS THE CAUSE OF BOTH, and it
           is one line covering all five bars. MEASURED at 390 on cold_prem19: the background
           panel ran 0 to 390, flush to both edges, while .editor-content beside it sits 15px in.
           100% of a wrapper carrying padding: 8px 0 IS the whole screen. Taking 30px out gives
           every bar the same 15px each side that the workspace already has. */
        max-width: calc(100% - 30px) !important;
        /* S224 15/09/26, second pass. Capping the width was not enough on its own: measured at
           390, .editor-toolbar sat at left 0 with a 30px gap on the right and .editor-actions
           was 30px off centre, because a capped box with no auto margins still starts at its
           container's left edge. Auto margins centre all five bars, so each now shows the same
           15px each side that .editor-content has. */
        margin-left: auto !important;
        margin-right: auto !important;
    }
    .editor-actions {
        width: 100% !important;
    }
}

/* ============================================================
   Responsive — hide editor on phones, single column public view
   ============================================================ */

/* Phone: hide the entire editor, show a message instead */
@media (max-width: 767px) {
    /* S217 09/09/2026, Rob: "you should be allowed to customise on an iPad and smaller, or on
       mobile". The tab, the editor chrome and the desktop-only message that used to live here
       are gone: the Loose ends lane removed the two redirects and built the preview-size ladder,
       and these three rules were the last thing stopping a phone. The editor was driven with
       real touch at 390 with them removed, so nothing else is in the way. */

    /* 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 */
    /* R3-K 24/09/2026 (Rob, round 3 items 29 and 40): the 16px at the BOTTOM. overflow-x: hidden makes this
       wrapper a scroll box, and a scroll box cuts off anything painted below its last child. The profile
       frame is an outline drawn 2px OUTSIDE the grid (S224), the nudge card has a 16px drop shadow and the
       Preferences cards a 6px one, so whenever the grid or a card was the last thing on the page (always on
       your own profile, where Report and Block are not printed) its bottom edge was cut off: MEASURED 2px
       of frame and 6px of card shadow lost at 360 and 600, nothing at 768 and up where nothing clips. The
       bottom padding gives every tab room for the deepest of them; the sides are unchanged. */
    .profile-public-wrapper {
        max-width: 100% !important;
        padding: 0 16px 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;
    }

    /* T-S228-053 18/09/2026: a date with a fixed 70px minimum left too little of a narrow
       public mobile widget for its event title. Stacking the two fields gives the title the
       widget's full content width; the public fit in profile-system.php then reserves the
       height this wrapping actually needs. The editor and all wider breakpoints are unchanged. */
    .profile-grid-public .widget-events-list li {
        flex-direction: column;
        align-items: flex-start !important;
        gap: 2px;
    }
    .profile-grid-public .widget-events-list .event-date {
        min-width: 0;
    }
    .profile-grid-public .widget-events-list .event-title {
        width: 100%;
    }

    .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 .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.
       S222 14/09/26: SCOPED AWAY FROM THE CUSTOMISE EDITOR. The universal selector handed this to
       every descendant, including a widget body only 8.16px wide inside the Mobile preview, where
       it laid 198 characters onto 153 line boxes and grew the music widget to 3,518.80px tall
       (measured by wc2, results/s221/wc2: turning this pair off took it to 940.45px). The dashboard
       still needs it for long emails and URLs, so it keeps it; the editor page carries
       .profile-editor-active and is excluded. The rest of the music widget's height is the note
       card inside its body, which the other lane is moving. */
    body.profile-dashboard-active:not(.profile-editor-active) #item-body .col-inner,
    body.profile-dashboard-active:not(.profile-editor-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 on mobile. S219 (T-S216-074): .profile-preview-nav removed
       from this list so the Dashboard / Customise pill under the sigil shows on a phone like every other width. */
    .profile-cover-change-btn,
    .profile-cover-reposition-btn,
    .profile-avatar-change-btn,
    .profile-avatar-reposition-btn,
    .btn-view-profile,
    .btn-customise-profile {
        display: none !important;
    }

    /* 15.6.6 [REMOVED X05, S238, 26/09/2026] centred BuddyPress's #item-nav / #object-nav tab list,
       which is no longer printed (the custom sidenav is the only member nav). */

    /* 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: 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: 2;
}
/* end of 16.1.3.1 */

/* 16.1.3.2 Button hover — brighter translucent */
.profile-cover-change-btn:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* end of 16.1.3.2 */

/* 16.1.3.3 Button icon */
/* S227 (backlog row 39 / S217-V7, 15/09/26): the 0.5px HORIZONTAL half of the S217 nudge was
   wrong and is gone. Re-measured as painted ink against the painted ring in the same dpr 8
   capture, so the button's own sub-pixel position cancels: with no nudge at all every glyph
   here sits within 0.063px of the ring centre horizontally, which is half a device pixel at
   dpr 8 and the floor of the measurement. The 0.5px pushed the two cover glyphs 0.44px right
   at dpr 8 and a full 1.00px right at dpr 1, while their sigil twins stayed centred.
   The 0.875px VERTICAL is real and stays: unnudged, the dashicons camera glyph paints 0.875px
   high of centre at every width tested, and the move glyph paints centred. */
.profile-cover-change-btn .dashicons {
    font-size: 18px;
    width: 18px;
    height: 18px;
    transform: translate(0, 0.875px);
}
/* 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;
    min-width: 190px;
    min-height: 190px;
    border-radius: 50%;
    border: 5px solid var(--color-gold, #CC9900);
    object-fit: cover;
    /* S217 09/09/2026 (EV-25): was --color-surface, plain white, and with the Gravatar
       fallback now transparent that made the largest placeholder on the site a white disc. */
    /* S219 (CUST-124): the gold Account person on the placeholder, inside the existing gold border */
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3.75 4.19 16.5 17.8'%3E%3Cpath d='M4.6 21.14c0-4.1 3.3-6.6 7.4-6.6s7.4 2.5 7.4 6.6z' fill='%23CC9900'/%3E%3Ccircle cx='12' cy='8.74' r='3.7' fill='%23CC9900'/%3E%3C/svg%3E") center 50% / 46% no-repeat, linear-gradient(145deg, #041D88, #0A2A9E);
    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
   S227 item 1 (Rob's photo 1.jpeg): the selector also covers :hover so a tapped button on a
   phone keeps these colours. Without it the parent theme's seeko-dynamic.css `a:hover
   { color: rgb(128,96,0) }` at (0,1,1) beats a bare `.preview-nav-btn` at (0,1,0) and the
   pair still reads mismatched. `.preview-nav-btn:hover` is (0,2,0) and holds. */
.preview-nav-btn,
.preview-nav-btn:hover {
    display: inline-block;
    /* F-068 (S233, 21/09/2026). The label was not vertically centred in the pill. MEASURED as
       PAINTED INK at dpr 8, not as a box: the cap box of DASHBOARD and CUSTOMISE sat at 11.375px
       against a pill midpoint of 12.000px, so the text was 0.625px HIGH (Rob read it as off-centre;
       the direction is up, not down). Symmetric 3px padding cannot be centred by line-height here,
       because the pill's height is auto: raising the line-height adds half-leading above and below
       and grows the box by the same amount, so the two move together and nothing changes. The lever
       is the padding split, and Chrome quantises the baseline to whole CSS pixels, so the reachable
       positions are 11.375 and 12.375 and nothing between: bracketed at 3, 3.25, 3.5, 3.75, 4 and
       4.25px of top padding, every value from 3.5 up lands on 12.375. 3.5/2.5 is the first, keeps
       the pill exactly 24px tall as before, and brings the offset from 0.625px to 0.375px. */
    padding: 3.5px 10px 2.5px;
    font-family: 'Montserrat', sans-serif;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    /* S229 17/09/26 (T-S229-061), Rob with his own profile picture: "the dashboard and profile
       and customize buttons that show up under the sigil all need to be changed just like the
       login and dashboard buttons in the top right of each page were changed so they need to go
       to the normal light cream background go border, blue text styling like the download
       button." Same face as .header-login-btn and .btn--primary. */
    color: var(--color-navy, #031B83);
    background: var(--color-cream, #FFFBE6);
    border: 2px solid var(--color-gold, #CC9900);
    border-radius: 10px;
    text-decoration: none;
    transition: all 0.2s;
    white-space: nowrap;
    line-height: 1.4;
    /* R3-08-hB2 25/09/26, D-651: gold rest shadow added - was a gold-bordered clickable with none. */
    box-shadow: var(--shadow-gold-hover);
}
/* end of 16.2.2.2 */
/* 16.2.2.3 Preview nav button hover, the gold fill.
   S227 item 1: gated, because a touch device applies :hover to the element it last tapped and
   keeps it there, which is what Rob photographed: he tapped CUSTOMISE, it stayed gold while
   DASHBOARD beside it stayed navy, and the pair read as two different buttons. */
@media (hover: hover) {
.preview-nav-btn:hover {
    /* S229: the platform's cream-to-darker-cream hover, not a gold fill. */
    background: var(--color-cream-hover, #FFF5CC);
    color: var(--color-navy, #031B83);
    border-color: var(--color-gold, #CC9900);
    text-decoration: none;
}
}
/* end of 16.2.2.3 */
/* 16.2.2.3b Preview nav button pressed (D-651, R3-08-hB2 25/09/26): no :active rule existed
   before this. Darker cream fill, no shadow, matching the platform's pressed-state standard. */
.preview-nav-btn:active {
    background: var(--color-cream-hover, #FFF5CC);
    box-shadow: none;
}
/* end of 16.2.2.3b */

/* 16.2.2.4 Avatar change button — gold circle, bottom-right */
.profile-avatar-change-btn {
    /* S217 (S217-V6, Rob 09/09/26): the sigil circles were 36px with a 14px glyph while the
       cover circles were 40px with an 18px glyph, and the theme stretched these to 40 wide so
       they were not round. All four match now, on the larger of the two sizes he chose. */
    /* S207 06/09/26, Rob item 29: one pixel to the right. */
    transform: translateX(1px);
    position: absolute;
    bottom: 8px;
    right: 8px;
    width: 40px;
    height: 40px;
    min-width: 40px;
    flex: 0 0 40px;
    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: 18px;
    width: 18px;
    height: 18px;
    /* S217: same camera glyph, same 0.875px lift to correct; it is already true horizontally. */
    transform: translate(0, 0.875px);
}
/* 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);
}
.profile-badge.profile-badge-host {
    background: var(--color-cream, #FFFBE6);
    color: var(--color-navy, #031B83);
    border: 1.5px solid var(--color-gold, #CC9900);
}
/* 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;
        min-width: 150px;
        min-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;
        min-width: 110px;
        min-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 [REMOVED X05, S238, 26/09/2026] collapsed the space of the hidden BuddyPress #item-nav on
   own-profile pages. The element is no longer printed, so there is no space to collapse. */
/* end of 16.6.9 */
/* 16.6.10 [REMOVED X05, S238, 26/09/2026] hid the empty BuddyPress #subnav on own-profile pages. The
   child settings/plugins/profile/friends overrides no longer print it; the Notifications subnav is
   shown by 17.6 below and page-polish.css 17.4.6, exactly as before. */
/* end of 16.6.10 */
/* end of 16.6 */

/* 16.7 Public profile action buttons — clean layout when viewing another member */
/* 16.7.1 Invite modal root stays out of the button row until it is opened */
/* X05 (S238, 26/09/2026): BuddyPress's duplicate Message (#send-private-message) and @mention
   (#post-mention) buttons used to be hidden here too. They are no longer printed at all
   (interest-system.php 3.8a removes them at source), so their selectors are gone. */
#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. */
/* S222 items 38 and 97, Rob 14/09/2026: "those buttons, the favourite button and the show
   interest button, are way too wide. Apply the 15 pixel padding on either end of both" and
   "these buttons are too wide, so give them fifteen fifteen pixel padding and make sure they
   are still centered."
   S198's one shared width stays (Rob, 29/08/26: "the three buttons above should all be the
   exact same shape and size and uniform, on all breakpoint sizes"); what changes is the value,
   which this rule was always meant to carry from the widest rendered label. Measured live as
   cold_std22 on a member and on a venue profile: the widest label in this row is "Would like
   to invite" at 113.92px of ink, so 113.92 + 15 + 15 + 2px of border = 145.92, taken as 146.
   Measured after: that label sits 15px inside each border at 1920 / 1280 / 1024 / 768 / 600 /
   360, nothing overflows (scrollWidth equals clientWidth on every button), and the row still
   wraps onto exactly the same number of lines it did before at every width. */
#item-buttons.profile-header-actions {
    --uks-action-btn-w: 146px;
}
#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.
   S238 F08: a venue or organiser profile now carries the business interest control
   (interest-system.php 4.1.1b), which is a <button class="wishlist-button"> until it becomes the
   Message anchor, so the row's shell names it beside the member control's anchor. */
#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,
#item-buttons.profile-header-actions .interest-button-wrap > .wishlist-button,
#item-buttons.profile-header-actions .offer-btn-holder button {
    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;
    /* S222 items 38 and 97, Rob 14/09/2026: 15px of padding at either end, and a white fill.
       Measured before: 12px of padding, and the buttons were transparent over the page's own
       rgb(248,248,248), so they were not white at all. min-width is zeroed because
       interest-system.php prints min-width:170px on .interest-btn from the footer, which held
       that one button 24px wider than the other two the moment the shared width came down. */
    min-width: 0 !important;
    padding-left: 15px !important;
    padding-right: 15px !important;
    background: #FFFFFF !important;
    border-width: 2px !important;
    border-radius: 10px !important;
    /* S227 items 89 and 128, Rob: "when I look at the size of the font for favourited and
       interested compared to the profile preferences and reputation font, I can see that even
       the font's too small." The tabs he is comparing against are .section-nav__item at 13px
       (page-polish.css), measured on the same page directly below this row. 12px -> 13px. */
    font-size: 13px !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.
       S224 14/09/26: the row still shares one resting state, and Rob has now chosen what it
       is. Shown the three versions in context at 360 he answered "B", both buttons white,
       because Show interest was already white and Favourite was see-through, so the pair read
       as two different colours. THIS RULE IS WHY the same change in the mu-plugin did not take:
       it is (1,2,1) with !important and sits LATER in the cascade, so it beat the plugin's own
       declaration. Changed at source rather than overridden again (LB-383). */
    background: #FFFFFF !important;
    border: 2px 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: var(--shadow-gold-hover) !important;
    position: relative;
    gap: 5px !important; /* S198, Rob: 5px between the + circle and the word */
    /* S222 items 38 and 97: 15px at either end, matching the rest of the row. */
    padding-left: 15px !important;
    padding-right: 15px !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. */
/* S222 item 97, Rob 14/09/2026: "make sure they are still centered."
   MEASURED FAULT: the "Favourite" word sat 11.51px LEFT of its button's midpoint, at every
   one of the six widths, before anything in this session was changed (ink 49.48px from the
   left edge against 72.5px from the right). The cause is this spacer. It was added in S198 to
   mirror the gold + circle at the other end, but the profile-header button that
   uksocials-member-favourites.php renders now contains only <span class="member-fav-label">:
   there is no .member-fav-plus element in it any more, so the spacer has nothing to balance
   and simply pushes the word left by half of (18px + the 5px gap). Retired for this row.
   Measured after: 45.98 / 46.00, a midpoint difference of 0.01px.
   FLAGGED SEPARATELY, not fixed here: the gold + circle is in Rob's own reference image 97
   and is NOT on the live button. That is markup, and it belongs to the other lane. */
#item-buttons.profile-header-actions .member-fav-btn::after {
    content: none;
}
/* S224 14/09/26: this was SOLID GOLD, which S198 itself superseded the same week. The
   mu-plugin's own rule already says the favourited state is the quiet cream fill with navy
   text, and its comment records the change; this copy was left behind at a specificity that
   beat it, so what actually rendered was the old gold. Brought onto the plugin's values, so
   there is one answer rather than two. */
#item-buttons.profile-header-actions .member-fav-btn.is-fav {
    background: #fffbe6 !important;
    color: #031B83 !important;
}
/* 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, anchored to the button by script, not by the flow.
   S235 21/09/2026, F-034: this rule used to be `position: absolute` against the
   `#item-buttons .interest-button-wrap` relative wrap, which put the panel inside
   `body.profile-public-active .bp-member-layout > .container` (this file, near the
   top) and inside `#buddypress .bp-member-layout` (buddypress.min.css). Both of
   those clip their overflow, so the 611px panel was cut off at the container's
   own bottom edge: reasons 5 to 7 and the Send button were painted nowhere, at
   any scroll position, and a mouse user could not send interest with them.
   MEASURED on the live profile at 1280 on 21/09/2026: panel 486-1098, clipping
   container 188-859, Send at 1051-1082 with elementFromPoint returning null.
   Fixed positioning takes the panel out of both clipping boxes (measured: no
   ancestor creates a containing block with transform, filter, will-change or
   contain), and interest-system.php 7.1.1 places it against the button and keeps
   it there on scroll and resize. The offsets are auto so that, if the script has
   not run yet, the panel still falls at its static position under the button
   rather than off the bottom of the viewport. Nothing about the panel itself
   changes: same width, same seven reasons, same colours, same Send button. */
#item-buttons .interest-reasons-popover {
    position: fixed;
    top: auto;
    right: auto;
    left: auto;
    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, #F8F8F8);
}
/* 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, rgba(3, 27, 131, 0.55));
    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, rgba(3, 27, 131, 0.55));
}
/* 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, rgba(3, 27, 131, 0.55));
    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 */
html[data-nav="kbd"] .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, rgba(3, 27, 131, 0.55));
    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, #F8F8F8);
    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 */
html[data-nav="kbd"] #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, rgba(3, 27, 131, 0.75));
    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, rgba(3, 27, 131, 0.55));
    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, #F8F8F8);
    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, rgba(3, 27, 131, 0.55));
    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, #F8F8F8);
    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, #F8F8F8);
    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 */
html[data-nav="kbd"] .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, rgba(3, 27, 131, 0.55));
    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 */
/* S222 (Rob, 14/09/2026): the one treatment reaches this button too. COMPUTED painted result
   before, from a model checked against the measured pixels on the bank button to within 1 of 255:
   rgb(104,118,181) on white, 4.33 to 1, under the 4.5 AA floor. It keeps its own colours now. */
.messages-mark-read:disabled {
    opacity: 1;
    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: 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: 2;
}
/* end of 20.1.1 */
/* 20.1.2 Cover reposition button hover */
.profile-cover-reposition-btn:hover {
    background: var(--color-cream-hover, #FFF5CC);
}
/* 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 {
    /* S217 (S217-V6, Rob 09/09/26): the sigil circles were 36px with a 14px glyph while the
       cover circles were 40px with an 18px glyph, and the theme stretched these to 40 wide so
       they were not round. All four match now, on the larger of the two sizes he chose. */
    position: absolute;
    bottom: 8px;
    right: 52px;
    width: 40px;
    height: 40px;
    min-width: 40px;
    flex: 0 0 40px;
    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: 18px;
    width: 18px;
    height: 18px;
}
/* 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-gold, #CC9900);
}
/* 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;
}
/* S234 21/09/2026, Rob: "The text in the profile designer popups should be centred". The card has
   carried text-align:center since S188; the markup carried an inline text-align:left and a 20px
   list indent, which is what actually drew the copy to the left. Those two inline values are
   removed at source (profile-system.php 3.0c.3) and the list is drawn the way every other centred
   list on the platform is drawn: no markers, no indent, so a bullet can never hang left of the
   centred line it belongs to. */
.uks-std-intro .uks-dialog-msg ul{ list-style: none; margin: 0; padding: 0; }
.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; }


/* ============================================================================
   20. SECTION: SAVE DESIGN AND RESET DESIGN, WHILE THE SAVED DESIGN IS STILL LOADING
   F-085, 21/09/2026.

   The editor page is rendered from the WIDESCREEN design and the member's own size is applied
   after window load (profile-grid.js 14.3.1). Measured at 1280 on 21/09/2026: the widescreen
   widget set was still on the grid at t = 3,813 ms and the member's desktop set arrived at
   t = 3,973 ms. Both controls that persist a layout are now disabled for that window and are
   opened by the apply itself (profile-grid.js 6.0a); this is the state they wear while closed.

   IT MUST NOT LOOK LIKE THE SAVING STATE, which is a deliberately UNGREYED cream button with a
   solid gold edge (.btn-save:disabled above, Rob's item 43: "Saving should be shown the same
   everywhere and it should not grey out"). That one means "your click landed and is in flight".
   This one means "not yet", so it keeps the white resting face and the navy label at full
   strength, mutes the gold edge to 40 per cent, drops the lift and the drop shadow so nothing
   reads as pressable, and takes the wait cursor. The label under Save Design says so in words.

   THE DOUBLED CLASS IN THE SELECTOR IS DELIBERATE, NOT A TYPO. page-polish.css carries
   `button:disabled:not(...)` at specificity (0,6,1) with `box-shadow: none !important`, which is
   what stripped the gold edge off the saving button in S229 and would strip it off this state
   too. .btn-save is excluded there by name; .btn-reset is not. Repeating .is-layout-loading
   lifts these rules to (0,7,1) so both buttons keep their edge, without editing page-polish.css,
   which another lane holds.
   ============================================================================ */
.profile-editor-wrapper .editor-toolbar .editor-actions button.btn-save.is-layout-loading.is-layout-loading:disabled,
.profile-editor-wrapper .editor-toolbar .editor-actions button.btn-reset.is-layout-loading.is-layout-loading:disabled {
    opacity: 1 !important;
    background: #ffffff !important;
    color: #031B83 !important;
    box-shadow: inset 0 0 0 2px rgba(204, 153, 0, 0.4) !important;
    transform: none !important;
    cursor: wait !important;
    animation: none !important;
}

/* No hover response at all: a control that cannot be used must not answer the pointer. */
.profile-editor-wrapper .editor-toolbar .editor-actions button.btn-save.is-layout-loading.is-layout-loading:disabled:hover,
.profile-editor-wrapper .editor-toolbar .editor-actions button.btn-reset.is-layout-loading.is-layout-loading:disabled:hover {
    background: #ffffff !important;
    color: #031B83 !important;
    box-shadow: inset 0 0 0 2px rgba(204, 153, 0, 0.4) !important;
    transform: none !important;
}

/* The status line hangs inside the Save button (profile-system.php 12151 moves it there), so it
   is named here alongside the other four states, which all restate their own colour for the same
   reason. Navy on white, the platform's own body colour, 14.11 to 1. */
.btn-save:disabled .save-status.status-loading,
.save-status.status-loading {
    color: #031B83 !important;
}

/* ============================================================================
   21. SECTION: ANOTHER MEMBER'S PROFILE IS LOOK-ONLY (N05, S238, the 27th of September 2026)
   Rob, 27/09/2026 (final): "There shouldn't be anything clickable at all when you look at somebody
   else's profile... The widgets are there to give people content to design their profile. But the
   profile is just something to look at."

   profile-system.php 8.1 gives the public grid the state class is-look-only for every viewer except
   the member themselves and an admin. Here every widget, and everything inside one, stops answering
   the pointer: no click, no tap, no hover state, no drag, no tooltip, and the Spotify player (a bare
   iframe that is itself the widget) cannot be pressed. Nothing is hidden, moved or restyled, so the
   widgets read exactly as before; they just do not answer. The Profile / Preferences / Reputation
   tabs, the header action row and the Report and Block footer are not widgets and are not touched,
   and the owner's own view and the customise editor never carry the class.

   The keyboard half is profile-system.php 8.0c, the script printed after a look-only grid. It also
   marks data-look-scroll on a box whose content runs past its own edge (measured before this was
   built: the venue reviews list held 1559px of reviews in a 420px box at 360), and 21.2 hands that
   box ALONE its pointer back so the rest can still be scrolled into view by wheel, swipe or
   scrollbar. Its children stay inert, and hovering it changes nothing (the widget-root :hover rules
   in pickable-buttons.php, venue-organiser-widgets.php 4.3 and profile-system.php 14.7 all restate
   the resting values). Behind the Free blur nothing gets its pointer back.

   The #pub-profile id lifts these rules above every pointer rule the widget files print for
   themselves: pickable-buttons.php 6.1.3 is (0,3,0) !important and printed after this file, and
   profile-system.php 14.7 gives .profile-sigil-body pointer-events:auto at (0,3,0).
   ============================================================================ */

/* 21.1 Every widget and everything inside it, pseudo-elements included */
#pub-profile .profile-grid-public.is-look-only [data-widget-id],
#pub-profile .profile-grid-public.is-look-only [data-widget-id] *,
#pub-profile .profile-grid-public.is-look-only [data-widget-id]::before,
#pub-profile .profile-grid-public.is-look-only [data-widget-id]::after,
#pub-profile .profile-grid-public.is-look-only [data-widget-id] *::before,
#pub-profile .profile-grid-public.is-look-only [data-widget-id] *::after {
    pointer-events: none !important;
}
/* end of 21.1 */

/* 21.2 A box whose content overflows it keeps the pointer, for scrolling only */
#pub-profile .profile-grid-public.is-look-only:not(.is-upgrade-blurred) [data-widget-id][data-look-scroll],
#pub-profile .profile-grid-public.is-look-only:not(.is-upgrade-blurred) [data-widget-id] [data-look-scroll] {
    pointer-events: auto !important;
    cursor: default !important;
}
/* end of 21.2 */
/* end of 21 */
