/*
Theme Name:  eKlektiv.Launch
Theme URI:   https://eklektiv.org
Description: eKlektiv's own theme. Dana's palette and chrome over BuddyNext, Better Messages, Eventonomy, Listora, WP Career Board and Learnomy. Standalone since 27 Sep 2026 (Kevin's ruling on Leaving Reign); `Template: reign-theme` removed, `index.php` added, and the four things Reign was carrying taken over in functions.php. The directory is still `eklektiv-child` — renaming it is cosmetic and is its own change.
Author:      eKlektiv
Version:     0.2.0
Requires PHP: 8.4
Text Domain: eklektiv-child
*/

/* ══════════════════════════════════════════════════════════════════════════
 * THE TOKEN SET — one, and it is Dana's.
 *
 * Kevin, 30 Sep 2026, Scenario Testing Briefing, d-palette a: *"Yes, blue
 * everywhere. One token set in style.css; every screen reads it."* And: *"make
 * sure we can choose light, dark OR Night themes that Dana has built and we
 * derived from our research into Monday.com."*
 *
 * Until today this sheet carried two palettes: the Aurora teal (`--ek-*`,
 * Theme and Brand §3) and Dana's blue (`--ds-*`, ruled 26 Sep: "Blue. Her
 * palette. Her avatar colour rules."), with every older screen restating one
 * or the other under its own prefix. Now there is one: the `--ds-*` values
 * below, in three schemes. Every other name — `--ek-*`, the per-screen
 * `--ek-xx-*` families, `--ek-dir-*`, `--reign-*`, `--bn-*`, Better Messages'
 * triplets — is an ALIAS of these, declared where it always was, so nothing
 * that reads an old name had to change and nothing can drift from here.
 *
 * Values are Dana's, read from her prototype's own `pal()` (PeoplePhone,
 * MobileHome, Main) — `06-Architecture/Decisions - Dana's Palette (26 Sep
 * 2026).md`. The status colours are the house's measured ones (Dark mode
 * playbook §4), now given a value per scheme.
 *
 * ## How a scheme is chosen
 *
 * The member picks Light, Dark, Night or "same as this device" on Settings →
 * Appearance; the companion's `Chrome\Scheme` saves it per person and stamps
 * `<html>` before the first paint:
 *
 *   Light   data-bx-mode="light"                       (this :root block)
 *   Dark    data-bx-mode="dark"  data-bn-theme="dark"  (the trio block:
 *           near-black)
 *   Night   data-bx-mode="dark"  data-ek-scheme="night" (the trio block,
 *           then the night block over it: navy)
 *
 * **The names are Kevin's, 30 Sep 2026 (e-dark-night b, "Swap them").** Dana's
 * prototype and Monday's screens call the navy column Dark and the near-black
 * one Night; Kevin saw that and ruled the other way. Stored choices keep their
 * names: a member who chose "dark" gets near-black.
 *
 * **Night is dark to everything else.** BuddyNext rewrites `data-theme` on
 * every load, so a third value cannot live there; instead Night stamps dark
 * (so every dark rule of ours and the vendors' applies — native controls,
 * shadows, Better Messages' dark class) and `html:root[data-ek-scheme="night"]`
 * swaps in Dana's navy values. It out-specifies the trio (0,2,1 against
 * 0,1,0), so the order of the two blocks does not matter.
 *
 * Still no `prefers-color-scheme` in any sheet (playbook §1): "same as this
 * device" is resolved by the head script into an explicit attribute, so the
 * attribute stays the one source of truth.
 *
 * ## Ink and fill (playbook §3.2)
 *
 * `--ds-accent` is a FILL behind white type (5.66:1 light, 4.77:1 dark and
 * night) and an edge; as TEXT it fails on the dark grounds (3.61:1 on navy). Text takes
 * `--ds-accent-text`. The same split holds for danger: `--ds-danger` is ink,
 * `--ds-danger-fill` sits behind white.
 * ══════════════════════════════════════════════════════════════════════════ */
:root {
	/* Dana's palette — light. */
	--ds-bg:          #F3F4F9;
	--ds-surface:     #FFFFFF;
	--ds-surface2:    #EEF0F7;
	--ds-line:        #E2E5EF;
	--ds-ink:         #1C1F33;
	--ds-ink2:        #5B6178;
	--ds-accent:      #3F5BD9;
	--ds-accent-soft: #E8ECFF;
	--ds-accent-text: #2F48B8;
	--ds-warm:        #FFF3E4;
	--ds-warm-line:   #F3D9B8;
	--ds-warm-ink:    #7A4300;
	--ds-on-accent:   #FFFFFF;
	/*
	 * The navigation rail's own ground (27 Sep 2026). Dana's `Main.dc.html`
	 * keeps a `rail` entry in every palette, separate from the card surface: the
	 * same white in light, a step darker than the cards in dark and night.
	 */
	--ds-rail:        #FFFFFF;
	/*
	 * The wordmark's ink (27 Sep 2026): #1F2A6B / #EDEFF8 / #ECEDF0, the
	 * `brand` entry of each of her palettes. The wordmark is not an action, so
	 * it is not the accent.
	 */
	--ds-brand-ink:   #1F2A6B;

	/*
	 * Status, per scheme (added 30 Sep 2026 so no sheet restates them). Ink
	 * values measured on the surface and the ground; fills carry white.
	 *   danger  #B42318  6.57 on white, 5.99 on the ground
	 *   good    #1A7F45  5.04 on white, 4.59 on the ground
	 */
	--ds-danger:      #B42318;
	--ds-danger-fill: #BC3915; /* white on it 5.62 */
	--ds-good:        #1A7F45;
	--ds-warn-fill:   #F5C044; /* Honey — a fill carrying ink text, never text itself */
	--ds-alarm:       #E5484D; /* Dana's unread dot, the same in every scheme */
	--ds-focus:       rgba(63, 91, 217, .28);

	/* Depth (playbook §3.8: a 4% shadow vanishes on a dark ground). */
	--ds-shadow:      0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .08);
	--ds-shadow-pop:  0 12px 32px rgba(10, 12, 30, .16);

	/* Better Messages reads colours as bare "r, g, b" triplets. */
	--ds-bg-rgb:      243, 244, 249;
	--ds-surface-rgb: 255, 255, 255;
	--ds-ink-rgb:     28, 31, 51;
	--ds-ink2-rgb:    91, 97, 120;
	--ds-accent-rgb:  63, 91, 217;
	--ds-surface2-rgb: 238, 240, 247;
	--ds-line-rgb:    226, 229, 239;
	--ds-accent-soft-rgb: 232, 236, 255;
	--ds-accent-text-rgb: 47, 72, 184;

	--ds-radius:      16px;
	--ds-radius-lg:   20px;

	/* Two faces since 10 Sep: Outfit carries display and the wordmark, Inter the body. */
	--ek-font:          "Outfit", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	--ek-font-body:     "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	--ek-radius:        14px;
	--ek-radius-pill:   999px;

	/*
	 * The Aurora names, now aliases (30 Sep 2026). Declared on the same element
	 * as the `--ds-*` values, so each resolves in whichever scheme is showing and
	 * no dark or night block has to restate them. What each used to be is kept
	 * beside it, because older notes in this theme quote those values.
	 */
	--ek-ground:        var(--ds-bg);          /* was #F2F4F7 Morning Mist */
	--ek-surface-solid: var(--ds-surface);     /* was #FFFFFF */
	--ek-sunken:        var(--ds-surface2);    /* was #F7F8FA */
	--ek-hairline:      var(--ds-line);        /* was #DFE6EE */
	--ek-ink:           var(--ds-ink);         /* was #1B1F24 */
	--ek-muted:         var(--ds-ink2);        /* was #5A6472 */
	--ek-faint:         var(--ds-ink2);        /* was #5D6875 */
	--ek-tint:          var(--ds-accent);      /* was #10A99B, fills only */
	--ek-teal-text:     var(--ds-accent-text); /* was #0A7A6F — the accent as ink */
	--ek-button:        var(--ds-accent);      /* was #0B8478 — the accent as fill */
	--ek-on-btn:        var(--ds-on-accent);
	--ek-wash:          var(--ds-accent-soft); /* was #E6F4F2 */
	--ek-teal-wash:     var(--ds-accent-soft); /* was 14% teal — own-message bubble */
	--ek-success:       var(--ds-good);        /* was the teal: "the brand IS success" no longer holds with a blue brand */
	--ek-warning:       var(--ds-warn-fill);
	--ek-error:         var(--ds-danger-fill);
	--ek-white:         #FFFFFF;               /* white type on a fill, every scheme */
	--ek-midnight:      #151B23;               /* the live-Room strip, dark in every scheme */
	--ek-navy:          #002D79;               /* the e. mark (the icon file's own navy) */
	--ek-logo-on-dark:  #F2F4F7;
}

/* Dark — the trio, and the NEAR-BLACK column of Dana's prototype (Kevin,
   30 Sep 2026, e-dark-night b: "Swap them" — her prototype and Monday call
   this one Night). `color-scheme: dark` makes native controls (the date
   picker, checkboxes, selects, scrollbars) draw dark too; BuddyNext's
   bn-base.css sets the same, but it does not load on every screen. */
[data-bn-theme="dark"],
[data-theme="dark"],
[data-bx-mode="dark"] {
	color-scheme: dark;
	--ds-bg:          #0D0E11;
	--ds-surface:     #17181C;
	--ds-surface2:    #1F2025;
	--ds-line:        #2A2C32;
	--ds-ink:         #ECEDF0;
	--ds-ink2:        #9EA2AC;
	--ds-accent:      #4B67E8;
	--ds-accent-soft: #1E2442;
	--ds-accent-text: #B3C2FF;
	--ds-warm:        #261F17;
	--ds-warm-line:   #3E3226;
	--ds-warm-ink:    #FFCF97;
	--ds-rail:        #121317;
	--ds-brand-ink:   #ECEDF0;

	--ds-danger:      #FF9A8F; /* 8.68 on this surface */
	--ds-good:        #6FD39B; /* 9.69 */
	--ds-focus:       rgba(75, 103, 232, .34);
	--ds-shadow:      0 1px 2px rgba(0, 0, 0, .40), 0 2px 6px rgba(0, 0, 0, .32);
	--ds-shadow-pop:  0 12px 32px rgba(0, 0, 0, .50);

	--ds-bg-rgb:      13, 14, 17;
	--ds-surface-rgb: 23, 24, 28;
	--ds-ink-rgb:     236, 237, 240;
	--ds-ink2-rgb:    158, 162, 172;
	--ds-accent-rgb:  75, 103, 232;
	--ds-surface2-rgb: 31, 32, 37;
	--ds-line-rgb:    42, 44, 50;
	--ds-accent-soft-rgb: 30, 36, 66;
	--ds-accent-text-rgb: 179, 194, 255;
}

/* Night — the NAVY column of Dana's prototype, over the dark block above
   (Kevin, 30 Sep 2026, e-dark-night b: "Swap them"; her prototype and
   Monday call this one Dark). A third palette, not a shade: navy #161A2E
   against Dark's near-black #0D0E11. */
html:root[data-ek-scheme="night"] {
	color-scheme: dark;
	--ds-bg:          #161A2E;
	--ds-surface:     #22273F;
	--ds-surface2:    #2A2F4B;
	--ds-line:        #353B5C;
	--ds-ink:         #EDEFF8;
	--ds-ink2:        #A9AFCB;
	--ds-accent:      #4B67E8;
	--ds-accent-soft: #2B3363;
	--ds-accent-text: #B3C2FF;
	--ds-warm:        #342B24;
	--ds-warm-line:   #54432F;
	--ds-warm-ink:    #FFCF97;
	--ds-rail:        #1B1F35;
	--ds-brand-ink:   #EDEFF8;

	--ds-danger:      #FF9A8F; /* 7.18 on this surface */
	--ds-good:        #6FD39B; /* 8.02 */

	--ds-bg-rgb:      22, 26, 46;
	--ds-surface-rgb: 34, 39, 63;
	--ds-ink-rgb:     237, 239, 248;
	--ds-ink2-rgb:    169, 175, 203;
	--ds-accent-rgb:  75, 103, 232;
	--ds-surface2-rgb: 42, 47, 75;
	--ds-line-rgb:    53, 59, 92;
	--ds-accent-soft-rgb: 43, 51, 99;
	--ds-accent-text-rgb: 179, 194, 255;
}

/*
 * BuddyNext's pinned accent, back on the token set (30 Sep 2026).
 *
 * `buddynext_brand_color` is set on the box, so `Theme\Appearance::
 * attach_accent()` (BuddyNext 1.2.1, includes/Theme/Appearance.php:119-170)
 * prints `:root,[data-bn-theme]{--bn-accent:#3F5BD9;--bn-accent-700:…}` AFTER
 * the token map — one hex for every scheme. Measured in dark on the Settings
 * page: `--bn-accent` #3F5BD9, which as text on the dark ground is about 3:1.
 * `html:root` / `html[data-bn-theme]` (0,1,1) out-rank that (0,1,0) wherever
 * each stylesheet lands. Its primary buttons keep the admin hex (they are
 * pinned with !important inside `.bn-app`), and white on it holds (5.66:1).
 *
 * In dark and night BuddyNext uses `--bn-accent` mostly as INK (131 uses,
 * playbook §6), so there it takes the accent's ink value — the lift the
 * playbook measured for the teal (feed 17 failures to 0), now in Dana's blue.
 */
html:root,
html[data-bn-theme] {
	--bn-accent:       var(--ds-accent);
	--bn-accent-700:   var(--ds-accent-text);
	--brand:           var(--ds-accent);
	--brand-hover:     color-mix(in oklch, var(--ds-accent) 86%, #000);
	--brand-light:     var(--ds-accent-soft);
}
html:root:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) {
	--bn-accent:       var(--ds-accent-text);
	--bn-accent-700:   var(--ds-accent-text);
	--bn-accent-fg:    var(--ds-bg);
	--brand-light:     var(--ds-accent-soft);
}

/* ──────────────────────────────────────────────────────────────────────────
 * Retired 10 Sep 2026 (Theme and Brand §2.1), removed from this sheet 25 Sep:
 * `--ek-periwinkle` #6C8CFF and `--ek-peach` #F0A15F. Dana's palette (ruled
 * 26 Sep, rolled out everywhere 30 Sep) brings back a warm family and a hue per
 * person, but as her own values above, not these.
 * ────────────────────────────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════════════════
 * The document's own type and ground.
 *
 * ══════════════════════════════════════════════════════════════════════════
 * WHY THIS DID NOT EXIST UNTIL 27 SEPTEMBER 2026
 *
 * This stylesheet had no `html` rule, no `body` rule and no heading rule. Not
 * an oversight so much as a consequence: as a Reign CHILD it never needed
 * them — Reign set the site's base typography and every screen inherited it.
 * A child theme is allowed to be a list of exceptions. A theme is not.
 *
 * The moment `template` stopped being `reign-theme`, every element in the
 * product that does not name a font of its own fell to the browser's initial
 * value, which is a serif. Kevin, within a minute: *"we still have serif fonts
 * popping up all over the screens."*
 *
 * ══════════════════════════════════════════════════════════════════════════
 * WHY `html` AND NOT ONLY `body`
 *
 * BuddyNext's shell bootstrap (`assets/js/shell/font-scale.js`) runs in the
 * HEAD, before `<body>` exists, reads the host theme's font off the root
 * element, and pins it as an INLINE style on `<html>`:
 *
 *     --bn-theme-font: "Times New Roman"; --bn-theme-heading-font: …
 *
 * An inline style beats every stylesheet rule, so BuddyNext's whole component
 * layer went serif and no amount of CSS could reach it — the token map in
 * `functions.php` was emitting the right value and losing to the attribute.
 * The script captures whatever the root element computes to, so the fix is to
 * give the ROOT a font. `body` alone would leave the script reading the
 * initial value one more time and pinning the serif again.
 *
 * ══════════════════════════════════════════════════════════════════════════
 * WHAT IS DELIBERATELY NOT DONE HERE
 *
 * `--ek-font-body` names Inter, and Inter is NOT enqueued site-wide — only
 * Outfit is. So body text resolves to the next face in the stack, which is
 * `system-ui`, and that is exactly how the app has always looked. Loading
 * Inter would change the body face of every screen, and doing that inside a
 * fix for a regression is how a regression fix becomes its own bug report.
 * It is a separate decision, and it sits beside a live question for Dana:
 * her boards set reading text in **Figtree**, not Inter.
 * ══════════════════════════════════════════════════════════════════════════ */

html {
	/*
	 * Load-bearing for BuddyNext's head script — see above. The stack carries
	 * its own fallbacks, so this is correct whether or not a webfont loads.
	 */
	font-family: var(--ek-font-body);
	-webkit-text-size-adjust: 100%;
	box-sizing: border-box;
}

/*
 * The base layer Reign carried (30 Sep 2026), restored as Reign wrote it
 * (critical.css in 8.0.7): border-box on the root, INHERITED below it, not
 * forced. Every vendor surface on this site was built and walked under exactly
 * this rule until 27 Sep, and the inherit form lets any component that sets
 * content-box on itself keep it for its children. The two places that had to
 * force border-box since (rail.css `.bn-app__rail`, the messenger tabs in
 * better-messages-aurora.css) are unaffected.
 */
*,
*::before,
*::after {
	box-sizing: inherit;
}

/* Text for screen readers only — WordPress core's pattern. The skip link in
   header.php is one; on focus it shows, top left, above everything. */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	width: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	position: absolute !important;
	word-wrap: normal !important;
}
.screen-reader-text:focus {
	clip: auto !important;
	clip-path: none;
	display: block;
	height: auto;
	width: auto;
	top: 8px;
	left: 8px;
	z-index: 100000;
	padding: 12px 16px;
	border-radius: 10px;
	background: var(--ds-surface);
	color: var(--ds-accent-text);
	outline: 2px solid var(--ds-accent-text);
	outline-offset: 2px;
	font: 600 15px/1.2 var(--ek-font-body);
	text-decoration: none;
}

body {
	margin: 0;
	font-family: var(--ek-font-body);
	font-size: 15px;
	line-height: 1.55;
	color: var(--ds-ink);
	background: var(--ds-bg);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

/*
 * Outfit carries display, Inter (or the system face behind it) carries
 * reading — Dana's rule since 10 September, and the one thing the boards have
 * never disagreed about. Stated once here rather than repeated on each of the
 * forty-odd rules in this file that were naming `--ek-font` only because
 * nothing else was.
 */
h1, h2, h3, h4, h5, h6 {
	font-family: var(--ek-font);
	font-weight: 700;
	line-height: 1.2;
	text-wrap: balance;
}

/*
 * Core's own form controls do not inherit type. Reign restated this; with no
 * parent, a search box and a comment field would have gone serif alongside
 * everything else — and a form field in a different face from its label is
 * the most visible version of this bug.
 */
button,
input,
optgroup,
select,
textarea {
	font-family: inherit;
	font-size: inherit;
	line-height: inherit;
}

/* Header badges — Build Brief 5.11 */
.ek-badge,
.bm-unread-badge,
.bn-mobile-nav .bn-badge,
.site-header .bn-notifications-badge {
	background: var(--ek-button);
	color: var(--ek-white);
	font-family: var(--ek-font);
	font-weight: 600;
	border-radius: var(--ek-radius-pill);
	min-width: 18px;
	height: 18px;
	line-height: 18px;
	font-size: 11px;
	text-align: center;
	padding: 0 5px;
}

/* Phone header carries no inbox icon — Build Brief 5.2 (desktop keeps it).
   The icon is BuddyNext's .bn-header-msg markup, rendered by the child-theme
   override buddynext/blocks/header-user-menu.php. */
@media (max-width: 767px) {
	.bn-header-msg.ek-header-inbox { display: none !important; }
}

/* Better Messages skin is in assets/css/better-messages-aurora.css */

/* ── Install-the-app card (child theme; JS in assets/js/pwa-install.js) ──
   Solid white card on the Aurora ground, above the bottom bar on phones,
   bottom-right on desktop. Never glass. */
.ek-install {
	position: fixed;
	z-index: 10000;
	left: 12px;
	right: 12px;
	bottom: calc(12px + env(safe-area-inset-bottom, 0px) + 64px); /* clear the 5-slot bottom bar */
	display: grid;
	grid-template-columns: 48px 1fr;
	grid-template-areas: "icon text" "actions actions";
	gap: 10px 14px;
	padding: 14px 16px;
	background: var(--ds-surface);
	color: var(--ds-ink);
	border-radius: var(--ek-radius);
	box-shadow: var(--ds-shadow-pop);
	font-family: var(--ek-font);
	opacity: 0;
	transform: translateY(12px);
	transition: opacity .25s ease, transform .25s ease;
}
.ek-install.is-visible { opacity: 1; transform: none; }
.ek-install__icon { grid-area: icon; width: 48px; height: 48px; border-radius: 12px; }
.ek-install__text { grid-area: text; min-width: 0; }
.ek-install__title { margin: 0 0 2px; font-weight: 600; font-size: 16px; }
.ek-install__body { margin: 0; font-size: 14px; opacity: .85; }
.ek-install__steps { margin: 8px 0 0; padding: 0; list-style: none; font-size: 14px; }
.ek-install__steps li { display: flex; align-items: center; gap: 8px; margin-top: 4px; color: var(--ek-teal-text); }
.ek-install__actions { grid-area: actions; display: flex; gap: 8px; justify-content: flex-end; }
.ek-btn--ghost { background: transparent; color: var(--ek-teal-text); }

@media (min-width: 768px) {
	.ek-install {
		left: auto;
		right: 24px;
		bottom: 24px;
		width: 380px;
	}
}

/* Footer copyright: the brand is "eKlektiv." with a lower-case e; Reign's
   footer capitalises text, which rendered it "EKlektiv." (10 Sep 2026). */
#reign-copyright-text,
#reign-copyright-text .reign-footer-site-title {
	text-transform: none;
}

/* ── Pronouns hidden (Kevin, 11 Sep 2026) ──────────────────────────────────
   The profile header drops them server-side (companion Chrome/Profile.php).
   Edit Profile has no per-field hook (BuddyNext templates/profile/edit.php
   field loop), so the field block is hidden here. Its input still posts the
   stored value, so a save never erases it. The header rule is a belt for any
   other surface that reuses the class. */
.bn-ep-field:has(#bn-field-pronouns),
.bn-pf-pronouns {
	display: none !important;
}

/* ── "Joined <date>" off member cards (interface walk B2, Kevin 11 Sep 2026) ─
   Space → Members prints it in p.bn-md-card__meta (BuddyNext 1.1.7
   templates/spaces/members.php:384; 1.2.0 parts/space-members-body.php:427; no
   filter); that class is used nowhere else. The profile header keeps its
   "Joined" line. */
p.bn-md-card__meta {
	display: none !important;
}

/* "Member since <year>" replaces the Joined line on space member cards
   (Kevin, 11 Sep 2026). Printed by the companion (Chrome/Profile.php) under the
   @handle, with the vendor's meta class for its type and colour. */
.bn-md-card__labels .ek-member-since {
	display: block;
	margin-top: 2px;
}

/* ── "Members only" audience hidden (Kevin, 15 Sep 2026) ────────────────────
   BuddyNext 1.2.0 adds it for site admins and space owners: the audience list
   item in the main feed composer, and a lock toggle in a space's tool row
   (templates/partials/composer.php:527-535, :622-634). eKlektiv is invite-only
   behind login, so a guest never reaches a post and the option only duplicates
   Public. No filter gates either control. Neither exists in 1.1.7. */
.bn-composer__privacy-pop li:has(> .bn-composer__privacy-opt[data-privacy="members"]),
.bn-composer__tool[data-wp-on--click="actions.toggleMembersOnly"] {
	display: none !important;
}

/* ── Profile row, member viewing member (interface walk B5, Kevin 11 Sep 2026)
   The Follow wrapper takes no box of its own so the shared control sits in the
   row like its siblings; the hidden attribute still removes it once connected.
   "✓ Connected" is status, not an action, so it sits under the row. */
.bn-pf-actions .ek-pf-follow {
	display: contents;
}
.bn-pf-actions .ek-pf-follow[hidden],
.bn-pf-actions .ek-disconnect-trigger {
	display: none !important;
}
.ek-pf-connected {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 10px 0 0;
	font-family: var(--ek-font);
	font-size: 14px;
	font-weight: 600;
	color: var(--ds-accent-text);
}
.ek-pf-connected[hidden] {
	display: none !important;
}
.ek-pf-connected svg {
	width: 16px;
	height: 16px;
}


/* Activity feed tabs, in priority order (Kevin, 12 Sep 2026).
   All · Groups · Contacts · Voices, "top priority to least".

   BuddyNext builds the strip as a plain array with no filter
   (templates/feed/home.php:194-206), so there is nothing to reorder server
   side. The strip is a flex row (.bn-tabs, bn-base.css:3362), so `order` moves
   the tabs with no flash of the vendor's sequence and no dependence on
   JavaScript. messaging.js then moves the elements themselves so keyboard and
   screen-reader order match what is on screen; these values are keyed to
   data-filter, not to position, so the two agree either way.

   The slugs are the vendor's and do not change: for-you = All,
   spaces = Groups, network = Contacts, following = Voices. */
.bn-feed-filter-tabs .bn-feed-filter-tab[data-filter="for-you"]   { order: 1; }
.bn-feed-filter-tabs .bn-feed-filter-tab[data-filter="spaces"]    { order: 2; }
.bn-feed-filter-tabs .bn-feed-filter-tab[data-filter="network"]   { order: 3; }
.bn-feed-filter-tabs .bn-feed-filter-tab[data-filter="following"] { order: 4; }


/* The bell's count, back on the bell (Kevin, 13 Sep 2026).

   Kevin: "we have a stray message count or notification count showing above
   the profile avatar". It is the notification bell's own badge, thrown clear
   of the bell by a collision between the two vendors — neither of which is
   wrong on its own:

     BuddyNext  .bn-block-notification-bell { position: relative }
                bn-header.css:55-58, so the badge it positions
                `absolute; top:1px; inset-inline-end:1px` sits on the icon.

     Reign      .reign-navbar-user > a,
                .reign-navbar-user > div  { position: static !important }
                in BOTH critical.min.css and main.min.css.

   Reign's carries !important, so the bell block is static whatever we say
   about specificity; the badge then finds no positioned ancestor inside the
   cluster and resolves against `nav#site-navigation`, landing at the whole
   navbar's top-right corner — which is where the avatar is. Measured on the
   sandbox: the bell sits at x=797..837 and its badge was drawn at x=865, y=1.

   The fix does not fight the !important. Reign's selector only matches DIRECT
   children of `.reign-navbar-user`, and the badge's own parent — the 40x40
   link — is a GRANDchild, so it is untouched by that rule and can simply be
   made the containing block. That is also where the badge belongs: on the icon
   button rather than on the wrapper around it. No !important, and nothing to
   unpick if Reign ever drops theirs.

   The messages icon rides the same rule: BuddyNext positions its badge
   identically, so if it is ever turned on it would land in the same wrong
   place for the same reason. */
.reign-navbar-user .bn-block-notification-bell > .bn-notification-bell-link,
.reign-navbar-user .bn-block-notification-bell > .bn-header-msg {
	position: relative;
}


/* Notifications, at half the height (Kevin, 13 Sep 2026: "this is ugly").

   Measured before touching anything, at 375px: a row with actions was **164px
   tall** to carry **39px** of sentence. The other 125px was chrome, and most of
   it was the same fact repeated:

     .bn-notif-row__text     39px  "Marcus O'Brien and 1 other posted in a group."
     .bn-notif-row__meta     44px  a chip reading "New post in group", the time,
                                   and the dismiss ×
     .bn-notif-row__actions  40px  "Open" and "Mark as read"
     padding                 24px

   Three of those earn their place. The rest is duplication:

   1. **The chip repeats the sentence.** The row says "posted in a group" and
      the chip says "New post in group" — and the little icon on the avatar
      (`__type`, which keeps its `aria-label`) says it a third time. One of the
      three is enough, and the sentence is the one a person actually reads.
   2. **The actions repeat the row.** The row itself carries
      `data-wp-on--click="actions.markRead"` and `data-notif-link`, so tapping
      anywhere already opens it AND marks it read. "Open" and "Mark as read"
      are a second copy of the row's own behaviour, given a whole 40px band.

   **"Open" is NOT hidden, and that is deliberate.** The row is a `div` with a
   click handler, not a link, so it takes no keyboard focus — which makes that
   anchor the only way to reach the notification without a mouse. Removing it
   would have tidied the screen by breaking it for anybody on a keyboard. It
   stays, shrunk to a quiet inline link beside the time, where it costs nothing.

   Everything here is CSS over the vendor's own markup (CLAUDE.md rule 3); no
   template is copied and no behaviour is replaced. */

/* One line for time and actions instead of two stacked bands.

   A GRID with both cells named, not a wrapping flex row. Wrapping was tried
   first and did not work: the two boxes measure 42px and 114px inside a 255px
   body, so they had room to share a line and still broke onto separate ones.
   Naming the cells makes the outcome a fact rather than a negotiation, and it
   also means a stray pseudo-element among the vendor's children cannot push
   anything onto a line of its own. */
.bn-notif-row__body {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: baseline;
	gap: 2px 10px;
	min-width: 0;
}

.bn-notif-row__text {
	grid-column: 1 / -1;
	min-width: 0;
	line-height: 1.4;
}

.bn-notif-row__meta {
	grid-column: 1;
	grid-row: 2;
	gap: 0 8px;
	min-height: 0;
	margin: 0;
}

.bn-notif-row__actions {
	grid-column: 2;
	grid-row: 2;
	justify-self: start;
	min-height: 0;
	margin: 0;
}

/* The chip. Its job is done by the sentence above it and by the type icon on
   the avatar, which keeps its own aria-label, so nothing is lost to a screen
   reader. */
.bn-notif-row__meta > .bn-badge { display: none; }

/* `--ek-dir-muted`, not `--bn-muted` (14 Sep 2026). BuddyNext declares no
   `--bn-muted` — its muted inks are `--bn-ink-2/3/4` — so all four uses in this
   file always fell back to #667085, a light-mode grey, in both themes. On a
   dark notifications page that measured 2.98:1 across every timestamp and
   every Open / Mark as read link: 22 failures on one screen. The same class of
   bug as the undeclared --ek-dir-line tokens found in Upcoming on 13 Sep —
   a var() whose fallback silently became the only value. --ek-dir-muted is
   #667085 in light, so nothing moves there, and #A0A7B2 in dark. */
.bn-notif-row__time {
	font-size: 12px;
	color: var(--ds-ink2);
}

/* Quiet, inline, and no longer a band of their own. */
.bn-notif-row__actions .bn-btn {
	padding: 0;
	min-height: 0;
	height: auto;
	border: 0;
	background: none;
	font-size: 12px;
	font-weight: 500;
	color: var(--ds-ink2);
	text-decoration: none;
}

.bn-notif-row__actions .bn-btn:hover,
.bn-notif-row__actions .bn-btn:focus-visible {
	color: var(--ds-accent-text);
	text-decoration: underline;
}

/* The × was a 44px control sitting inside the meta line, and it alone set that
   line's height. Lifted out to the row's own corner: the touch target stays 44px
   (it must), it just stops inflating the text column. */
.bn-notif-row {
	position: relative;
	padding: 11px 44px 11px 12px;
	gap: 10px;
}

.bn-notif-row__dismiss {
	position: absolute;
	top: 4px;
	right: 4px;
	width: 40px;
	height: 40px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* The tab strip overflows its container (700px of tabs in 351px at phone
   width), so "Comments" was clipped mid-word with nothing to say it continued.
   Let it scroll, and take the scrollbar off since the cut-off tab is now the
   affordance. */
.bn-notif-tabs {
	overflow-x: auto;
	flex-wrap: nowrap;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

.bn-notif-tabs::-webkit-scrollbar { display: none; }
.bn-notif-tabs > * { flex: 0 0 auto; }


/* Accept / Decline on a connection request (Kevin, 13 Sep 2026).

   The controls are rendered by the companion on the vendor's own
   `buddynext_part_notification_row_after`, which fires OUTSIDE the row's
   closing tag — so they arrive as a sibling, not a child. This tucks them back
   against the row they belong to and matches the unread tint from BuddyNext's
   own `--bn-accent-50`, so the join reads as one object rather than a strip
   bolted underneath.

   The left padding lines the buttons up under the sentence, clear of the
   avatar column, rather than under the avatar. */
.ek-connreq {
	display: flex;
	gap: 8px;
	margin: -11px 0 0;
	padding: 0 12px 12px 50px;
	border-bottom: 1px solid var(--ds-line);
}

.ek-connreq--unread { background: var(--bn-accent-50, var(--ds-accent-soft)); }

.ek-connreq form { margin: 0; }

.ek-connreq__btn {
	padding: 6px 14px;
	border: 1px solid transparent;
	border-radius: 999px;
	font-family: var( --ek-dir-body, Inter, system-ui, sans-serif );
	font-size: 12.5px;
	font-weight: 600;
	line-height: 1.3;
	cursor: pointer;
}

/* `--ek-teal-fill`, not `--ek-teal-text` (14 Sep 2026) — a regression of mine.
   On 13 Sep --ek-teal-text was lifted to #6FDCCB in dark because it is an ink,
   and its uses were checked for fills first. That check matched
   `var(--ek-teal-text)` with no spaces and no fallback, so this rule — written
   `var(--ds-accent-text)` — was never seen, and Accept would have
   gone mint with white type in dark. No pending request was on screen to
   show it. --ek-teal-fill is the token that never follows the theme. */
.ek-connreq__btn--yes {
	background: var(--ds-accent);
	color: var(--ds-on-accent);
}

.ek-connreq__btn--yes:hover,
.ek-connreq__btn--yes:focus { background: color-mix(in oklch, var(--ds-accent) 82%, #000); }

.ek-connreq__btn--no {
	background: transparent;
	border-color: var(--ds-line);
	color: var(--ds-ink2);
}

.ek-connreq__btn--no:hover,
.ek-connreq__btn--no:focus { color: var(--ds-ink); border-color: var(--ds-ink2); }

/* The unread dot, off the dismiss button.

   Moving the × into the row's top-right corner (above) put it exactly where
   BuddyNext already pins `.bn-notif-row__pulse` — measured overlapping, dot
   806..832 inside button 804..844, so the dot was drawn underneath it. The dot
   moves to the leading edge, which is where an unread marker reads best anyway:
   a rail down the left of the list, scannable in one pass, instead of a mark
   competing with a control. */
.bn-notif-row__pulse {
	inset-block-start: 50%;
	inset-inline-end: auto;
	inset-inline-start: 3px;
	transform: translateY( -50% );
}


/* The dark values of the Aurora names (`--ek-ink` #E6E8EB, `--ek-teal-text`
   #6FDCCB, `--ek-muted`/`--ek-faint` #A7A7A7; 13 and 26 Sep 2026) were removed on
   30 Sep: those names are aliases of `--ds-*` now (the token set at the top), so
   they follow Light, Dark and Night without a block of their own. */

/* ══════════════════════════════════════════════════════════════════════════
 * Article cards: tap the cover to play the video (Kevin, 15 Sep 2026).
 *
 * The companion draws the card (Chrome/ArticleCards.php::render_video_card())
 * with BuddyNext's own article-card classes, so the vendor's border, 16:9 cover
 * cap and body type all still apply; this only styles what it adds — the cover
 * as a button with a play mark, and the player that replaces it
 * (assets/js/article-video.js). The play mark is a FILL (`--ek-button` with a
 * white glyph), so it deliberately does not flip in dark mode.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-article-video__play {
	position: relative;
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	font: inherit;
	color: inherit;
	cursor: pointer;
}

.ek-article-video__play img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ek-article-video__icon {
	position: absolute;
	top: 50%;
	left: 50%;
	display: grid;
	place-items: center;
	width: 64px;
	height: 64px;
	border-radius: 50%;
	background: var(--ds-accent);
	color: var(--ds-on-accent);
	box-shadow: 0 4px 16px rgb(0 0 0 / 0.35);
	transform: translate(-50%, -50%);
	transition: transform 0.15s ease;
}

.ek-article-video__icon svg {
	margin-left: 3px; /* The triangle's optical centre sits right of its box. */
}

.ek-article-video__play:hover .ek-article-video__icon {
	transform: translate(-50%, -50%) scale(1.08);
}

.ek-article-video__play:focus-visible {
	outline: 3px solid var(--ds-accent-text);
	outline-offset: -3px;
}

.bn-post-card__article.ek-article-video:focus-within {
	border-color: var(--bn-accent);
}

.ek-article-video__body {
	color: inherit;
	text-decoration: none;
}

.ek-article-video__stage {
	position: relative;
}

.ek-article-video__frame {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

@media (prefers-reduced-motion: reduce) {
	.ek-article-video__icon {
		transition: none;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * Header search pop-up, in dark (Kevin, 15 Sep 2026: "in dark mode it is hard
 * to read").
 *
 * Reign's pop-up (`.search-wrap .rg-search-form-wrap`, Reign 8.0.7
 * `assets/css/main.css:3189-3274`) paints the field with its generic
 * `input[type="search"]` rule on `--reign-form-*` tokens. In dark that put a
 * #181d24 field on a #1a2028 panel, measured on /activity/:
 *   field vs panel 1.03:1, field edge vs panel 1.19:1 (UI edges need 3:1),
 *   a 4%-black panel shadow that vanishes on the dark page (playbook 3.8),
 *   and Reign's blue (#97c0ee) as the focus edge plus a second white outline
 *   (`input[type="search"]:focus-visible`), the blue trap in playbook 3.7.
 *
 * Here the field takes the blue-grey of BuddyNext's left rail (`.bn-app` /
 * `.bn-rail__item`, #23262F in dark; Kevin, 15 Sep 2026, pinned rather than
 * `var(--bn-bg)`, playbook 3.1) with a visible edge, the placeholder takes the
 * house muted ink, focus is the house teal ring, and the close icon matches the
 * muted ink with the house danger on hover. Measured with the values below:
 * text 12.31, placeholder 6.23, search icon 7.19, field edge 3.42 on the field
 * and 3.70 on the panel, close 6.76, focus teal 9.19. Light mode is untouched.
 *
 * `!important` on the close glyph only: Reign sets that colour with
 * `!important` (`main.css:3236-3243`), which nothing else can beat.
 * ══════════════════════════════════════════════════════════════════════════ */
:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) .search-wrap .rg-search-form-wrap {
	border-color: var(--ds-line);
	box-shadow: var(--ds-shadow);
}

:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) .search-wrap .rg-search-form-wrap form.search-form input.search-field {
	background-color: var(--ds-surface2);
	border-color: var(--ds-ink2);
	color: var(--ds-ink);
}

:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) .search-wrap .rg-search-form-wrap form.search-form input.search-field::placeholder {
	color: var(--ds-ink2);
	opacity: 1;
}

:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) .search-wrap .rg-search-form-wrap form.search-form input.search-field:focus {
	border-color: var(--ds-accent-text);
	box-shadow: 0 0 0 3px var(--ds-focus);
	outline: none;
}

:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) .search-wrap .rg-search-close::before {
	color: var(--ds-ink2) !important;
}

@media (hover: hover) and (pointer: fine) {
	:is([data-bn-theme="dark"], [data-theme="dark"], [data-bx-mode="dark"]) .search-wrap .rg-search-close:hover::before {
		color: var(--ds-danger) !important;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * The member's home, above the feed — Dana's MobileHome board, in her palette.
 *
 * Drawn by `Chrome\Home` on `buddynext_feed_home_before`.
 *
 * **Moved to `--ds-*` on 26 Sep 2026** (Kevin: "apply this to the others"),
 * after People proved the palette against her board. The Next-up strip is now
 * her WARM family rather than teal — she drew it amber, that was flagged as a
 * departure while §2.1 allowed no warm accent, and her palette turns out to
 * contain exactly that family. Her drawing was right and the teal was the
 * deviation.
 *
 * The group rows follow People: one card, hairline-separated rows inside it,
 * rather than a stack of separately bordered boxes.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-home {
	display: flex;
	flex-direction: column;
	gap: 16px;
	margin: 0 0 22px;
	color: var(--ds-ink);
}


.ek-home__eyebrow {
	font-family: var(--ek-font);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ds-ink2);
	margin: 0 0 8px;
}
.ek-home__bucket { font-weight: 700; }

/* ══════════════════════════════════════════════════════════════════════════
 * Coming up, and Your groups — Dana's MobileHomeAlt board, 27 September 2026.
 *
 * Kevin: *"check the latest version of mobile home screen for the gallery
 * controls on my groups and coming event cards."* Both were single columns —
 * one wide "Next up" strip and a vertical list of group rows. Her newer board
 * makes both horizontal galleries you swipe.
 *
 * Her measurements, not approximations of them: 300px event cards, 148px group
 * tiles, 12px between, 22px radii, `scroll-snap-align: start`.
 *
 * **The rail bleeds to both screen edges.** `margin-inline: -16px` cancels the
 * page gutter and `padding-inline: 16px` puts it back inside, so the first card
 * lines up with the heading above it and the last can be swiped clear of the
 * screen. The 4px tail is hers, and it is what stops the last card sitting
 * flush against the edge at the end of a swipe.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-home__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin: 22px 4px 0;
}
.ek-home__h2 {
	margin: 0;
	font-family: var(--ek-font);
	font-size: 18px;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--ds-ink);
}
.ek-home__seeall {
	display: flex;
	align-items: center;
	gap: 2px;
	padding: 6px 0;
	font-family: var(--ek-font);
	font-size: 14px;
	font-weight: 700;
	color: var(--ds-accent-text);
	text-decoration: none;
	white-space: nowrap;
}
.ek-home__seeall:hover { text-decoration: underline; }
.ek-home__chev { flex: 0 0 auto; }

.ek-home__rail {
	display: flex;
	gap: 12px;
	margin: 10px -16px 0;
	padding: 0 16px 6px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior-x: contain;
}
/* Her rails carry no scrollbar; the cards' own edges say there is more. */
.ek-home__rail::-webkit-scrollbar { display: none; }
.ek-home__rail-end { flex: 0 0 auto; width: 4px; }

/* ── One event card ──────────────────────────────────────────────────── */
.ek-home__ev {
	flex: 0 0 auto;
	width: 300px;
	scroll-snap-align: start;
	box-sizing: border-box;
	padding: 18px;
	border-radius: 22px;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
}
/*
 * Soon wears her WARM family. That is her system doing the job it is for —
 * warm is the colour of a thing with a time on it — and it is why the amber
 * she drew was never a drawing artifact.
 */
.ek-home__ev.is-hot {
	background: var(--ds-warm);
	border-color: var(--ds-warm-line);
}
/*
 * The card is a link now (Kevin, 27 Sep 2026), so it needs a link's manners:
 * no underline on the card itself, its own focus ring, and a visible answer to
 * a hover. The title used to carry all three and only covered its own line.
 */
a.ek-home__ev {
	text-decoration: none;
	color: inherit;
}

a.ek-home__ev:hover {
	border-color: var(--ds-accent);
}

a.ek-home__ev:focus-visible {
	outline: 2px solid var(--ds-accent);
	outline-offset: 2px;
}

.ek-home__ev-eyebrow {
	margin: 0;
	font-family: var(--ek-font);
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: 0.08em;
	color: var(--ds-ink2);
}
.ek-home__ev.is-hot .ek-home__ev-eyebrow { color: var(--ds-warm-ink); }
.ek-home__ev-title {
	margin: 4px 0 0;
	font-family: var(--ek-font);
	font-size: 21px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.015em;
	color: var(--ds-ink);
}
.ek-home__ev.is-hot .ek-home__ev-title { color: var(--ds-warm-ink); }
.ek-home__ev-title a { color: inherit; text-decoration: none; }
.ek-home__ev-title a:hover { text-decoration: underline; }
.ek-home__ev-where {
	margin: 4px 0 0;
	font-size: 14px;
	line-height: 1.4;
	color: var(--ds-ink2);
}
.ek-home__ev.is-hot .ek-home__ev-where { color: var(--ds-warm-ink); opacity: .82; }
.ek-home__ev-going {
	margin: 12px 0 0;
	font-size: 13px;
	font-weight: 700;
	color: var(--ds-accent-text);
}
.ek-home__ev.is-hot .ek-home__ev-going { color: var(--ds-warm-ink); }

/* ── One group, and the gallery of many ──────────────────────────────── */
/* A young person's Home: Key Flows v68, Family board 7 (Family\YouthHome). */
.ek-home__yhcard { display: flex; align-items: center; gap: 12px; margin-top: 10px; padding: 12px 14px; border: 1px solid var(--ds-line); background: var(--ds-surface); border-radius: var(--ds-radius); }
.ek-home__yhmark, .ek-home__yhinit { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; color: #fff; font-weight: 700; font-size: 14px; }
.ek-home__yhmark { border-radius: 10px; background: var(--ds-accent); color: var(--ds-on-accent); }
.ek-home__yhface { flex: none; width: 40px; height: 40px; border-radius: 50%; object-fit: cover; }
.ek-home__yhtext { display: flex; flex-direction: column; min-width: 0; }
.ek-home__yhtitle { font-weight: 700; overflow-wrap: anywhere; }
.ek-home__yhsub { font-size: 13px; color: color-mix(in srgb, var(--ds-ink) 68%, transparent); overflow-wrap: anywhere; }
.ek-home__yhfam { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ek-home__yhperson { display: flex; align-items: center; gap: 12px; }
.ek-home__yhempty { margin-top: 10px; padding: 14px; border: 1px dashed var(--ds-line); border-radius: var(--ds-radius); }
.ek-home__yhempty p { margin: 0 0 4px; }

/* A group saved at the Statement of Faith: Your groups, Key Flows v67 board 1c screen 4 (SofExits::saved_card). */
.ek-home__saved {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin-top: 10px;
	padding: 14px;
	border: 1px solid var(--ds-line);
	background: var(--ds-surface);
	border-radius: var(--ds-radius);
	color: var(--ds-ink);
}
.ek-home__saved-top { display: flex; align-items: center; gap: 12px; }
.ek-home__saved-tile { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 10px; color: #fff; font-weight: 700; font-size: 14px; }
.ek-home__saved-text { display: flex; flex-direction: column; min-width: 0; }
.ek-home__saved-name { font-weight: 700; overflow-wrap: anywhere; }
.ek-home__saved-line { font-size: 13px; color: color-mix(in srgb, var(--ds-ink) 68%, transparent); }
.ek-home__saved-replied { margin: 0; padding: 10px 12px; border-radius: 10px; font-size: 14px; background: color-mix(in srgb, var(--ds-good) 14%, var(--ds-surface)); }
.ek-home__saved-finish { display: block; min-height: 44px; line-height: 44px; border-radius: 10px; text-align: center; font-weight: 700; background: var(--ds-accent); color: var(--ds-on-accent); text-decoration: none; }
.ek-home__saved-del { margin: 0; text-align: center; }
.ek-home__saved-delete { min-height: 44px; padding: 0 8px; border: 0; background: none; color: var(--ds-accent-text); font: inherit; font-size: 14px; font-weight: 600; text-decoration: underline; cursor: pointer; }
.ek-home__saved-trust { display: flex; align-items: flex-start; gap: 8px; margin: 10px 0 0; font-size: 13px; color: color-mix(in srgb, var(--ds-ink) 68%, transparent); }
.ek-home__saved-trust .ek-trust__mark { flex: none; width: 16px; height: 16px; color: var(--ds-accent-text); }
.ek-home__saved-trust .ek-trust__mark svg { width: 16px; height: 16px; }

.ek-home__one {
	display: flex;
	align-items: center;
	gap: 14px;
	margin-top: 10px;
	padding: 12px;
	border: 1px solid var(--ds-line);
	background: var(--ds-surface);
	border-radius: 22px;
	color: var(--ds-ink);
	text-decoration: none;
}
.ek-home__one:hover { border-color: var(--ds-accent); }
.ek-home__one-tile {
	flex: 0 0 auto;
	width: 112px; height: 112px;
	border-radius: 20px;
	display: flex; align-items: center; justify-content: center;
	background: var(--ds-accent);
	color: var(--ds-on-accent);
	font-family: var(--ek-font);
	font-weight: 700; font-size: 30px;
	line-height: 1;
}
/* The same picture on the single-group card. */
img.ek-home__one-tile {
	object-fit: cover;
}

.ek-home__one-text { flex: 1 1 auto; min-width: 0; }
.ek-home__one-name {
	display: block;
	font-family: var(--ek-font);
	font-weight: 700; font-size: 19px; line-height: 1.2;
}
.ek-home__one-line { display: block; margin-top: 6px; font-size: 14px; color: var(--ds-ink2); }
.ek-home__one-go {
	display: block; margin-top: 10px;
	font-size: 13px; font-weight: 700; color: var(--ds-accent-text);
}

.ek-home__tile {
	flex: 0 0 auto;
	width: 148px;
	scroll-snap-align: start;
	display: flex;
	flex-direction: column;
	gap: 8px;
	color: var(--ds-ink);
	text-decoration: none;
}
.ek-home__tile-face {
	position: relative;
	width: 148px; height: 148px;
	border-radius: 22px;
	display: flex; align-items: center; justify-content: center;
	background: var(--ds-accent);
	color: var(--ds-on-accent);
	font-family: var(--ek-font);
	font-weight: 700; font-size: 32px;
	line-height: 1;
}
.ek-home__tile:hover .ek-home__tile-face { filter: brightness(1.06); }
.ek-home__tile:focus-visible .ek-home__tile-face {
	outline: 2px solid var(--ds-accent);
	outline-offset: 3px;
}
/* Her badge sits ON the tile, top-left, in the tile's hue on white. */
.ek-home__tile-lead {
	position: absolute;
	left: 10px; top: 10px;
	padding: 3px 6px;
	border-radius: 6px;
	background: #FFFFFF;
	font-family: var(--ek-font);
	font-size: 10.5px; font-weight: 700;
	letter-spacing: 0.06em;
	line-height: 1;
}
/*
 * The group's own picture, filling the tile. `object-fit: cover` because a
 * group's avatar is square but not always exactly so, and a squashed logo
 * reads as a mistake the group made rather than one we made.
 */
.ek-home__tile-img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	/*
	 * The radius is on the image, not `overflow: hidden` on the face: the
	 * "YOU LEAD" badge is a child of the face and sits ON the tile, and
	 * clipping the face would clip the badge with it.
	 */
	border-radius: 22px;
}

.ek-home__tile-name {
	display: block;
	padding: 0 2px;
	font-family: var(--ek-font);
	font-weight: 700; font-size: 14.5px; line-height: 1.25;
	/* Two lines, then clip: her tiles are the same height whatever they hold. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* ══════════════════════════════════════════════════════════════════════════
 * The bottom bar, in her accent.
 *
 * The markup is BuddyNext's and the active slot takes the vendor's own accent,
 * which this site sets to the brand teal through `buddynext_brand_color`
 * (Theme/Appearance.php, per the dark-mode playbook §3.1). That setting is
 * site-wide, so changing it would repaint every vendor surface at once —
 * exactly the rollout Kevin has not ruled on yet.
 *
 * So the bar is skinned here instead: the one surface a member looks at on
 * every screen moves to her accent, and nothing else does. When the rollout is
 * decided, the right move is the SETTING, and these rules come out.
 * ══════════════════════════════════════════════════════════════════════════ */
.bn-mobile-nav .bn-mobile-nav__item.is-active,
.bn-mobile-nav a[aria-current="page"] {
	color: var(--ds-accent-text);
}
.bn-mobile-nav .bn-mobile-nav__item.is-active svg,
.bn-mobile-nav a[aria-current="page"] svg {
	color: var(--ds-accent-text);
	stroke: var(--ds-accent-text);
}
/* `.bn-badge` is not the bar's badge — the bar uses `.bn-mobile-nav__badge`,
   which the Better Messages skin already paints with !important. Naming the
   wrong class here left the one visible badge teal after the flip. */
.ek-badge {
	background: var(--ds-accent);
	color: var(--ds-on-accent);
}

/* Dana's `--ds-*` palette was declared here from 26 Sep 2026, beside the teal
   and separate from it. Since 30 Sep it IS the token set, at the top of this
   sheet, with Light, Dark and Night. */

/* ══════════════════════════════════════════════════════════════════════════
 * People — Dana's PeoplePhone board, to her spacing and her surfaces.
 *
 * The first pass drew each person as a separate bordered row. Her board groups
 * a section into ONE card with hairline-separated rows inside it, and that is
 * most of why the screens read so differently: hers has two objects on the
 * page where mine had eleven.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-people {
	display: flex;
	flex-direction: column;
	gap: 18px;
	color: var(--ds-ink);
}

/*
 * Her top row — title left, the member's own chip right, on a 44px line
 * (boards/PeoplePhone.dc.html:24). It became the top of the screen on 26 Sep
 * 2026, when the People hub stopped rendering Reign's masthead (body.ek-bare,
 * below); before that the masthead was above it and a bare <h1> was enough.
 */
.ek-people__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	min-height: 44px;
}

/*
 * 25px / 700, which is what her board says. It was 28px / 800 — my value, not
 * hers, and a visible part of why the built screen read heavier than the
 * drawing.
 */
.ek-people__title {
	font-family: var(--ek-font);
	font-size: 25px;
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.1;
	color: var(--ds-ink);
	margin: 0;
}

/* The viewer's own chip: 36px to the 42px she gives other people, in the
   viewer's own hue (People::avatar_hue() sets the background inline). */
.ek-people__me {
	flex: 0 0 auto;
	width: 36px; height: 36px;
	border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	background: var(--ds-accent);
	color: var(--ds-on-accent);
	font-family: var(--ek-font);
	font-size: 14px; font-weight: 700;
	line-height: 1;
}

.ek-people__eyebrow {
	font-family: var(--ek-font);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ds-ink2);
	margin: 0 0 8px;
}

/* One card per section, rows inside it. */
.ek-people__list {
	list-style: none;
	margin: 0;
	padding: 0;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius-lg);
	overflow: hidden;
}
.ek-people__row {
	display: flex;
	align-items: center;
	gap: 12px;
	margin: 0;
	padding: 13px 15px;
	border-top: 1px solid var(--ds-line);
}
.ek-people__row:first-child { border-top: 0; }

/*
 * Now an <img>, not a letter (27 September 2026). The hue stays as the
 * element's background — `People::avatar_img()` sets it inline — so it shows
 * for the instant before the picture paints and behind a broken one.
 */
.ek-people__avatar {
	flex: 0 0 auto;
	width: 40px; height: 40px;
	border-radius: 50%;
	object-fit: cover;
	display: block;
	background: var(--ds-accent);
}

.ek-people__who-text { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ek-people__name {
	font-family: var(--ek-font);
	font-weight: 700; font-size: 15.5px; color: var(--ds-ink);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ek-people__line {
	font-size: 13px; color: var(--ds-ink2);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Message is an outline pill, Connect is filled. Hers, exactly. */
.ek-people__act {
	flex: 0 0 auto;
	font-family: var(--ek-font);
	font-size: 13px; font-weight: 700;
	text-decoration: none;
	padding: 8px 15px;
	border-radius: 999px;
	border: 1px solid var(--ds-line);
	color: var(--ds-accent-text);
	background: var(--ds-surface);
	cursor: pointer;
}
.ek-people__act:hover { border-color: var(--ds-accent); }
.ek-people__act--connect,
.ek-people__send {
	background: var(--ds-accent);
	border: 1px solid var(--ds-accent);
	color: var(--ds-on-accent);
}

.ek-people__note,
.ek-people__empty,
.ek-people__nomatch {
	margin: 0;
	font-size: 12.5px;
	color: var(--ds-ink2);
	max-width: 46ch;
	line-height: 1.5;
}
.ek-people__nomatch {
	padding: 14px 15px;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius-lg);
}
.ek-people__privacy-link { color: var(--ds-accent-text); font-weight: 600; }

/* Search */
.ek-people__search { display: flex; gap: 8px; align-items: center; margin: 0; }
.ek-people__search-field {
	flex: 1 1 auto; min-width: 0;
	font: inherit; font-size: 15px;
	color: var(--ds-ink); background: var(--ds-surface);
	border: 1px solid var(--ds-line); border-radius: 999px;
	padding: 12px 16px;
}
.ek-people__search-field::placeholder { color: var(--ds-ink2); }
.ek-people__search-go {
	flex: 0 0 auto;
	font-family: var(--ek-font); font-size: 14px; font-weight: 700;
	color: var(--ds-on-accent); background: var(--ds-accent);
	border: 0; border-radius: 999px; padding: 12px 18px; cursor: pointer;
}
.ek-people__search-clear { flex: 0 0 auto; font-size: 13px; font-weight: 600; color: var(--ds-accent-text); text-decoration: none; }

/* The person card — tap any name. */
/*
 * The person on a row IS the link to their profile.
 *
 * This was `details > summary` — Dana's "tap any name" as an expanding panel —
 * until Kevin looked at the built screen: *"I don't need the expanding cards,
 * they already have message button, and if I could click the names and go to
 * profile I would be set."* The panel is gone (People::who()), and with it the
 * `[open]` state that used to hide the row's action pill and re-wrap the row.
 *
 * No underline at rest: the row is a list, not prose, and 40+ underlined names
 * in one card is noise. The name underlines on hover and the whole block takes
 * a focus ring, so both pointer and keyboard say the same thing.
 */
.ek-people__who {
	flex: 1 1 auto;
	min-width: 0;
	display: flex; flex-direction: row; align-items: center; gap: 12px;
	text-decoration: none;
	color: inherit;
}
a.ek-people__who:hover .ek-people__name { text-decoration: underline; }
a.ek-people__who:focus-visible {
	outline: 2px solid var(--ds-accent);
	outline-offset: 3px;
	border-radius: var(--ds-radius);
}

/* The connect sheet */
.ek-people__connect > summary { list-style: none; cursor: pointer; display: inline-block; }
.ek-people__connect > summary::-webkit-details-marker { display: none; }
.ek-people__connect[open] > summary {
	background: var(--ds-accent-soft);
	color: var(--ds-accent-text);
	border-color: var(--ds-accent);
}
.ek-people__sheet {
	margin-top: 12px; padding: 15px;
	border-radius: var(--ds-radius);
	background: var(--ds-surface2);
	display: flex; flex-direction: column; gap: 9px;
}
.ek-people__sheet-title { margin: 0; font-family: var(--ek-font); font-weight: 700; font-size: 17px; color: var(--ds-ink); }
.ek-people__sheet-mutual { margin: 0; font-size: 13px; color: var(--ds-ink2); }
.ek-people__sheet-label { font-size: 13px; font-weight: 600; color: var(--ds-ink); }
.ek-people__optional { font-weight: 400; color: var(--ds-ink2); }
.ek-people__note-field {
	width: 100%; font: inherit; font-size: 14px;
	color: var(--ds-ink); background: var(--ds-surface);
	border: 1px solid var(--ds-line); border-radius: 12px;
	padding: 10px 12px; resize: vertical;
}
.ek-people__send { align-self: flex-start; font-size: 14px; border-radius: 999px; padding: 11px 20px; }
.ek-people__sheet-foot { margin: 0; font-size: 12.5px; color: var(--ds-ink2); line-height: 1.5; }

/* Sent — her accent-soft, not a teal wash. */
.ek-people__notice {
	margin: 0; padding: 12px 14px;
	border-radius: var(--ds-radius);
	background: var(--ds-accent-soft);
	color: var(--ds-accent-text);
	font-size: 14px; font-weight: 600;
}

/* Requests — the warm family is hers, and this is what it is for. */
.ek-people__request {
	margin: 0;
	padding: 15px;
	background: var(--ds-warm);
	border: 1px solid var(--ds-warm-line);
	border-radius: var(--ds-radius-lg);
	display: flex; flex-direction: column; gap: 11px;
}
.ek-people__request + .ek-people__request { margin-top: 8px; }
.ek-people__request-head { display: flex; align-items: center; gap: 12px; }
.ek-people__request .ek-people__name { color: var(--ds-warm-ink); }
.ek-people__request .ek-people__line { color: var(--ds-warm-ink); opacity: .78; }
.ek-people__request-note {
	margin: 0; padding: 11px 13px;
	border-radius: 12px;
	background: var(--ds-surface);
	font-size: 14px; color: var(--ds-ink); line-height: 1.45;
}
.ek-people__request-acts { display: flex; gap: 8px; flex-wrap: wrap; }

/* Who can find you */
.ek-people__back { margin: 0; font-size: 13px; }
.ek-people__back a { color: var(--ds-accent-text); text-decoration: none; font-weight: 600; }
.ek-people__privacy {
	list-style: none; margin: 0; padding: 0;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius-lg);
	overflow: hidden;
}
.ek-people__privacy-row {
	margin: 0; padding: 14px 15px;
	border-top: 1px solid var(--ds-line);
	display: flex; align-items: center; gap: 12px;
}
.ek-people__privacy-row:first-child { border-top: 0; }
.ek-people__privacy-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ek-people__privacy-name { font-family: var(--ek-font); font-weight: 700; font-size: 15px; color: var(--ds-ink); }
.ek-people__privacy-why { font-size: 13px; color: var(--ds-ink2); line-height: 1.45; }
.ek-people__privacy-fixed { flex: 0 0 auto; font-size: 15px; opacity: .45; }
.ek-people__switch {
	flex: 0 0 auto; cursor: pointer;
	font-family: var(--ek-font); font-size: 13px; font-weight: 700;
	border-radius: 999px; padding: 8px 18px;
	border: 1px solid var(--ds-line);
	background: var(--ds-surface2); color: var(--ds-ink2);
}
.ek-people__switch[aria-pressed="true"] {
	background: var(--ds-accent);
	border-color: var(--ds-accent);
	color: var(--ds-on-accent);
}

/* ══════════════════════════════════════════════════════════════════════════
 * Full-bleed hubs — the ground Reign's shell used to paint.
 *
 * `body.ek-bare` is set by `eklektiv_child_bare_chrome()` for the hubs listed
 * in `eklektiv/chrome/bare_hubs`, whose documents skip Reign's `#page`,
 * `#masthead` and `#content` entirely (the reasoning is at the top of
 * `header.php`). Everything here exists because one of those elements was
 * doing a job:
 *
 *   `#page.site` painted the page ground — so `body` paints it now;
 *   `#content` set the top rhythm under the masthead — there is no masthead,
 *      so the screen starts at its own gutter;
 *   `.bn-app` takes `--bn-canvas`, which is the vendor's ground, not Dana's.
 *
 * Nothing here styles the SCREEN. The People rules above are untouched; this
 * is only the chrome those rules now sit in.
 * ══════════════════════════════════════════════════════════════════════════ */
body.ek-bare {
	background: var(--ds-bg);
}

body.ek-bare .bn-app {
	background: var(--ds-bg);
}

/*
 * Dana's phone gutters.
 *
 * Her board (boards/PeoplePhone.dc.html:24) is a 390px frame padded
 * `22px 18px 110px`. BuddyNext's mobile rule is `12px` inline with 88px of
 * bottom clearance for the fixed bar (bn-shell.css:676-695) — 6px tighter at
 * the sides than she drew, and her 110px bottom is the same 88px plus the room
 * she leaves under the last card. Matched here rather than argued with: the
 * vendor value is a sensible default for an unknown theme, and hers is a
 * measurement of this screen.
 *
 * `padding-top` matters more than it looks. BuddyNext's mobile block sets only
 * `padding-inline` and `padding-bottom`, leaving `padding-block: var(--bn-s5)`
 * (20px) from the desktop rule — which was right under a masthead and is two
 * pixels short of hers with nothing above it.
 */
@media (max-width: 768px) {
	body.ek-bare .bn-app__main {
		padding: 22px 18px 110px;
	}
}

/*
 * Desktop: a column, not a stretch.
 *
 * Dana drew a phone. With Reign's shell gone and the rail collapsed, the main
 * column would otherwise run the full width of a monitor and her 20px cards
 * would become 1600px ribbons. 640px is her frame (390px) plus room for the
 * wider type a desktop invites — a value to revisit when there is a desktop
 * board, not a guess at one.
 *
 * `.bn-app__main > *` sets `max-width: none` (bn-shell.css:228-232), so this
 * has to out-specify it; `body.ek-bare .bn-app__main > *` does, at 0,3,1.
 */
@media (min-width: 768.02px) {
	body.ek-bare .bn-app__main {
		padding-block: 36px 64px;
	}
	body.ek-bare .bn-app__main > * {
		max-width: 640px;
		margin-inline: auto;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * The groups directory: one heading, and Dana’s palette.
 *
 * Two things, both caused by the directory joining the bare screens on
 * 27 September 2026.
 *
 * **One heading.** The row carries the screen’s name, the way it does on
 * People and Upcoming — and BuddyNext’s own section head says "Groups"
 * again 40px below it. Hiding the vendor’s, not ours, because ours is the
 * one that also carries the avatar, search and notifications; dropping it
 * would take those with it. Scoped to this stack (`.bn-sd-stack`), so the
 * section head keeps working everywhere else it is used.
 *
 * **The palette.** The search button and the filter apply button are the
 * last teal left on a screen a member reaches straight from Home’s "See
 * all". Same repoint as `.ek-upcoming`, and scoped the same way: the
 * `--ek-dir-*` family still dresses the Events directory and Listora, and
 * those are not in this change.
 * ══════════════════════════════════════════════════════════════════════════ */
body.ek-bare .bn-sd-stack > .bn-section-head .bn-section-head__title {
	display: none;
}

body.ek-bare .bn-sd-stack {
	--ek-dir-teal:        var(--ds-accent);
	--ek-dir-teal-hover:  var(--ds-accent-text);
	--ek-dir-teal-ink:    var(--ds-accent-text);
	--ek-dir-teal-wash:   var(--ds-accent-soft);
	--ek-teal-fill:       var(--ds-accent);
	--ek-teal-text:       var(--ds-accent-text);
}

/* ══════════════════════════════════════════════════════════════════════════
 * The group hero's four buttons, on one line (27 September 2026).
 *
 * Taking Reign's masthead off the group page also changed the page's width:
 * `body.ek-bare .bn-app__main` uses Dana’s 18px side gutter, six pixels
 * tighter per side than BuddyNext's 12px, and the hero's action cluster
 * needed 318px in 313. So the invite button wrapped onto a line of its own
 * and sat there looking like a mistake.
 *
 * Measured rather than eyeballed: 113 + 50 + 97 + 40, with three 6px gaps.
 * Trimming the two text buttons' inline padding from 12/16 to 8 gives back
 * sixteen pixels — enough that a longer label, or a translation, still fits,
 * instead of landing one pixel inside the limit.
 *
 * Scoped to the bare group page: this is OUR gutter's consequence, not a
 * quarrel with the vendor's button.
 * ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
	body.ek-bare .bn-sh-hero__actions .bn-btn {
		padding-inline: 8px;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * Picking the second adult from your contacts — Trust Model §4.2.
 *
 * Kevin, 27 Sep 2026: "both, contacts first." The row is the control, so its
 * accessible name is the person's own name and there is no verb to approve.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-pending__co-list {
	list-style: none;
	margin: 0 0 14px;
	padding: 0;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius-lg);
	overflow: hidden;
}
.ek-pending__co-row { margin: 0; border-top: 1px solid var(--ds-line); }
.ek-pending__co-row:first-child { border-top: 0; }
.ek-pending__co-row form { margin: 0; }
.ek-pending__co-pick {
	display: flex; align-items: center; gap: 12px;
	width: 100%; padding: 13px 15px;
	background: transparent; border: 0; cursor: pointer;
	font: inherit; color: var(--ds-ink); text-align: left;
}
.ek-pending__co-pick:hover { background: var(--ds-surface2); }
.ek-pending__co-pick:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: -2px; }
.ek-pending__co-avatar {
	flex: 0 0 auto;
	width: 40px; height: 40px;
	border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	background: var(--ds-accent);
	color: var(--ds-on-accent);
	font-family: var(--ek-font);
	font-size: 15px; font-weight: 700;
	line-height: 1;
}
.ek-pending__co-name {
	font-family: var(--ek-font);
	font-weight: 700; font-size: 15.5px;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ══════════════════════════════════════════════════════════════════════════
 * THE PALETTE LIVES HERE NOW — Kevin, 26 September 2026.
 *
 * > *"Look it just makes sense to me to put it in our stylesheet....we are
 * > working our way out of Reign all together."*
 *
 * It was 32 Reign theme mods, set on the sandbox during the palette flip. That
 * made the app's colours a **configuration** — not in git, not surviving a
 * rebuild, and owned by a theme we have decided to replace. This block is the
 * move: the values are Dana's `--ds-*` above, and everything else is an alias.
 *
 * ## Why aliases rather than restyling every vendor
 *
 * Measured on the sandbox, 27 Sep 2026 — four plugins read `--reign-*` straight
 * out of the cascade, and between them they read **eighteen names**:
 *
 * | Plugin | Reads |
 * |---|---|
 * | WP Career Board | 15, through `integrations/reign/assets/reign-compat.css` |
 * | BuddyNext | 10 |
 * | Learnomy | 6 |
 * | WB Listora | 3 |
 *
 * WP Career Board's own bridge says it best: it reads Reign's live variables
 * *"with no PHP colour snapshot to go stale"*, and every mapping carries a hex
 * fallback *"used only when Reign isn't the active theme."* So the bridge isn't
 * a dependency on Reign — **it is a dependency on those eighteen names**, and
 * whoever declares them owns the palette. From today that is us.
 *
 * That is also the answer to the question I had wrong earlier: the token bridge
 * was not the expensive part of leaving Reign. It is eighteen lines.
 *
 * ## Why `:root:root`
 *
 * Reign emits its compiled palette as inline CSS in `wp_head`, on `:root`.
 * Ours is a stylesheet, and which of the two wins would otherwise depend on
 * document order — which changes when a plugin enqueues something, which is
 * exactly the kind of fragility that hides for a week. `:root:root` is the same
 * element at one higher specificity, so ours wins wherever it lands. It is a
 * deliberate escalation, and it is the only one in this file.
 *
 * When Reign goes, these names stay: the vendors still read them, and
 * `eKlektiv.Launch` will declare them from the same `--ds-*` source.
 * ══════════════════════════════════════════════════════════════════════════ */
:root:root {
	/* Ground, surfaces and lines. */
	--reign-site-body-bg-color:        var(--ds-bg);
	--reign-site-sections-bg-color:    var(--ds-surface);
	--reign-site-secondary-bg-color:   var(--ds-surface2);
	--reign-site-border-color:         var(--ds-line);
	--reign-site-hr-color:             var(--ds-line);
	--reign-border:                    var(--ds-line);   /* Listora's own name. */

	/* Type. */
	--reign-site-body-text-color:      var(--ds-ink);
	--reign-site-headings-color:       var(--ds-ink);
	--reign-site-alternate-text-color: var(--ds-ink2);

	/* Links, accent and buttons. A link is text, so it takes the text accent. */
	--reign-site-link-color:           var(--ds-accent-text);
	--reign-site-link-hover-color:     var(--ds-accent);
	--reign-accent-color:              var(--ds-accent);
	--reign-accent-hover-color:        var(--ds-accent-text);
	--reign-accent:                    var(--ds-accent);  /* Listora's own name. */
	--reign-colors-theme:              var(--ds-accent);  /* WP Career Board reads this one. */
	--reign-colors-theme-hover:        var(--ds-accent-text); /* ...and its hover. */

	/*
	 * **Found missing by audit, 27 September 2026**, when the vendors were
	 * grepped for every `--reign-*` they actually read and the list compared
	 * with this block. Six names were being read and not declared. While Reign
	 * is installed they resolve from Reign and nothing shows; the day it goes
	 * they would each fall to their own `var()` fallback, which is the vendor's
	 * default rather than Dana's — a status message in somebody else's green,
	 * a button with somebody else's corner.
	 *
	 * Status colours: ours already exist as `--ek-*` and are the ones the
	 * Build Brief measured, so they are aliased rather than re-picked.
	 */
	--reign-color-success:             var(--ek-success);
	--reign-color-error:               var(--ek-error);
	--reign-color-info:                var(--ds-accent);

	/*
	 * Geometry. Dana's radius is 16px for a card and her buttons are softer
	 * than her cards, which is what `--bn-r-lg` and the group page's 14px
	 * chips already say. Given as literals because Reign's own are literals
	 * and a vendor reading them expects a length, not a token that might not
	 * resolve in its own stylesheet.
	 */
	--reign-global-border-radius:      16px;
	--reign-global-button-radius:      14px;
	--reign-site-button-bg-color:      var(--ds-accent);
	--reign-site-button-bg-hover-color: var(--ds-accent-text);
	--reign-site-button-text-color:      var(--ds-on-accent);
	--reign-site-button-text-hover-color: var(--ds-on-accent);

	/*
	 * Form fields. Not part of the flip, and they should have been: Kevin's
	 * note on Night mode is precisely about this — *"we need to pay attention
	 * to consistency in the background of buttons and fields and we need to
	 * pick an outline color and text color that works well consistently."*
	 * One surface, one line, one ink, in every mode.
	 */
	--reign-form-background-color:       var(--ds-surface);
	--reign-form-border-color:           var(--ds-line);
	--reign-form-text-color:             var(--ds-ink);
	--reign-form-placeholder-color:      var(--ds-ink2);
	--reign-form-focus-background-color: var(--ds-surface);
	--reign-form-focus-border-color:     var(--ds-accent);
	--reign-form-focus-text-color:       var(--ds-ink);
}

/* ══════════════════════════════════════════════════════════════════════════
 * Corners — Dana's scale, through BuddyNext's own knob (27 September 2026).
 *
 * After the palette bridge above, the profile screen already resolved to her
 * colours in both modes; measured on the sandbox, `--bn-surface` was #FFFFFF
 * and #22273F, `--bn-line` #E2E5EF and #353B5C, `--bn-accent` #3F5BD9 — hers,
 * exactly, because BuddyNext reads ten of the `--reign-*` names. So the LAST
 * visible difference from `MemYou` was not colour. It was the corner: every
 * vendor card came out at 10px against her 20.
 *
 * BuddyNext derives its whole radius scale from one declaration in
 * `bn-base.css` — `--bn-radius-base: 10px`, with `sm` at ×0.5, `lg` at ×1.4 and
 * `xl` at ×2. Moving that one number is the vendor's own designed-in seam and
 * exactly the posture D18 asks for: skin with tokens, rebuild nothing.
 *
 * 14px gives 7 / 14 / 19.6 / 28. Her buttons are 14 and her cards 20, so the
 * two shapes a member actually looks at land on her numbers without touching a
 * single vendor rule.
 *
 * **This moves every BuddyNext surface, not just the profile** — cards, chips,
 * buttons, fields, the feed — which is the point: one scale, or the app reads
 * as two products. Reverting is deleting this declaration.
 * ══════════════════════════════════════════════════════════════════════════ */
:root:root {
	--bn-radius-base: 14px;
}

/*
 * The one exception, because the vendor's own default lands on the wrong step.
 * A plain `.bn-card` takes `--bn-r-md` (14px); her cards are 20. The
 * `[data-v2]` variant already takes `lg`, so this brings the plain one into
 * line rather than introducing a shape.
 */
.bn-card {
	border-radius: var(--bn-r-lg);
}

/* ══════════════════════════════════════════════════════════════════════════
 * The profile completeness meter, off.
 *
 * BuddyNext prints a "0% complete" ring under the profile buttons. Dana's
 * `MemYou` board has no such thing, and it is not an omission — the board's
 * own footnote is the argument against it: *"No age, church, job or family
 * fields. Add nothing you don't want to."* A meter that reads 0% tells a
 * member the opposite, on a screen whose whole promise is that filling it in
 * is optional. It is also the first thing a new member sees about themselves,
 * and it says they are incomplete.
 *
 * Hidden rather than unhooked: it is a vendor template element with no filter
 * (searched, 27 Sep), and CSS is what D18 leaves us. Nothing else on the hero
 * moves.
 * ══════════════════════════════════════════════════════════════════════════ */
.bn-pf-completeness {
	display: none;
}

/*
 * Dark, on the same trio this site has always used and at the same escalated
 * specificity, because Reign emits its own dark block on `[data-bx-mode]`.
 *
 * Nothing is restated: every name above resolves through `--ds-*`, and those
 * already flip. This block exists only so the escalation applies in dark too.
 */
/*
 * `!important`, and it is the only tool that works here.
 *
 * Reign emits its DARK palette with `!important` on every declaration — read
 * off the rendered page, 27 Sep 2026: `--reign-site-body-bg-color:#23262f
 * !important`. An important declaration beats any amount of specificity, so the
 * `:root:root` escalation that wins in light loses in dark, and the app would
 * have gone Reign's slate grey the moment anybody switched mode. Caught by
 * reading what the page actually emits rather than by looking at it in light.
 *
 * So: important against important, and then specificity decides — which is
 * where `:root:root` earns its place a second time.
 */
:root:root[data-bn-theme="dark"],
:root:root[data-theme="dark"],
:root:root[data-bx-mode="dark"] {
	--reign-site-body-bg-color:        var(--ds-bg) !important;
	--reign-site-sections-bg-color:    var(--ds-surface) !important;
	--reign-site-secondary-bg-color:   var(--ds-surface2) !important;
	--reign-site-border-color:         var(--ds-line) !important;
	--reign-site-hr-color:             var(--ds-line) !important;
	--reign-border:                    var(--ds-line) !important;
	--reign-site-body-text-color:      var(--ds-ink) !important;
	--reign-site-headings-color:       var(--ds-ink) !important;
	--reign-site-alternate-text-color: var(--ds-ink2) !important;
	--reign-site-link-color:           var(--ds-accent-text) !important;
	--reign-site-link-hover-color:     var(--ds-accent) !important;
	--reign-accent-color:              var(--ds-accent) !important;
	--reign-accent-hover-color:        var(--ds-accent-text) !important;
	--reign-accent:                    var(--ds-accent) !important;
	--reign-colors-theme:              var(--ds-accent) !important;
	--reign-site-button-bg-color:      var(--ds-accent) !important;
	--reign-site-button-bg-hover-color: var(--ds-accent-text) !important;
	--reign-site-button-text-color:      var(--ds-on-accent) !important;
	--reign-site-button-text-hover-color: var(--ds-on-accent) !important;
	--reign-form-background-color:       var(--ds-surface) !important;
	--reign-form-border-color:           var(--ds-line) !important;
	--reign-form-text-color:             var(--ds-ink) !important;
	--reign-form-placeholder-color:      var(--ds-ink2) !important;
	--reign-form-focus-background-color: var(--ds-surface) !important;
	--reign-form-focus-border-color:     var(--ds-accent) !important;
	--reign-form-focus-text-color:       var(--ds-ink) !important;
}

/* The ask — Trust Model §4.3, beside the second adult on the holding screen. */
.ek-pending__vouch { margin-bottom: 14px; }
.ek-pending__vouch-said {
	margin: 0 0 14px;
	padding: 12px 14px;
	border-radius: var(--ds-radius);
	background: var(--ds-accent-soft);
	color: var(--ds-accent-text);
	font-size: 14.5px;
	line-height: 1.5;
}

/* ══════════════════════════════════════════════════════════════════════════
 * The top row — Dana's MobileHomeAlt, 27 September 2026.
 *
 * Her board has no site header. Avatar, greeting, search and notifications are
 * the page's own first row, which is what lets Home render with Reign's
 * masthead gone. Her measurements: 44px controls, 22px radii, 12px between.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-top {
	display: flex;
	align-items: center;
	gap: 12px;
}

.ek-top__mid {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
}
/*
 * The title face of the row (Upcoming, and any screen named rather than
 * greeted). Dana's `MemYou` sets it at 15px/700 beside a 40px back arrow;
 * here it is the page's <h1>, so it takes her screen-heading size instead and
 * the row grows to fit it.
 */
/*
 * A row with a back arrow carries FOUR controls (back, search, bell, avatar),
 * so the title gets what is left — 15.5px, which is also exactly what Dana
 * sets on `MemYou`. A destination row carries three, and its title is the
 * screen's heading at her heading size. Same element, two jobs, and the
 * truncation Kevin would otherwise have seen ("Your pr...") is the reason it
 * is two.
 */
.ek-top--back .ek-top__title {
	font-size: 16px;
	letter-spacing: 0;
}

.ek-top__title {
	margin: 0;
	font-family: var(--ek-font);
	font-weight: 700;
	font-size: 26px;
	line-height: 1.15;
	letter-spacing: -0.02em;
	color: var(--ds-ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* The row spaces itself everywhere EXCEPT inside `.ek-home`, where it is a
   flex child and the column's own `gap` already does it. Stated this way round
   because every new bare screen gets the right spacing for free, and only the
   one exception has to know it is an exception. */
.ek-top {
	margin-bottom: 18px;
}
.ek-home .ek-top {
	margin-bottom: 0;
}

.ek-top__hello {
	font-size: 13px;
	line-height: 1.2;
	color: var(--ds-ink2);
}
.ek-top__name {
	font-family: var(--ek-font);
	font-weight: 700;
	font-size: 21px;
	line-height: 1.15;
	letter-spacing: -0.02em;
	color: var(--ds-ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Search and notifications: outlined on the surface, hers. */
.ek-top__icon {
	position: relative;
	flex: 0 0 auto;
	width: 44px; height: 44px;
	border-radius: 22px;
	border: 1px solid var(--ds-line);
	background: var(--ds-surface);
	color: var(--ds-ink);
	display: flex; align-items: center; justify-content: center;
	text-decoration: none;
}
.ek-top__icon:hover { border-color: var(--ds-accent); }
.ek-top__icon:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }

/* Her unread dot, ringed in the surface so it reads on either mode. */
.ek-top__dot {
	position: absolute;
	top: 9px; right: 10px;
	width: 9px; height: 9px;
	border-radius: 5px;
	background: var(--ds-alarm);
	border: 2px solid var(--ds-surface);
}

/* ── The avatar, and what it opens ───────────────────────────────────── */
/*
 * A `<details>`, so it needs no script — this row is the only way out of a
 * screen with no site header, and it must not depend on a bundle loading.
 */
.ek-top__me { position: relative; flex: 0 0 auto; }
/*
 * The member's real picture, not their initial (27 September 2026). The
 * typography here used to draw the letter; it is kept off deliberately rather
 * than left behind, because a stray text node inside the summary would show
 * through a transparent PNG.
 */
.ek-top__me-btn {
	list-style: none;
	width: 44px; height: 44px;
	border-radius: 22px;
	overflow: hidden;
	display: flex;
	cursor: pointer;
}
.ek-top__me-img {
	width: 100%; height: 100%;
	object-fit: cover;
	display: block;
}
.ek-top__me-btn::-webkit-details-marker { display: none; }
.ek-top__me-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 3px; }

/*
 * **The menu opens away from the edge the avatar is nearest** — 27 September
 * 2026, after Kevin: *"the avatar menu is not showing properly."*
 *
 * `.ek-top` puts the avatar in one of two places, and the menu has to know
 * which:
 *
 *   FIRST in the row   on Home and the other destination screens, where the
 *                      row is avatar, greeting, search, bell. The menu opens
 *                      rightwards, into the page.
 *   LAST in the row    on the group page, the profile and every sub-screen,
 *                      where the row leads with a back arrow. The menu opens
 *                      leftwards, into the page.
 *
 * It was `left: 0` unconditionally, which was written when only the first case
 * existed. On a back-arrow screen that sent a 200px menu off the right of a
 * 375px phone — "Settings", "Light or dark" and "Sign out" all sliced in half
 * at the screen edge. Flipping it to `right: 0` unconditionally simply moved
 * the same bug to Home, where it measured 138px off the LEFT.
 *
 * So: right-anchored by default, left-anchored when the avatar leads. Checked
 * both ways on the sandbox rather than reasoned about, because that is how the
 * second version got shipped.
 */
.ek-top__me-menu {
	position: absolute;
	right: 0; left: auto; top: 52px;
	z-index: 30;
	box-sizing: border-box;
	width: 320px;
	max-width: calc(100vw - 36px);
	padding: 10px;
	background: var(--ds-bg);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius-lg);
	box-shadow: var(--ds-shadow-pop);
	display: flex;
	flex-direction: column;
	gap: 10px;
}
/* Avatar first (Home and the other destinations): open into the page. */
.ek-top__me:first-child .ek-top__me-menu {
	left: 0;
	right: auto;
}

/*
 * The rows, as drawn (Key Flows v71, Family board 1 screen 1; Kevin 30 Sep
 * 2026, d-you-menu a): the member's picture and name over "Your profile", then
 * one card of rows with hairlines between, then Sign out in a card of its own.
 * 48px rows, 15px/600 labels, 13px sub-lines in ink2, a chevron at the end.
 */
.ek-top__me-head {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 4px 6px;
	border-radius: var(--ds-radius);
	color: var(--ds-ink);
	text-decoration: none;
}
.ek-top__me-head:hover { background: var(--ds-surface2); }
.ek-top__me-head:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
.ek-top__me-face {
	flex: 0 0 auto;
	width: 44px; height: 44px;
	border-radius: 50%;
	object-fit: cover;
	display: block;
}
.ek-top__me-who { display: flex; flex-direction: column; min-width: 0; }
.ek-top__me-name {
	font-family: var(--ek-font);
	font-weight: 700;
	font-size: 19px;
	line-height: 1.2;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ek-top__me-sub { font-size: 13px; color: var(--ds-ink2); }

.ek-top__me-card {
	display: flex;
	flex-direction: column;
	padding: 0 14px;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius-lg);
}

.ek-top__me-item {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	min-height: 48px;
	padding: 8px 0;
	border: 0;
	border-top: 1px solid var(--ds-line);
	background: transparent;
	font: inherit;
	color: var(--ds-ink);
	text-align: left;
	text-decoration: none;
	cursor: pointer;
}
.ek-top__me-item:first-child { border-top: 0; }
.ek-top__me-item:hover .ek-top__me-label { text-decoration: underline; }
.ek-top__me-item:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; border-radius: 6px; }
.ek-top__me-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ek-top__me-label { font-weight: 600; font-size: 15px; line-height: 1.3; }
.ek-top__me-line { font-size: 13px; line-height: 1.3; color: var(--ds-ink2); }
.ek-top__me-chev { flex: 0 0 auto; color: var(--ds-ink2); }

/* Sign out: the drawn accent-text word, alone in its card. */
.ek-top__me-out {
	font-weight: 600;
	font-size: 15px;
	color: var(--ds-accent-text);
}

/* ══════════════════════════════════════════════════════════════════════════
 * Desktop home — Dana's `Main.dc.html`, above 768px.
 *
 * Kevin, 27 September 2026: *"Ok do those."*
 *
 * Every number is off her board. The one structural thing to understand is
 * that her header spans the CONTENT COLUMN and not the viewport — the rail is
 * beside it, not under it — which is why these rules live on `.ek-deskbar`
 * inside `.bn-app__main` rather than on anything fixed.
 *
 *     bar        68px tall, padded 0 28px, on the RAIL's ground with a 1px
 *                line under it
 *     search     460px x 42px, 12px corner, 1px line, on surface2, 14.5px
 *     icon       44px square, 12px corner, 1px line, on surface
 *     avatar     44px, fully round, 2px line
 *     greeting   Outfit 30px 700 -0.01em, the date 15px in ink2 under it
 *
 * The phone row (`.ek-top`) and this are mutually exclusive: exactly one is
 * shown at any width, and the pair is emitted by `Chrome\Home`.
 * ══════════════════════════════════════════════════════════════════════════ */

/* Below her breakpoint the phone row is the row; neither of these exists. */
.ek-deskbar,
.ek-deskhead {
	display: none;
}

@media (min-width: 768.02px) {
	/*
	 * **Wherever the bar is drawn, the phone row gives way** — 27 September
	 * 2026, when Kevin asked for the bar on People, Upcoming and Groups too:
	 * *"those screens are very mobile centric."*
	 *
	 * This was two bespoke rules, `.ek-home .ek-top` and `.ek-app .ek-top`,
	 * one per place that happened to draw a bar. A third, fourth and fifth
	 * screen would have meant three more, and the fifth would have been
	 * forgotten.
	 *
	 * The general sibling combinator says the actual rule instead: a phone row
	 * that follows a desktop bar is the redundant one. It needs no wrapper and
	 * no list of screens, and it fails safe — a screen with no bar keeps its
	 * row at every width, which is what a screen with no bar needs.
	 */
	.bn-app__shell:has( > .ek-deskbar ) .ek-top,
	.ek-app__shell:has( > .ek-deskbar ) .ek-top {
		display: none;
	}

	/* ── The bar is a row of the SHELL, not a block in a column ──────────────
	 *
	 * Kevin, 27 September 2026: *"on desktop it should go all the way across
	 * and the right widget area should start under it."* Dana's board is the
	 * same shape — her `<header>` is a sibling of `<main>` and spans the
	 * content column AND the aside, with the rail beside the pair.
	 *
	 * The bar is emitted by `buddynext/shell/rail.php`, which both shells
	 * render as a direct child, so it is already a grid item of each. All that
	 * is left is to say where: a first row, starting right of the rail and
	 * running to the end, with the columns below it. The rail spans both rows.
	 *
	 * No number appears in any of this. The old arrangement needed the bar to
	 * escape the main column's padding with `margin: -36px -24px 0`, and
	 * widening it over the sidebar would have meant a third literal — the
	 * sidebar's own width — plus a matching push on the sidebar to get it back
	 * under the bar. `grid-column: 2 / -1` says the same thing and keeps
	 * saying it if any of those widths ever change.
	 *
	 * `.bn-app__region` is `display: contents`, so `.bn-app__main` and
	 * `.bn-app__right` are themselves grid items of `.bn-app__shell` and take
	 * their row directly.
	 * ───────────────────────────────────────────────────────────────────── */

	.bn-app__shell,
	.ek-app__shell {
		grid-template-rows: auto minmax(0, 1fr);
	}

	.bn-app__shell > .bn-app__rail,
	.ek-app__shell > .bn-app__rail {
		grid-row: 1 / -1;
	}

	.bn-app__shell > .ek-deskbar,
	.ek-app__shell > .ek-deskbar {
		grid-column: 2 / -1;
		grid-row: 1;
	}

	/*
	 * The app screens have no sidebar, so one row assignment is the whole
	 * story here. The hub shells' two columns differ either side of 1024px and
	 * are set in their own blocks at the end of this file — see the note
	 * there.
	 */
	.ek-app__shell > .ek-app__main {
		grid-row: 2;
	}

	/*
	 * **The column gets her width.**
	 *
	 * This sheet used to cap every child of the main column at 640px, with a
	 * note saying so: *"640px is her frame (390px) plus room for the wider type
	 * a desktop invites — a value to revisit when there is a desktop board, not
	 * a guess at one."* There is a desktop board now, and it measures 1128px of
	 * content beside a 248px rail at 1440.
	 *
	 * Raised for `.ek-home` ONLY, and that is deliberate. The vendor's activity
	 * feed is a sibling below it and keeps the 640px measure — which is also
	 * hers: her board sets the feed in a 640px column with a 320px aside beside
	 * it. The aside is not built, so the feed simply keeps its width rather
	 * than stretching to fill the space the aside would have taken.
	 */
	body.ek-bare .bn-app__main > .ek-home {
		max-width: 1128px;
	}

	/*
	 * The bar's own look. It no longer breaks out of anything: as a grid item
	 * in the shell's first row (see above) its left edge is already flush
	 * against the rail and its right edge already runs past the sidebar, so
	 * the three negative margins that used to buy that are gone and only her
	 * 28px of inner padding is left.
	 */
	.ek-deskbar {
		display: flex;
		align-items: center;
		gap: 12px;
		height: 68px;
		padding: 0 28px;
		background: var(--ds-rail);
		border-bottom: 1px solid var(--ds-line);
	}

	/*
	 * The wordmark, and the way home.
	 *
	 * Kevin's placement rather than Dana's: her rail carries the wordmark and
	 * her bar opens with the search. The rail's mark became the collapse
	 * control, and one 40px square cannot sensibly be the brand, the toggle
	 * AND the link home — so the word moved here and took the link with it.
	 *
	 * `flex: 0 0 auto` so it never gives way; the search beside it is what
	 * yields on a narrow column.
	 */
	.ek-deskbar__brand {
		flex: 0 0 auto;
		display: flex;
		align-items: center;
		text-decoration: none;
	}

	.ek-deskbar__wordmark {
		font-family: var(--ek-font);
		font-weight: 800;
		font-size: 24px;
		line-height: 1;
		letter-spacing: -0.02em;
		color: var(--ds-brand-ink);
		white-space: nowrap;
	}

	.ek-deskbar__brand:hover .ek-deskbar__wordmark,
	.ek-deskbar__brand:focus-visible .ek-deskbar__wordmark {
		color: var(--ds-accent-text);
	}

	/*
	 * Her 460px search. `max-width` rather than a flat width so it gives way
	 * on a narrow laptop instead of pushing the avatar off the end — she drew
	 * it at 1440, and with the wordmark now in front of it there is less room
	 * than she had.
	 */
	.ek-deskbar__search {
		display: flex;
		align-items: center;
		gap: 10px;
		width: 460px;
		max-width: 100%;
		min-width: 0;
		height: 42px;
		padding: 0 14px;
		border: 1px solid var(--ds-line);
		border-radius: 12px;
		background: var(--ds-surface2);
		color: var(--ds-ink2);
		font-size: 14.5px;
		text-decoration: none;
	}

	.ek-deskbar__search:hover,
	.ek-deskbar__search:focus-visible {
		border-color: var(--ds-accent);
		color: var(--ds-ink);
	}

	.ek-deskbar__search-text {
		flex: 1 1 auto;
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	/* Everything after the search sits at the far end, as she has it. */
	.ek-deskbar__end {
		display: flex;
		align-items: center;
		gap: 12px;
		margin-inline-start: auto;
	}

	.ek-deskbar__icon {
		position: relative;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 44px;
		height: 44px;
		flex: 0 0 auto;
		border: 1px solid var(--ds-line);
		border-radius: 12px;
		background: var(--ds-surface);
		color: var(--ds-ink);
		text-decoration: none;
	}

	/*
	 * Both glyphs at 20px, stated here rather than left to the markup.
	 *
	 * The bell is drawn inline with `width="20" height="20"` on the element;
	 * Apps comes from `buddynext_icon()`, which emits no dimensions at all, so
	 * it sized itself from the bar's font and measured 15px beside a 20px bell
	 * (27 September 2026, on the deploy that moved Apps into this row). Two
	 * controls the same size, side by side, should carry the same mark size,
	 * and a rule here covers whatever the next one is drawn with.
	 */
	.ek-deskbar__icon svg {
		width: 20px;
		height: 20px;
		flex: 0 0 auto;
	}

	.ek-deskbar__icon:hover,
	.ek-deskbar__icon:focus-visible {
		border-color: var(--ds-accent);
		color: var(--ds-accent-text);
	}

	/* Where you are, in the row of controls. */
	.ek-deskbar__icon[aria-current="page"] {
		border-color: var(--ds-accent);
		background: var(--ds-accent-soft);
		color: var(--ds-accent-text);
	}

	/*
	 * The unread dot, ringed in the button's own ground so it reads as sitting
	 * ON the bell rather than beside it. #E5484D is hers and is a literal for
	 * the same reason the meetings date chip is: it must mean "waiting" in
	 * both modes, and neither `--ds-*` carries an alarm colour.
	 */
	.ek-deskbar__dot {
		position: absolute;
		top: 8px;
		inset-inline-end: 9px;
		width: 9px;
		height: 9px;
		border-radius: 999px;
		background: var(--ds-alarm);
		box-shadow: 0 0 0 2px var(--ds-surface);
	}

	/*
	 * The avatar keeps `TopRow`'s own menu markup, so this only resizes it to
	 * her 44px and gives it the ring her board draws. The menu inside is
	 * unchanged — it is the same element and the same rows (Light, Dark or Night is in Settings since 30 Sep).
	 */
	.ek-deskbar .ek-top__me {
		flex: 0 0 auto;
	}

	.ek-deskbar .ek-top__me-btn,
	.ek-deskbar .ek-top__me-img {
		width: 44px;
		height: 44px;
		border-radius: 999px;
	}

	.ek-deskbar .ek-top__me-btn {
		box-shadow: 0 0 0 2px var(--ds-line);
	}

	/* ── The greeting, below the bar ──────────────────────────────────────── */

	/*
	 * `margin-top: 0`, where this was 28px. The bar used to pull the main
	 * column's 36px of top padding away with it; now that the bar is a shell
	 * row, that padding stays and is the space above the greeting. 28px on top
	 * of it would be 64px, against Dana's 28.
	 */
	.ek-deskhead {
		display: block;
		margin: 0 0 26px;
	}

	/*
	 * Her greeting is ONE line on the desktop — "Good evening, Hannah" — where
	 * the phone stacks it over two. `TopRow::greeting()` emits the two spans
	 * either way, so the comma and the space are restored here rather than in
	 * a second copy of the PHP.
	 */
	.ek-deskhead__hello {
		font-family: var(--ek-font);
		font-size: 30px;
		font-weight: 700;
		line-height: 1.15;
		letter-spacing: -0.01em;
		color: var(--ds-ink);
	}

	.ek-deskhead__hello .ek-top__hello,
	.ek-deskhead__hello .ek-top__name {
		display: inline;
		font: inherit;
		color: inherit;
		letter-spacing: inherit;
	}

	.ek-deskhead__hello .ek-top__name::before {
		content: " ";
	}

	.ek-deskhead__date {
		margin-top: 4px;
		font-size: 15px;
		color: var(--ds-ink2);
	}

	/*
	 * A screen's own name, where Home has its greeting — People, Upcoming,
	 * Groups. Same 30px, and no date under it: a date belongs to the day you
	 * opened the app, not to a list of people.
	 */
	.ek-deskhead--title {
		margin-bottom: 20px;
	}

	/* ── Your groups, as her three-up grid ────────────────────────────────── */

	/*
	 * Her desktop draws the member's groups as cards in a 3-column grid, each
	 * with a 58px band in the group's own colour across the top. The phone
	 * draws the same groups as a horizontal rail of tiles, which is what
	 * `.ek-home__rail` is — so the rail becomes a grid here rather than a
	 * second block being rendered.
	 */
	.ek-home .ek-home__rail {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 14px;
		overflow: visible;
		scroll-snap-type: none;
	}

	.ek-home .ek-home__rail-end {
		display: none;
	}

	/*
	 * **The cards fill their column.**
	 *
	 * Kevin: *"notice on desktop the coming up cards overlap."* They did, by
	 * 26px, and the arithmetic says why: the rule above turns `.ek-home__rail`
	 * into three equal columns, which at this width are 260px each — and an
	 * event card is `width: 300px; flex: 0 0 auto`, because on a phone the
	 * rail is a horizontal SCROLLER and a card in a scroller has to state its
	 * own width. In a grid that width is not a request, it is an overflow, and
	 * the next card starts before this one ends.
	 *
	 * Both sections share `.ek-home__rail` — Coming up and Your groups — so
	 * the grid caught both. That is right for the groups and accidental for
	 * the events, and the accident is what showed.
	 *
	 * `width: auto` hands the sizing back to the grid. The phone keeps its
	 * 300px because this whole block is inside the desktop query.
	 *
	 * **Her desktop does not do this at all**, and that is still the open
	 * item: `Main.dc.html` puts ONE warm Next-up card across the column with
	 * an RSVP in it, not a row of three. That card needs the RSVP control
	 * Eventonomy does not expose in a list, so it waits on the same decision
	 * as the meetings screen. This makes the interim arrangement correct
	 * rather than making it hers.
	 */
	.ek-home .ek-home__rail > .ek-home__ev {
		width: auto;
		min-width: 0;
	}

	/*
	 * Her card. On the phone a group is a big coloured tile with its name
	 * underneath; on the desktop it is a card — a 58px band in the group's own
	 * colour across the top, then a white body.
	 *
	 * Same markup either way. `.ek-home__tile-face` is the band and
	 * `.ek-home__tile-name` is the body, so nothing is re-rendered; only the
	 * shape changes at the breakpoint.
	 */
	.ek-home .ek-home__tile {
		display: flex;
		flex-direction: column;
		width: auto;
		border: 1px solid var(--ds-line);
		border-radius: 16px;
		background: var(--ds-surface);
		overflow: hidden;
	}

	.ek-home .ek-home__tile-face {
		flex: 0 0 auto;
		width: 100%;
		height: 58px;
		border-radius: 0;
		position: relative;
	}

	/*
	 * Her band carries the group's MEETING TIME — "TUESDAYS · 7:30 PM" — set
	 * in white across the bottom of it. We do not have that here:
	 * `SpaceMemberService::membership_rows()` returns id, name, slug, category
	 * and role, and the schedule lives in `ek_group_profile` (the table
	 * `Chrome\GroupPage::meets_line()` reads) for groups created through our
	 * own Start-a-group form.
	 *
	 * So the band carries the group's face instead, small and centred, which
	 * is at least a thing that identifies the group. The time is a data
	 * question rather than a styling one, and a real one: a group with no
	 * profile row has no schedule to show, which is why it is not simply
	 * fetched here and left blank for half of them.
	 */
	.ek-home .ek-home__tile-img,
	.ek-home .ek-home__tile-mono {
		position: absolute;

		/*
		 * **All four sides, in one `inset`** — and that is the fix, not the
		 * style.
		 *
		 * This set `bottom` and `inset-inline-start` only. On a phone the
		 * picture FILLS the face, so its rule there is `inset: 0` — and the
		 * `top: 0` from it survived into this one. The result: every group
		 * with a real picture had its avatar pinned to the TOP of the colour
		 * band and ending 14px above it, while every group with initials
		 * overhung correctly, because the initials span carries a different
		 * phone rule. Kevin, on the first card: *"the avatar is up."*
		 *
		 * Measured before the fix — Design Critique (image) sat 0px from the
		 * band's top; BSF (initials) sat 32px. Two different treatments of the
		 * same element, and only one of them on purpose.
		 *
		 * The shorthand writes all four, so nothing from another breakpoint
		 * can be left behind. Same lesson as the meetings date chip, which
		 * needed `inset: auto auto 46px 16px` for exactly this reason.
		 */
		inset: auto auto -18px 14px;
		width: 44px;
		height: 44px;
		border-radius: 12px;
		box-shadow: 0 0 0 3px var(--ds-surface);
		object-fit: cover;
	}

	.ek-home .ek-home__tile-mono {
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 16px;
		background: inherit;
	}

	/* Her lead chip stays on the band, at its far end. */
	.ek-home .ek-home__tile-lead {
		inset-inline-start: auto;
		inset-inline-end: 10px;
		top: 10px;
		bottom: auto;
	}

	/*
	 * The body. The extra top padding is the room the face above overhangs
	 * into — 18px of it, plus her 12px — so the name never sits under a tile.
	 */
	.ek-home .ek-home__tile-name {
		padding: 30px 14px 14px;
		font-family: var(--ek-font);
		font-size: 17px;
		font-weight: 700;
		line-height: 1.25;
		color: var(--ds-ink);
		text-align: start;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * The right-hand rail's cards — BuddyNext's, skinned.
 *
 * Kevin, 27 September 2026: *"Skin the groups rail from the vendor."* Not
 * replace it: the four cards on the groups directory — Suggested for you,
 * Your groups, New groups, Popular this week — are the vendor's own, they
 * work, and their content is a question for another day.
 *
 * **Most of the skinning was already done and not by this file.** Measured
 * before touching anything: card #FFFFFF on #E2E5EF, headings #5B6178, rows
 * #1C1F33, meta #5B6178 — Dana's palette, every one. That is the `--bn-*`
 * token map in `functions.php` doing its job: point BuddyNext's tokens at
 * `--ds-*` once and its own components arrive in her colours without a
 * stylesheet knowing they exist.
 *
 * What was left is geometry, which no token carries:
 *
 *   card radius   19.6px → her 16px (`--ds-radius`)
 *   row radius     7px   → 10px, the rail's own row corner
 *   heading        given the tracking her section headings have, so the
 *                  card titles and the left rail's YOUR GROUPS read as the
 *                  same kind of label
 *
 * Scoped to `.bn-app__right` so it dresses the rail's cards and not every
 * `.bn-sidebar-card` the vendor might place elsewhere.
 * ══════════════════════════════════════════════════════════════════════════ */

.bn-app__right .bn-sidebar-card {
	border-radius: var(--ds-radius);
}

.bn-app__right .bn-sidebar-card__header {
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ds-ink2);
}

.bn-app__right .bn-sd-side-row {
	border-radius: 10px;
}

/*
 * A row that goes somewhere should say so on hover. The vendor leaves these
 * flat, which on a 320px column of names reads as a list rather than as four
 * lists of links.
 */
.bn-app__right .bn-sd-side-row:hover {
	background: var(--ds-surface2);
}

/*
 * Leaders, on People's right column (Chrome\PeopleRail, 27 September 2026).
 *
 * The rows reuse `.ek-people__who` / `__avatar` / `__name` / `__line` from the
 * main column so a person looks the same on both sides of the screen, and add
 * only what the narrower column changes: no card of their own (the vendor's
 * `.bn-sidebar-card` already is one), no dividing rules, a 34px face instead of
 * 40, and the same 10px hover the vendor rows next door take.
 */
.ek-rail-people {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.ek-rail-people__row { margin: 0; }
.ek-rail-people .ek-people__who {
	padding: 7px 8px;
	border-radius: 10px;
	gap: 10px;
}
.ek-rail-people .ek-people__who:hover { background: var(--ds-surface2); }
.ek-rail-people__avatar { width: 34px; height: 34px; }
.ek-rail-people .ek-people__name { font-size: 14.5px; }
.ek-rail-people .ek-people__line { font-size: 12.5px; }

/*
 * Apps — the placeholder screen (Chrome\Apps, 27 September 2026).
 *
 * Kevin: *"Create an empty page for that to navigate to....we will build that
 * out later."* One line, set like a caption rather than like body text, so the
 * screen reads as deliberately unfinished instead of as a page that failed to
 * load.
 */
.ek-apps__soon {
	margin: 0;
	color: var(--ds-ink2);
	font-size: 15px;
}

/* ══════════════════════════════════════════════════════════════════════════
 * The hub shell's two columns sit differently either side of 1024px, and that
 * is the vendor's arrangement, not ours.
 *
 * Found 27 September 2026 at 900px: the Leaders rail drew on the LEFT and the
 * People content on the right, swapped. My own regression, from the commit
 * that made the desktop bar a row of the shell.
 *
 * `bn-shell.css` has two arrangements. Above 1024px the shell is three tracks
 * — rail, content, sidebar — and the sidebar sits beside the content. At
 * `max-width: 1024px` it drops to TWO tracks and gives `.bn-app__right`
 * `grid-column: -2`, which in a two-track grid IS the content track: the
 * sidebar is meant to reflow under the content rather than beside it.
 *
 * Pinning both to `grid-row: 2` broke the second arrangement — they became one
 * cell, so grid bumped `.bn-app__main`, the one with no explicit column, into
 * the next free slot and invented a third column to hold it.
 *
 * So the rows are split at the vendor's own breakpoint: beside each other
 * above it, stacked below it. `grid-row: 3` needs no third track declared;
 * an implicit row is created for it.
 *
 * These live at the END of the file on purpose. The first attempt put them in
 * the middle of the `min-width: 768.02px` block, which closed that block early
 * and left every rule after it — the whole bar, its wordmark, its search —
 * gated to `max-width: 1024px`. At 1440 the bar measured zero wide.
 * ══════════════════════════════════════════════════════════════════════════ */

@media (min-width: 1024.02px) {
	.bn-app__shell > .bn-app__region > .bn-app__main,
	.bn-app__shell > .bn-app__region > .bn-app__right {
		grid-row: 2;
	}
}

@media (min-width: 768.02px) and (max-width: 1024px) {
	.bn-app__shell > .bn-app__region > .bn-app__main {
		grid-row: 2;
	}

	.bn-app__shell > .bn-app__region > .bn-app__right {
		grid-row: 3;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * People — Kevin's layout, 27 September 2026 (decisions item 10).
 *
 * Two filters in the middle over BuddyNext's own member card, flattened; a
 * column of the people in her groups she has not connected with, beside the
 * list on a computer and ABOVE it on a phone.
 *
 * The column is ours and lives inside `.bn-app__main`. It cannot be the
 * vendor's `.bn-app__right`: below 1025px `bn-shell.css` gives that element
 * `grid-column: -2` in a two-track grid, so it always reflows UNDER the
 * content — measured at 1,307px down on a 375px screen with twelve people.
 * ══════════════════════════════════════════════════════════════════════════ */

.ek-people__cols {
	display: flex;
	flex-direction: column;
	gap: 18px;
}

/*
 * Phone: the column first, by `order`. The DOM keeps the list first so a
 * screen reader hears the main content first at every width; this is the one
 * place the visual order and the reading order part company, which is why the
 * column carries its own heading.
 */
.ek-people__aside { order: -1; }

.ek-people__main {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 14px;
}

@media (min-width: 1024.02px) {
	/*
	 * The bare hubs cap every child of the main column at 640px — Dana's
	 * reading measure, and right for a single column of content. People stopped
	 * being one column on 27 September: 640 left the list at 312px beside a
	 * 300px aside, which is narrower than the phone. 1128px is the width
	 * `.ek-home` already takes for the same reason, so the two desktop screens
	 * measure the same rather than each picking a number.
	 */
	body.ek-bare .bn-app__main > .ek-people {
		max-width: 1128px;
	}

	.ek-people__cols {
		flex-direction: row;
		align-items: flex-start;
		gap: 28px;
	}
	.ek-people__main { flex: 1 1 auto; }
	.ek-people__aside {
		order: 0;
		flex: 0 0 300px;
		width: 300px;
		position: sticky;
		top: 16px;
	}
}

/* ── The two filters ──────────────────────────────────────────────────────
 * Links, not buttons: each filter is a real address, so it can be sent, kept
 * and reached with the keyboard without a line of script.
 */
.ek-people__filters {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}

.ek-people__filter {
	display: inline-flex;
	align-items: center;
	height: 34px;
	padding: 0 16px;
	border: 1px solid var(--ds-line);
	border-radius: 17px;
	background: var(--ds-surface);
	color: var(--ds-ink);
	font-family: var(--ek-font);
	font-size: 13.5px;
	font-weight: 700;
	text-decoration: none;
}

.ek-people__filter:hover { border-color: var(--ds-accent); }

.ek-people__filter[aria-selected="true"] {
	background: var(--ds-accent);
	border-color: var(--ds-accent);
	color: var(--ds-on-accent);
}

/* ── The card grid ────────────────────────────────────────────────────────
 * Three up on a computer, one up on a phone. The vendor's own grid mode is
 * 203px a card; this column is wider, so the tracks are a minimum rather than
 * a count and the cards breathe instead of stretching.
 */
.ek-people__cards {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: 1fr;
	gap: 14px;
}

@media (min-width: 560px) {
	.ek-people__cards { grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); }
}

.ek-people__card {
	margin: 0;
	display: flex;
	flex-direction: column;
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius);
	overflow: hidden;
}

/*
 * The card sits inside our own wrapper, which is the visible card. The
 * vendor's own frame is unset so the two do not draw two borders.
 */
.ek-people__card .bn-md-card,
.ek-people__card .bn-card {
	border: 0 !important;
	border-radius: 0 !important;
	background: transparent !important;
	box-shadow: none !important;
}

/*
 * **@handle off** (Kevin, 27 Sep, decision 7). The one card ruling with no
 * template argument — `member-card.php` prints it unconditionally — so it
 * comes off here. `visibility` is not used: the line must take no space.
 */
.ek-people__card .bn-md-card__handle { display: none !important; }

/*
 * `show_actions: false` leaves a "View profile" button in the vendor's action
 * slot. That is a third action nobody asked for, and the whole card is already
 * a link to the profile, so the slot goes and ours takes its place below.
 */
.ek-people__card .bn-md-card__actions,
.ek-people__card .bn-md-card__connect-decide { display: none !important; }

/*
 * **No dot, and `presence: 'offline'` is not enough.** The card takes the
 * argument, but `.bn-avatar` draws its `::after` for offline too — a grey
 * 11.8px dot, measured on the sandbox. A grey dot still says "presence" and
 * still invites the member to read something into it, and the rule is that
 * this screen has no online dot at all. So the pseudo-element goes.
 */
.ek-people__card .bn-avatar::after { display: none !important; }

/*
 * The action hugs the right — Kevin, 27 Sep: *"the message button should be
 * right justified instead of stretching across the card."* A button as wide as
 * its card reads as the card's primary surface; Message is one of two things
 * you can do with a contact, not the point of them.
 *
 * `align-items: flex-end` sizes every child to its content, so the group line
 * takes `align-self: stretch` back — it needs the full width to truncate
 * against rather than shrink-wrapping its own text.
 */
.ek-people__card-act {
	margin-top: auto;
	padding: 0 12px 12px;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 8px;
}

.ek-people__card-line {
	align-self: stretch;
	font-size: 12.5px;
	color: var(--ds-ink2);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/*
 * The Connect form is a `<details>`, so it must not become a flex container —
 * that would break its own summary/content layout. Closed, it shrinks to the
 * button and hugs the right with everything else; open, it takes the card's
 * width back, because the note field needs it.
 */
.ek-people__card-act .ek-people__connect { align-self: flex-end; }
.ek-people__card-act .ek-people__connect[open] { align-self: stretch; }

/* ── The column ───────────────────────────────────────────────────────── */

.ek-people__col {
	background: var(--ds-surface);
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius);
	padding: 14px 12px;
}

.ek-people__col-head {
	margin: 0 4px 10px;
	font-family: var(--ek-font);
	font-size: 10.5px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ds-ink2);
}

.ek-people__col-group + .ek-people__col-group { margin-top: 14px; }

.ek-people__col-name {
	margin: 0 4px 4px;
	font-family: var(--ek-font);
	font-size: 14px;
	font-weight: 700;
	color: var(--ds-ink);
}

.ek-people__col-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.ek-people__col-row {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	min-height: 46px;
	padding: 0 4px;
}

.ek-people__col-face {
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	object-fit: cover;
	display: block;
}

.ek-people__col-who {
	flex: 1 1 auto;
	min-width: 0;
	font-weight: 700;
	font-size: 13.5px;
	color: var(--ds-ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* No number on it, per the no-counts rule — and it would be a count of people she has not met. */
.ek-people__col-all {
	display: inline-block;
	margin: 6px 4px 0;
	font-size: 12.5px;
	font-weight: 600;
	color: var(--ds-accent-text);
}


/* ── The trust line, anywhere but the Start a group form ─────────────────
 * One quiet line with the small shield (Key Flows note `tone`). start.css
 * carries its own copy for the form's screens; this one serves the group
 * settings "Invite someone" panel (Invite\InviteLinksClosed, 28 Sep 2026).
 * Existing tokens only, so it follows light and dark with the rest of the page.
 */
.ek-invite-panel .ek-trust {
	display: flex;
	gap: 10px;
	align-items: flex-start;
	margin: 0 0 16px;
	font-size: 14px;
	line-height: 1.5;
	color: var(--ds-ink);
}

.ek-invite-panel .ek-trust__mark {
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	margin-top: 2px;
	color: var(--ds-accent-text);
}

.ek-invite-panel .ek-trust__mark svg {
	width: 16px;
	height: 16px;
	display: block;
}

/*
 * The line between the page and the right-hand sidebar runs to the bottom (Kevin,
 * 29 Sep 2026: "the right hand sidebar border does not extend to the bottom").
 * BuddyNext draws it as the sidebar's own left border (bn-shell.css,
 * `.bn-app__right`), but that column is sticky and only as tall as its cards, so the
 * line stopped under the last card. The main column is as tall as the page, so the
 * line moves there; the sidebar stays sticky. Above 1024px only: below it the vendor
 * stacks the sidebar under the page with a top border instead.
 */
@media (min-width: 1025px) {
	.bn-app__shell:has( .bn-app__right ) .bn-app__main {
		border-inline-end: 1px solid var(--bn-line);
	}
	.bn-app__shell:has( .bn-app__right ) .bn-app__right {
		border-inline-start: 0;
	}
}

/* ══════════════════════════════════════════════════════════════════════════
 * Light, Dark or Night — the member's choice, on Settings → Appearance.
 *
 * Kevin, 30 Sep 2026 (d-palette a, d-you-menu a): the choice lives in
 * Settings, not in the You menu. The control is the companion's
 * (`Chrome\Scheme::control()`), placed first in BuddyNext's own Appearance
 * card. Four tiles, two by two at phone width; each carries a small sample of
 * its scheme — the ground, a card and the accent — painted in that scheme's
 * own values whatever is showing, which is why the samples are the one place
 * the palette's literals are repeated. "Same as this device" is split
 * light/dark.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-scheme { margin: 0 0 20px; }
.ek-scheme__set { margin: 0; padding: 0; border: 0; min-width: 0; }
.ek-scheme__legend { display: block; margin: 0 0 10px; padding: 0; }
.ek-scheme__opts {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px;
}
@media (min-width: 560px) {
	.ek-scheme__opts { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.ek-scheme__opt {
	position: relative;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	gap: 8px;
	min-width: 0;
	padding: 10px;
	border: 1px solid var(--ds-line);
	border-radius: var(--ds-radius);
	background: var(--ds-surface);
	color: var(--ds-ink);
	cursor: pointer;
}
.ek-scheme__opt:hover { border-color: var(--ds-accent); }
.ek-scheme__opt:has(.ek-scheme__radio:checked) {
	border-color: var(--ds-accent);
	box-shadow: 0 0 0 1px var(--ds-accent);
	background: var(--ds-accent-soft);
}
.ek-scheme__opt:has(.ek-scheme__radio:focus-visible) {
	outline: 2px solid var(--ds-accent);
	outline-offset: 2px;
}
/* The radio stays in the tree for keyboard and screen reader; the tile is its face. */
.ek-scheme__radio {
	position: absolute;
	opacity: 0;
	width: 1px; height: 1px;
	margin: 0;
}
.ek-scheme__name { font-weight: 600; font-size: 14px; line-height: 1.25; overflow-wrap: anywhere; }
.ek-scheme__opt:has(.ek-scheme__radio:checked) .ek-scheme__name { color: var(--ds-accent-text); }

.ek-scheme__swatch {
	position: relative;
	display: block;
	height: 44px;
	border-radius: 10px;
	border: 1px solid var(--ds-line);
	overflow: hidden;
}
/* A card on the ground, with an accent bar on it. */
.ek-scheme__swatch i {
	position: absolute;
	left: 10px; right: 10px; top: 10px; bottom: -4px;
	border-radius: 6px 6px 0 0;
	background: var(--sw-surface);
	box-shadow: inset 0 3px 0 var(--sw-accent);
}
.ek-scheme__swatch--light { background: #F3F4F9; --sw-surface: #FFFFFF; --sw-accent: #3F5BD9; }
.ek-scheme__swatch--dark  { background: #0D0E11; --sw-surface: #17181C; --sw-accent: #4B67E8; } /* near-black (Kevin, 30 Sep: "Swap them") */
.ek-scheme__swatch--night { background: #161A2E; --sw-surface: #22273F; --sw-accent: #4B67E8; } /* navy */
.ek-scheme__swatch--system {
	background: linear-gradient(90deg, #F3F4F9 50%, #0D0E11 50%);
	--sw-surface: linear-gradient(90deg, #FFFFFF 50%, #17181C 50%);
	--sw-accent: #3F5BD9;
}

.ek-scheme__save { margin-top: 12px; }
/* With script a tap saves, so the button is only for a browser without it. */
.ek-scheme--live .ek-scheme__save { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
 * A young person's photo control opens the avatar builder (Kevin, morning
 * 30 Sep 2026; companion Family\YouthPhotos). On her edit screen the upload
 * button is hidden; the companion's script puts a link to the builder in its
 * place, in the same corner and the same shape (`.ek-ep-avatar-design` keeps
 * the vendor's `.bn-ep-avatar-btn`). Without script the link shows under the
 * hero instead. Staff editing a young person's profile get no upload either.
 * ══════════════════════════════════════════════════════════════════════════ */
.ek-ep--designs .bn-ep-avatar-btn:not(.ek-ep-avatar-design) { display: none !important; }
.ek-ep-avatar-design { color: inherit; text-decoration: none; }
.ek-ep-design { margin: 10px 0 0; }
.ek-ep-design[hidden] { display: none; }
.ek-ep-design__link { font-weight: 600; color: var(--ds-accent-text); }
