/**
 * Stats — front-end stylesheet.
 *
 * Two responsibilities:
 *
 *   1. The BP profile nav tab icon. Rendered as a CSS ::before
 *      pseudo-element on the anchor inside the BP-generated
 *      <li id="stats-profile-tab-personal-li">. Strategy borrowed
 *      from the reference "Interests" plugin — the icon becomes part
 *      of the anchor's own text flow, so it inherits color,
 *      font-size, and hover-state from its parent automatically. The
 *      "icon disconnected from text" problem in 1.0.2 (which used
 *      DOM-injected <i> elements) is fixed by this approach.
 *
 *   2. The Stats tab body — header, summary cards, chart, scale
 *      switcher, and empty-state note.
 */

/* ==================================================================
 * 1. Nav tab Font Awesome icon — CSS ::before.
 *
 * BuddyPress renders our profile tab as:
 *
 *   Legacy templates : <li id="stats-profile-tab-personal-li">
 *                         <a id="user-stats-profile-tab" ...>Stats</a>
 *                      </li>
 *   BP Nouveau       : <li id="stats-profile-tab-personal-li">
 *                         <a ...>Stats</a>
 *                      </li>
 *
 * (BP appends "-personal-li" to the `item_css_id` we pass into
 * bp_core_new_nav_item.)
 *
 * The font-family stack covers FA4 / FA5 / FA6 Free & Pro so the
 * glyph renders no matter which Font Awesome version the active
 * theme has loaded. For fa-chart-line we need the SOLID variant
 * (font-weight: 900) — the icon doesn't exist in the regular
 * variant.
 *
 * Sizing/color: NOT set explicitly. The pseudo-element inherits
 * font-size and color from the <a> automatically, which is the
 * whole point of doing it this way — the icon scales with the
 * label text and changes color on :hover/:focus along with it.
 * ================================================================== */

#stats-profile-tab-personal-li > a::before,
#user-stats-profile-tab::before,
li[id^="stats-profile-tab"] > a::before {
	content: "\f201";                            /* fa-chart-line */
	font-family: "Font Awesome 6 Free",
				 "Font Awesome 6 Pro",
				 "Font Awesome 5 Free",
				 "Font Awesome 5 Pro",
				 "FontAwesome";
	font-weight: 900;                            /* solid variant */
	font-style: normal;
	font-variant: normal;
	text-rendering: auto;
	line-height: 1;
	display: inline-block;
	margin-right: 6px;
	vertical-align: -1px;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	speak: none;
}

/* Optional inline icon — used inside the tab body header (h2.title).
 * Inherits color from its parent so the in-page heading icon picks
 * up whatever text color the theme assigns to h2. */
.stats-fa-icon,
.stats-tab-title-icon {
	display: inline-block;
	margin-right: 6px;
	color: inherit;
}

/* ==================================================================
 * 2. Tab body
 * ================================================================== */

/* ------------------------------------------------------------------ */
/* Tab wrapper                                                         */
/*                                                                    */
/* margin-top: -50px pulls the heading up to sit closer to the BP nav */
/* tabs above (per your CSS spec). Box-sizing border-box so paddings  */
/* don't push the chart off the right edge of the parent container.  */
/* ------------------------------------------------------------------ */

.stats-tab-wrap {
	max-width: 100%;
	box-sizing: border-box;
	padding: 4px 0 8px;
	margin-top: -50px;
}

.stats-tab-header {
	margin: 0 0 16px;
}

.stats-tab-title {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 20px;
	line-height: 1.3;
	font-weight: 600;
	margin-top: 30px !important;
	margin-left: 15px !important;
}

.stats-tab-title-icon {
	color: #1e73be;
	font-size: 18px;
}

.stats-tab-subtitle {
	margin: 0;
	font-size: 13px;
	color: #6b7280;
	line-height: 1.45;
}

/* ------------------------------------------------------------------ */
/* Summary row — two cards, each with three colored counters          */
/*                                                                    */
/* Each card displays "<title>" as a small uppercase label, then a    */
/* row of three counters: total (black), members (green), guests      */
/* (blue). Colors stay in sync with Stats_Chart::colors() so the      */
/* numbers and the curves read as one linked story.                   */
/*                                                                    */
/* The numbers use tabular-nums so they align cleanly when totals     */
/* span different digit widths across the two cards.                  */
/* ------------------------------------------------------------------ */

.stats-summary-row {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin: 0 0 16px;
}

.stats-summary-card {
	flex: 1 1 240px;
	min-width: 240px;
	box-sizing: border-box;
	padding: 3px 8px;
	background: #f7f9fb;
	background-clip: border-box;
	border: 1px solid #e3e6ea;
	border-radius: 6px;
}

.stats-summary-label {
	font-size: 11px;
	color: #6b7280;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	margin-bottom: 2px;
}

.stats-summary-row-numbers {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 14px;
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
}

.stats-num {
	display: inline-flex;
	align-items: baseline;
	gap: 5px;
}

.stats-num strong {
	font-size: 20px;
	font-weight: 700;
	line-height: 1.1;
}

.stats-num-label {
	font-size: 11px;
	color: #6b7280;
	letter-spacing: 0.02em;
	text-transform: lowercase;
}

/* Color contract — must match Stats_Chart::colors() */
.stats-num-total    strong { color: #1f2937; }   /* near-black */
.stats-num-member   strong { color: #16a34a; }   /* green */
.stats-num-guest    strong { color: #1e73be; }   /* blue */
.stats-num-register strong { color: #f59e0b; }   /* orange — registrations */

/* ------------------------------------------------------------------ */
/* Chart wrapper + chart                                               */
/*                                                                    */
/* The wrapper is flush at 100% of the parent column (no negative     */
/* margins, no width extension). The chart was made wider by trimming */
/* the internal SVG padding instead — see Stats_Chart::PAD_LEFT and   */
/* PAD_RIGHT in includes/class-stats-chart.php (and the mirrored      */
/* defaults in assets/js/stats-chart.js). That moves the plot-area    */
/* edges closer to the SVG's outer edges, which is what gives the     */
/* line and grid more horizontal room — without changing the size of  */
/* the wrapper container at all.                                      */
/*                                                                    */
/* Negative bottom margin (-15px) per your spec lets the chart        */
/* visually overlap the scale-switcher slightly without affecting     */
/* the buttons' click targets.                                        */
/* ------------------------------------------------------------------ */

.stats-chart-wrap {
	width: 100%;
	margin: 0 0 -15px;
	padding: 0;
}

.stats-chart {
	width: 100%;
	max-width: 100%;
	background: #fff0;
	background-clip: border-box;
	background-clip: border-box;
	border: 0px solid #e3e6ea;
	border-radius: 6px;
	padding: 0;
	box-sizing: border-box;
	overflow: hidden;
}

/* The SVG itself fills the chart container width 100%. Internal
 * SVG padding (PAD_LEFT/PAD_RIGHT in PHP) reserves space for axis
 * labels — we don't add CSS padding around the SVG. */
.stats-chart-svg {
	display: block;
	width: 100%;
	height: auto;
	max-height: 260px;
}

/* ------------------------------------------------------------------ */
/* Chart curves                                                        */
/*                                                                    */
/* Per-layer stroke colors are set as inline SVG attributes by the    */
/* renderer (PHP and JS sides), so they look right even if this CSS  */
/* fails to load. The class-based rules below are a soft override —  */
/* themes can re-skin curves by changing these properties without    */
/* editing the renderer.                                              */
/* ------------------------------------------------------------------ */

.stats-chart-line {
	fill: none;
}
.stats-chart-line-total    { stroke: #6b7280; }
.stats-chart-line-member   { stroke: #16a34a; }
.stats-chart-line-guest    { stroke: #1e73be; }
.stats-chart-line-register { stroke: #f59e0b; }

.stats-chart-bg {
	fill: #fff0;
}
.stats-chart-frame {
	stroke: #e3e6ea;
}
.stats-chart-grid {
	stroke: #eef1f4;
}
.stats-chart-xtick {
	stroke: #cbd2d9;
}
.stats-chart-xlabel,
.stats-chart-ylabel {
	fill: #6b7280;
}
.stats-chart-today          { fill: #6b7280; }
.stats-chart-today-total    { fill: #6b7280; }
.stats-chart-today-member   { fill: #16a34a; }
.stats-chart-today-guest    { fill: #1e73be; }
.stats-chart-today-register { fill: #f59e0b; }

/* ------------------------------------------------------------------ */
/* Legend — small inline color-key strip below the scale switcher.    */
/*                                                                    */
/* Helps readers map the three curves to their meaning without        */
/* hovering. Colors mirror Stats_Chart::colors() exactly.             */
/* ------------------------------------------------------------------ */

.stats-legend {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 14px;
	margin: 0 0 14px;
	font-size: 11px;
	color: #6b7280;
	letter-spacing: 0.02em;
}

.stats-legend-item {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	line-height: 1.2;
}

.stats-legend-swatch {
	display: inline-block;
	width: 14px;
	height: 3px;
	border-radius: 2px;
	background: #6b7280;
}

.stats-legend-total    .stats-legend-swatch { background: #6b7280; }
.stats-legend-member   .stats-legend-swatch { background: #16a34a; }
.stats-legend-guest    .stats-legend-swatch { background: #1e73be; }
.stats-legend-register .stats-legend-swatch { background: #f59e0b; }

/* ------------------------------------------------------------------ */
/* Scale switcher — Daily / Weekly / Monthly / Yearly                  */
/*                                                                    */
/* Default state per your spec: light gray fill (#f1f4f7) with        */
/* muted text color (#777b80). Hover lifts to a soft blue tint;       */
/* active state is solid blue. Stocks-app aesthetic, small font       */
/* (11px) so the switcher reads as secondary chrome, not primary UI. */
/* ------------------------------------------------------------------ */

.stats-scale-switcher {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 4px;
	margin: 6px 0 14px;
	padding: 0;
}

button.stats-scale-btn {
	background: #f1f4f7;
	color: #777b80;
}

.stats-scale-btn {
	appearance: none;
	-webkit-appearance: none;
	border: 1px solid transparent;
	border-radius: 999px;
	padding: 4px 12px;
	margin: 0;
	font-family: inherit;
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.02em;
	cursor: pointer;
	line-height: 1.4;
	text-transform: none;
	transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}

.stats-scale-btn:hover,
.stats-scale-btn:focus {
	color: #1e73be;
	border-color: #d6e4f2;
	background: #f3f8fd;
	outline: none;
}

.stats-scale-btn.is-active,
button.stats-scale-btn.is-active {
	color: #ffffff;
	background: #1e73be;
	border-color: #1e73be;
}

.stats-scale-btn.is-active:hover,
.stats-scale-btn.is-active:focus,
button.stats-scale-btn.is-active:hover,
button.stats-scale-btn.is-active:focus {
	color: #ffffff;
	background: #155a98;
	border-color: #155a98;
}

/* ------------------------------------------------------------------ */
/* Empty-state note                                                    */
/* ------------------------------------------------------------------ */

.stats-empty-note {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	margin: 12px 0 0;
	padding: 10px 12px;
	background: #f7f9fb;
	border: 1px solid #e3e6ea;
	border-radius: 6px;
	color: #4b5563;
	font-size: 13px;
	line-height: 1.5;
}

.stats-empty-note i {
	color: #1e73be;
	margin-top: 2px;
	flex: 0 0 auto;
}

/* ------------------------------------------------------------------ */
/* Denied state                                                        */
/* ------------------------------------------------------------------ */

.stats-tab-denied {
	padding: 14px 16px;
	border: 1px solid #f5d6c6;
	background: #fff7f1;
	color: #8a3b16;
	border-radius: 6px;
	font-size: 14px;
}

.stats-tab-denied p {
	margin: 0;
}

/* ==================================================================
 * 3. wp-admin "Statistics" page
 *
 * The admin Statistics page reuses the same .stats-tab-wrap / chart
 * / scale-switcher / legend markup as the BP profile tab, so most
 * styles flow through unchanged. The rules below cover only the
 * admin-specific chrome (the "wrap" page wrapper, the H1 with FA
 * icon, the lede paragraph, and the auxiliary "profiles tracked"
 * row) AND override the negative top-margin on .stats-tab-wrap which
 * exists for BP layout reasons but doesn't apply in wp-admin.
 * ================================================================== */

.stats-admin-wrap {
	max-width: 1100px;
}

.stats-admin-title {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 16px 0 6px;
	font-size: 23px;
	font-weight: 400;
	line-height: 1.3;
}

.stats-admin-title-icon {
	color: #1e73be;
	font-size: 20px;
}

.stats-admin-lede {
	margin: 0 0 18px;
	font-size: 13px;
	color: #50575e;
	line-height: 1.5;
	max-width: 760px;
}

.stats-admin-aux {
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	margin: 0;
	padding: 6px 12px;
	background: #f0f4f7;
	border: 1px solid #dde3e8;
	border-radius: 6px;
	font-size: 13px;
	color: #50575e;
}

.stats-aux-label {
	letter-spacing: 0.02em;
}

.stats-aux-value {
	font-size: 15px;
	font-weight: 700;
	color: #1f2937;
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ */
/* Auxiliary row — flex container holding the "Profiles tracked"      */
/* counter on the left and the region filter dropdown on the right.   */
/* The flex layout keeps them aligned baseline-to-baseline and lets   */
/* the dropdown wrap below the counter on narrow viewports without    */
/* either element clipping.                                           */
/* ------------------------------------------------------------------ */

.stats-admin-aux-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px;
	margin: 0 0 14px;
}

/* ------------------------------------------------------------------ */
/* Region filter — dropdown + footnote                                 */
/* ------------------------------------------------------------------ */

.stats-region-filter {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	color: #50575e;
}

.stats-region-label {
	letter-spacing: 0.02em;
	font-weight: 500;
}

.stats-region-select {
	padding: 4px 26px 4px 10px;
	font-size: 13px;
	line-height: 1.4;
	color: #1f2937;
	background: #ffffff;
	border: 1px solid #dde3e8;
	border-radius: 6px;
	min-width: 160px;
	max-width: 280px;
	cursor: pointer;
	transition: border-color 120ms ease, box-shadow 120ms ease;
}

.stats-region-select:hover {
	border-color: #c2cdd6;
}

.stats-region-select:focus {
	outline: none;
	border-color: #1e73be;
	box-shadow: 0 0 0 2px rgba(30, 115, 190, 0.18);
}

.stats-region-select[aria-busy="true"] {
	opacity: 0.6;
	cursor: progress;
}

.stats-region-note {
	font-size: 11px;
	color: #6b7280;
	font-style: italic;
	max-width: 320px;
	line-height: 1.4;
}
.stats-region-note[hidden] {
	display: none;
}

/* ------------------------------------------------------------------ */
/* Secondary summary row — registrations card                          */
/*                                                                    */
/* Sits between the visit cards and the chart. Single card, full      */
/* width, with the orange `stats-num-register` colored numbers.       */
/* ------------------------------------------------------------------ */

.stats-summary-row-secondary {
	margin-top: -4px;
}

.stats-summary-card-registrations {
	flex: 1 1 100%;
	min-width: 100%;
	background: #fdf6ec;
	border-color: #f1d8a6;
}

/* The two scope wrappers (.stats-card-scope) flex like the cards
 * themselves so the JS can target month-vs-all numbers without
 * shrinking the cards. */
.stats-card-scope {
	flex: 1 1 240px;
	min-width: 240px;
	display: flex;
}
.stats-card-scope > .stats-summary-card {
	flex: 1 1 auto;
	min-width: 0;
}

/* In the admin context, the BP-layout-specific negative top margin
 * is wrong — there's no stack of nav tabs above us to pull under.
 * The .stats-tab-wrap-admin modifier resets it. */
.stats-tab-wrap-admin {
	margin-top: 0;
}

/* ------------------------------------------------------------------ */
/* Mobile tweaks                                                       */
/* ------------------------------------------------------------------ */

@media (max-width: 520px) {
	.stats-tab-wrap {
		margin-top: -30px;
	}
	.stats-tab-title {
		font-size: 18px;
	}
	.stats-summary-card {
		min-width: 100%;
		flex-basis: 100%;
		padding: 4px 10px;
	}
	.stats-summary-row-numbers {
		gap: 10px;
	}
	.stats-num strong {
		font-size: 18px;
	}
	.stats-scale-btn {
		padding: 4px 10px;
		font-size: 10px;
	}
	.stats-legend {
		gap: 10px;
		font-size: 10px;
	}
}

/* ==================================================================
 * 3. Live "<N> Members Online" counter — 1.0.8, refined in 1.0.9.
 *
 * Rendered by Stats_Presence::render_counter_marker() as a placeholder
 * in wp_footer, then relocated by assets/js/stats-presence.js to sit
 * UNDER the GeneratePress `.site-logo`. Sizing/color follows the
 * brief: 14px, light grey.
 *
 * POSITIONING (1.0.9)
 * -------------------
 * GeneratePress's header is typically `display: flex` (the
 * `.inside-header` wrapper). In 1.0.8 the counter was inserted as
 * the next sibling of `.site-logo`, which means it became a flex
 * child too and laid out *beside* the logo. 1.0.9 fixes that two
 * ways:
 *
 *   1. JS inserts the counter AFTER the closest flex/grid ancestor
 *      of the logo, so it lands as a sibling of the whole header row
 *      rather than as a flex sibling of the logo. Body class
 *      `.site-logo-counter-after-flex` is added in this case.
 *
 *   2. CSS below uses `flex: 1 1 100%` and `width: 100%` so that on
 *      the rare theme where the counter STILL ends up inside a flex
 *      container (custom header layouts, child themes that wrap the
 *      logo unconventionally), it forces a wrap onto its own row
 *      instead of squeezing next to the logo.
 *
 * `pointer-events: none` because the counter is informational —
 * stray clicks shouldn't intercept the logo's link area.
 *
 * The color is set explicitly rather than relying on inherit; the
 * `.site-logo` is typically an <a>, and inherited color would be
 * the theme's link color (often a brand accent) which doesn't
 * match the "light grey" spec on most themes.
 * ================================================================== */
.stats-online-counter {
	/* Force block + full-row layout. The combination of
	 * `display: block` + `width: 100%` + `flex-basis: 100%` covers
	 * the three positioning regimes the counter can land in:
	 *
	 *   - Normal block flow → display:block handles it.
	 *   - Inside a flex container → flex-basis:100% forces wrap.
	 *   - Inside a grid container → grid-column:1/-1 spans full row.
	 *
	 * All three rules are safe to apply unconditionally — each is a
	 * no-op outside its corresponding layout regime.
	 */
	display: block;
	width: 100%;
	flex: 0 0 100%;
	grid-column: 1 / -1;

	font-size: 14px;
	color: #9e9e9e;            /* "light grey" — neutral, theme-agnostic. */
	font-weight: 400;
	line-height: 1.4;
	margin-top: 4px;
	margin-bottom: 0;
	padding: 0;
	text-align: inherit;        /* center-logo headers: counter follows the logo's alignment. */
	/* 1.5.0 — the element is now an <a href="/members/">. Two
	 * adjustments needed against the legacy <div> shape:
	 *
	 *   - Reset the theme's default anchor underline so the counter
	 *     keeps reading as a small status line, not a link banner.
	 *     Underline returns on hover/focus only.
	 *   - Drop the old `pointer-events: none` rule — the whole point
	 *     of being a link is that clicks DO navigate.
	 */
	text-decoration: none;
	cursor: pointer;

	/* font-family inherits from <body> so the counter matches the
	   site's body face rather than the logo's display face. */
}

a.stats-online-counter:hover,
a.stats-online-counter:focus {
	text-decoration: underline;
	color: inherit;
}

/* Smooth fade when JS hydration replaces the server-rendered count
 * with a fresh live value. ~150ms is fast enough to feel
 * synchronous on a normal connection but slow enough to read as
 * deliberate rather than glitchy.
 */
.stats-online-counter {
	transition: opacity 150ms ease-out;
}

/* When the counter still sits in the footer (the JS relocation
 * didn't run — non-GP theme, JS disabled, or .site-logo missing),
 * keep it from looking like an orphaned footer banner.
 */
body:not(.site-logo-counter-mounted) #stats-online-counter {
	margin-top: 8px;
	padding: 6px 12px;
}

/* When the counter has been mounted via the flex/grid path, place
 * it visually under the logo. The negative margin-top pulls the
 * counter up into the header's lower whitespace (the flex row
 * leaves space below the logo that we'd otherwise be skipping
 * past), and margin-left aligns it to the logo's visual baseline
 * rather than to the very left edge of the header container.
 *
 * Color #577130 is the site's olive/brand neutral — overrides the
 * default #9e9e9e from the base rule for the after-flex path
 * specifically, because in that path the counter sits against the
 * header's background which makes the lighter grey too washed-out
 * to read.
 *
 * Values per spec (1.1.0):
 *   - margin-top: -26px   (pull up into the logo row)
 *   - margin-left: 70px   (align to logo wordmark baseline)
 *   - color: #577130      (brand olive)
 */
body.site-logo-counter-after-flex #stats-online-counter {
	margin-top: -26px;
	margin-left: 70px;
	color: #577130;
}

/* ==================================================================
 * 4. "My Visitors" panel — 1.2.0
 *
 * Sits below the chart on the Stats tab. The grid itself is
 * deliberately MINIMALLY styled here — the <ul> uses the exact same
 * selector set as the BP Nouveau /members directory (#members-list,
 * .item-list, .members-list, .bp-list, .grid, .four) so:
 *
 *   - The GP child theme's grid rule (#members-list { display: grid;
 *     grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
 *     gap: 1rem; }) applies.
 *   - The GP child theme's rounded-avatar rule
 *     (.buddypress-wrap.round-avatars .avatar { border-radius: 50%;
 *      height: 120px; }) applies.
 *   - BP Nouveau's per-card responsive widths (.grid.four > li
 *     { width: 25%; }, .grid.three > li { width: 33.3%; }, etc.)
 *     apply along with their @media-query breakpoints.
 *
 * What the rules below DO add:
 *
 *   - Top margin (the 30px gap the spec called for between the chart
 *     and the visitors heading).
 *   - A self-contained fallback grid for themes that DON'T already
 *     style #members-list — so the plugin still produces a 4-column
 *     responsive grid on a stock WP theme.
 *   - The full-width "Load More" button.
 *   - A subtle "loading" state for the button while the REST call
 *     is in flight.
 * ================================================================== */

.stats-visitors-wrap {
	margin: 30px 0 0;
	padding: 0;
	box-sizing: border-box;
}

/* The "My Visitors" heading reuses .stats-tab-title (same display
 * flex/gap/size/weight as the "Profile Stats" heading), but the
 * 30px top margin from that base rule is already accounted for by
 * the section wrapper above — leaving the rule unchanged keeps the
 * two headings visually paired. The icon styling is also inherited
 * from .stats-tab-title-icon (defined earlier in this file). */
.stats-visitors-title {
	/* No additional rules needed — the spec was specifically "use
	   same label parameters as for .stats-tab-title". The class
	   .stats-visitors-title is kept only as a hook for sites that
	   want to differentiate the two headings later. */
}

/* ------------------------------------------------------------------
 * Fallback grid — only fires when the active theme has NOT styled
 * #members-list itself. The :where() wrapper drops specificity to
 * zero so any theme rule on #members-list wins automatically; if
 * the theme has nothing, our reset takes effect.
 *
 * The rule is gated by `.stats-visitors-list` so we never affect
 * an actual members directory page that happens to share the DOM.
 * ------------------------------------------------------------------ */

:where(#members-list.stats-visitors-list) {
	margin: 16px 0 0;
	padding: 0;
	border-top: 0;
	list-style: none;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: 1rem;
}

:where(#members-list.stats-visitors-list)::before {
	content: none;
}

:where(#members-list.stats-visitors-list > li) {
	margin: 0;
	padding: 0;
	width: auto;
	float: none;
	border-bottom: 0;
	box-sizing: border-box;
	list-style: none;
}

/* Center the avatar + text block on each visitor card. Same effect
 * as BP Nouveau's `.buddypress-wrap .grid.bp-list > li .item-avatar
 * { text-align: center; }` rule, applied as a fallback. */
:where(#members-list.stats-visitors-list > li .item-avatar) {
	text-align: center;
	margin: 0;
}
:where(#members-list.stats-visitors-list > li .item-avatar img.avatar) {
	border-radius: 50%;
	display: inline-block;
	height: 120px;
	width: auto;
	max-width: 100%;
}
:where(#members-list.stats-visitors-list > li .item) {
	text-align: center;
	margin: 8px auto 0;
}
:where(#members-list.stats-visitors-list > li .list-title) {
	font-size: 15px;
	line-height: 1.2;
	margin: 6px 0 2px;
	font-weight: 600;
}
:where(#members-list.stats-visitors-list > li .list-title a) {
	text-decoration: none;
}
:where(#members-list.stats-visitors-list > li .bp_nickname) {
	font-size: 12px;
	color: #6b7280;
	margin: 2px 0;
}
:where(#members-list.stats-visitors-list > li .bp_profession),
:where(#members-list.stats-visitors-list > li .bp_country) {
	font-size: 12px;
	color: #4b5563;
	margin: 2px 0;
	line-height: 1.3;
}
:where(#members-list.stats-visitors-list > li .last-activity) {
	font-size: 11px;
	color: #9ca3af;
	margin: 6px 0 0;
	font-style: italic;
}

/* ------------------------------------------------------------------
 * Load More button — full-width by spec.
 *
 * Uses the same blue accent as the active scale-switcher pill
 * (#1e73be) so the two interactive elements on this page read as
 * one design system. Hover state mirrors the scale-switcher hover
 * darker tone (#155a98).
 * ------------------------------------------------------------------ */

.stats-visitors-load-more {
	appearance: none;
	-webkit-appearance: none;
	display: block;
	width: 100%;
	box-sizing: border-box;
	margin: 20px 0 0;
	padding: 12px 16px;
	background: #1e73be;
	color: #ffffff;
	border: 1px solid #1e73be;
	border-radius: 6px;
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: 0.02em;
	cursor: pointer;
	text-align: center;
	transition: background-color 120ms ease, border-color 120ms ease, opacity 120ms ease;
}

.stats-visitors-load-more:hover,
.stats-visitors-load-more:focus {
	background: #155a98;
	border-color: #155a98;
	color: #ffffff;
	outline: none;
}

.stats-visitors-load-more[disabled],
.stats-visitors-load-more[aria-busy="true"] {
	opacity: 0.65;
	cursor: progress;
	pointer-events: none;
}

/* Empty-state variant — when the profile has zero recorded
 * visitors, we still render the section but with a friendly note
 * instead of an empty grid. Reuses .stats-empty-note styling for
 * visual consistency with the chart's empty-state. */
.stats-visitors-empty {
	margin-top: 16px;
}

/* ------------------------------------------------------------------
 * Mobile tweaks — the BP/GP responsive rules already cover the
 * card grid itself; these only adjust spacing of OUR added chrome
 * (heading offset, button padding).
 * ------------------------------------------------------------------ */

@media (max-width: 520px) {
	.stats-visitors-wrap {
		margin-top: 24px;
	}
	.stats-visitors-load-more {
		padding: 10px 14px;
		font-size: 13px;
	}
	:where(#members-list.stats-visitors-list) {
		grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
		gap: 0.75rem;
	}
	:where(#members-list.stats-visitors-list > li .item-avatar img.avatar) {
		height: 90px;
	}
}


/* ==================================================================
 * 5. Visibility-mode toggle — "Public Visible / Private Browsing"
 *    (1.3.0). Ported visually intact from the Proconsilium Front
 *    plugin's Consilium/Read-mode capsule — same shape, same vertical
 *    pill, same scroll-away. The original psr-mode-* classes are
 *    re-prefixed to stats-mode-* so the two plugins can coexist on
 *    the same site (both capsules would render side by side on a
 *    single-post page that's also the user's own profile, which is
 *    unusual but possible).
 *
 * Label map:
 *   PSR "Consilium Mode" (ON, green)  → "Public Visible"
 *   PSR "Read Mode"      (OFF, grey)  → "Private Browsing"
 *
 * Default visual state: `.is-off` (grey) — matches the default-
 * private posture chosen in PHP. The server renders the class on
 * the wrapper at page-load time, so there's no JS flash from
 * "green for a frame, then snap to grey".
 * ================================================================== */

/* Wrapper: fixed, label + capsule in one row. */
.stats-mode-toggle {
	position: fixed;
	/* `left` is set dynamically in JS to sit 15px to the LEFT of the
	   main content column. The value here is a fallback used only
	   until the JS measurement runs. */
	left: 15px;
	top: 200px !important;
	z-index: 99990;
	/* The wrapper's box is EXACTLY the capsule (34x64). The label is
	   absolutely positioned and pinned to the capsule's left, so the
	   capsule's position is immovable regardless of label length —
	   no vertical "jump" between modes. */
	width: 34px;
	height: 64px;
	-webkit-user-select: none;
	-moz-user-select: none;
	user-select: none;
}

/* Vertical text label — absolutely positioned to the LEFT of the
   capsule and vertically centred against it. Out of flow so its
   variable length cannot affect the capsule. */
.stats-mode-toggle .stats-mode-label {
	position: absolute;
	right: calc( 100% + 10px );   /* 10px gap left of the capsule */
	top: 50%;
	writing-mode: vertical-rl;
	text-orientation: mixed;
	transform: translateY( -50% ) rotate( 180deg );
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 0.3px;
	line-height: 1;
	white-space: nowrap;
	margin: 0;
	transition: color 0.2s ease;
	color: #8ea580;               /* ON / Public Visible colour */
}

/* Capsule track — vertical pill. */
.stats-mode-toggle .stats-mode-switch {
	position: relative;
	width: 34px;
	height: 64px;
	border-radius: 34px;
	background: #8ab46d24;        /* ON = soft green tint */
	cursor: pointer;
	padding: 0;
	transition: background 0.25s ease, border-color 0.25s ease;
	box-shadow: inset 0 1px 3px rgba( 0, 0, 0, 0.18 );
	-webkit-tap-highlight-color: transparent;
	border: solid 1px #91a580 !important;
}
.stats-mode-toggle .stats-mode-switch:focus-visible {
	outline: 2px solid #2f6f12;
	outline-offset: 2px;
}

/* White knob. Sits near the TOP when ON. */
.stats-mode-toggle .stats-mode-knob {
	position: absolute;
	left: 50%;
	transform: translateX( -50% );
	top: 4px;                     /* ON position = up */
	width: 26px;
	height: 26px;
	border-radius: 50%;
	background: #ffffff;
	box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.3 );
	transition: top 0.25s ease;
	pointer-events: none;
}

/* ----- OFF state (Private Browsing) -------------------------------- */
.stats-mode-toggle.is-off .stats-mode-switch {
	background: #9aa0a60d;
	border: solid 1px #97aec12b !important;
}
.stats-mode-toggle.is-off .stats-mode-knob {
	top: 34px;                    /* OFF position = down (64 - 4 - 26) */
}
.stats-mode-toggle.is-off .stats-mode-label {
	color: #adbad2;
}

/* Brief in-flight visual when a flip is being persisted: the JS
 * adds `is-busy` after the user agrees, before the REST round-trip
 * resolves. Dims the knob slightly so the user knows something is
 * happening without a spinner cluttering the capsule. */
.stats-mode-toggle.is-busy .stats-mode-knob {
	opacity: 0.55;
}
.stats-mode-toggle.is-busy {
	pointer-events: none;
}

/* Scroll-away state: fade out as the toggle's bottom edge nears the
 * end of the content body, so it doesn't hover over comments or
 * other below-the-fold UI. JS toggles `.is-hidden`. */
.stats-mode-toggle {
	transition: opacity 0.2s ease, visibility 0.2s ease;
}
.stats-mode-toggle.is-hidden {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

/* On very short viewports, nudge the toggle up so it never collides
 * with the footer; keep it comfortably below the header otherwise. */
@media ( max-height: 600px ) {
	.stats-mode-toggle {
		top: 110px;
	}
}

/* Hide the toggle entirely on narrower screens (below 1200px),
 * where there isn't room for a left-gutter control beside the
 * content column. Members on mobile will see the privacy-mode
 * notice on the Stats tab when they're in Private mode, but can't
 * change it from there in this version — desktop-only setting,
 * same constraint PSR ships with. */
@media ( max-width: 1199.98px ) {
	.stats-mode-toggle {
		display: none !important;
	}
}


/* ==================================================================
 * 6. Visibility confirmation modal (1.3.0)
 *    -----------------------------------
 *    Two pre-rendered modals (one per direction) live in the page
 *    DOM hidden. The JS controller pops the appropriate one open
 *    on toggle click, captures Cancel/Agree, and either reverts the
 *    visual toggle (Cancel) or POSTs to the REST endpoint (Agree).
 *
 *    The visuals follow the spec literally: Cancel = grey, Agree =
 *    green. The green of the Public-direction Agree matches the
 *    olive used elsewhere in the plugin (the .stats-online-counter
 *    after-flex color), so the "Agree" button reads as the same
 *    brand-positive action across the plugin.
 * ================================================================== */

/* Backdrop — dim the page behind the modal while open. Pointer-
 * events claimed so clicks outside the modal are absorbed (we add
 * an explicit click-to-dismiss handler in JS that treats backdrop
 * clicks as Cancel). */
.stats-visibility-modal-backdrop {
	position: fixed;
	inset: 0;
	background: rgba( 17, 24, 39, 0.55 );
	z-index: 99998;
	-webkit-backdrop-filter: blur( 1px );
	backdrop-filter: blur( 1px );
}
.stats-visibility-modal-backdrop[hidden] {
	display: none !important;
}

/* Modal container — centered. The inner wraps the actual card so
 * we can apply padding/border-radius separately from the centering
 * math. */
.stats-visibility-modal {
	position: fixed;
	inset: 0;
	z-index: 99999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
	box-sizing: border-box;
	pointer-events: none;  /* clicks pass through the centering wrapper… */
}
.stats-visibility-modal[hidden] {
	display: none !important;
}

.stats-visibility-modal-inner {
	pointer-events: auto;  /* …but land on the actual card. */
	background: #ffffff;
	border-radius: 12px;
	box-shadow:
		0 1px 3px rgba( 0, 0, 0, 0.10 ),
		0 12px 32px rgba( 17, 24, 39, 0.28 );
	max-width: 460px;
	width: 100%;
	padding: 22px 24px 18px;
	box-sizing: border-box;
	font-family: inherit;
	color: #1f2937;
	animation: stats-visibility-modal-pop 160ms ease-out;
	/* Centered layout — 1.4.0. The spec asks for the title, body
	 * copy, and action buttons to all sit on the modal's central
	 * axis. Setting text-align here makes the title + body text
	 * centred automatically (they're block-level paragraphs/
	 * headings that inherit text-align), and the action row picks
	 * up its own justify-content: center below. */
	text-align: center;
}

@keyframes stats-visibility-modal-pop {
	from {
		opacity: 0;
		transform: scale( 0.96 );
	}
	to {
		opacity: 1;
		transform: scale( 1 );
	}
}

.stats-visibility-modal-title {
	margin: 0 0 10px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	color: #111827;
	/* text-align inherits from .stats-visibility-modal-inner — centred. */
}

.stats-visibility-modal-body {
	margin: 0 0 18px;
	font-size: 14px;
	line-height: 1.55;
	color: #374151;
	/* text-align inherits — centred. The longer copy strings the
	 * 1.3.0 spec ships with breathe better centred at the 460px
	 * max-width than they did left-aligned (which left a thin
	 * left rag on the second line). */
}

.stats-visibility-modal-actions {
	display: flex;
	justify-content: center;  /* centred per 1.4.0 spec */
	gap: 12px;
	margin: 0;
	padding: 0;
}

.stats-visibility-modal-btn {
	appearance: none;
	-webkit-appearance: none;
	display: inline-block;
	padding: 9px 22px;        /* a touch more horizontal room for the pill */
	border-radius: 25px;      /* fully-rounded pill per 1.4.0 spec */
	border: 1px solid transparent;
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: 0.02em;
	cursor: pointer;
	transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

/* Cancel — grey, pill-rounded. */
.stats-visibility-modal-btn-cancel {
	background: #e5e7eb;
	color: #1f2937;
	border-color: #e5e7eb;
	border-radius: 25px;
}
.stats-visibility-modal-btn-cancel:hover,
.stats-visibility-modal-btn-cancel:focus {
	background: #d1d5db;
	border-color: #d1d5db;
	outline: none;
}

/* Agree — green pill. 1.4.0 swaps the background to #7db04a (a
 * brighter, friendlier olive that visually matches the toggle's
 * own ON-state green family) while keeping the original #16a34a
 * as the BORDER colour — that 1px outline keeps a clean edge
 * against light page backgrounds where #7db04a would otherwise
 * read as a flat blob. */
.stats-visibility-modal-btn-agree {
	background: #7db04a;
	color: #ffffff;
	border-color: #16a34a;
	border-radius: 25px;
}
.stats-visibility-modal-btn-agree:hover,
.stats-visibility-modal-btn-agree:focus {
	background: #6a9d3c;
	border-color: #138a3f;
	color: #ffffff;
	outline: none;
}

/* Busy state (REST round-trip in flight). */
.stats-visibility-modal-btn[disabled],
.stats-visibility-modal-btn[aria-busy="true"] {
	opacity: 0.65;
	cursor: progress;
	pointer-events: none;
}

/* Mobile sizing — match the modal padding to the smaller viewport.
 * Modals still render on mobile even though the floating toggle
 * itself is hidden — useful for power users who flip via JS from
 * the browser console, and a no-op cost for everyone else. */
@media ( max-width: 520px ) {
	.stats-visibility-modal {
		padding: 12px;
	}
	.stats-visibility-modal-inner {
		padding: 18px 18px 14px;
	}
	.stats-visibility-modal-title {
		font-size: 16px;
	}
	.stats-visibility-modal-body {
		font-size: 13.5px;
	}
}

/* Private-mode notice in the My Visitors section. Lives in the
 * .stats-visitors-wrap block from section 4 — placed here for
 * proximity with the toggle/modal styles it explains. */
.stats-visitors-private-notice i {
	color: #6b7280;
}


/* ==================================================================
 * 7. Visitor card additions (1.4.0)
 *
 * Two new lines added to the cards rendered by Stats_Visitors::
 * render_card(), and to the GP child theme's /members loop:
 *
 *   .bp_region / .member-region    — the visitor's Region xprofile
 *                                    field, sitting under .bp_country.
 *
 *   .stats-visitor-visited-ago     — "visited 3 hours ago" style line
 *                                    sourced from the stats_visitors
 *                                    last_visited_at column. Only
 *                                    appears on My Visitors cards
 *                                    (the /members directory has no
 *                                    per-visit timestamp to show).
 *
 * Both inherit the centred / small / muted typography of the cards
 * around them; explicit rules below cover sites that don't already
 * style siblings like .bp_country (so the new lines never read as
 * accidentally different).
 * ================================================================== */

:where(#members-list.stats-visitors-list > li .bp_region),
:where(#members-list.stats-visitors-list > li .member-region) {
	font-size: 12px;
	color: #4b5563;
	margin: 2px 0;
	line-height: 1.3;
}

:where(#members-list.stats-visitors-list > li .stats-visitor-visited-ago) {
	font-size: 11px;
	color: #9ca3af;
	margin: 6px 0 0;
	font-style: italic;
}

/* 1.6.2 — visit-time line sits flush against the line above it.
 * Explicit selector path matches the GP theme's card markup
 * (`div.item-block > p.item-meta.stats-visitor-visited-ago`),
 * so this rule wins specifically over the generic .item-meta
 * margins the theme stack applies — without needing !important. */
div.item-block p.item-meta.stats-visitor-visited-ago {
	margin-top: 0px;
}


/* ==================================================================
 * 8. Inline horizontal twin of the visibility toggle (1.5.0)
 *
 * Rendered inside the My Visitors "you're in Private Browsing"
 * notice so users can flip back to Public without scrolling up to
 * the fixed left-gutter capsule. Same data attributes, same JS
 * controller, same modal-confirm flow as the floating toggle —
 * just laid out horizontally and centred in its container.
 *
 * The class `.stats-mode-toggle-inline` overrides whichever rules
 * from section 5 don't fit a horizontal layout. We keep the same
 * colour states (ON / is-off / hover / focus / busy) by NOT
 * overriding the track/knob/label colour rules — those continue to
 * apply because the `.stats-mode-toggle` base class is still on
 * the wrapper.
 *
 * Layout swap:
 *   Vertical capsule (default)        Inline horizontal capsule
 *   -------------------------         --------------------------
 *   wrapper:  34w × 64h               64w × 34h (knob slides L↔R)
 *   label:    LEFT, rotated 180°      ABOVE the capsule, normal
 *                                     text orientation
 *   position: fixed (left gutter)     static (centred in parent)
 * ================================================================== */

.stats-visitors-private-block {
	margin: 16px 0 0;
	padding: 18px 16px;
	text-align: center;
	background: #f9fafb;
	border-radius: 10px;
	border: 1px solid #e5e7eb;
}

.stats-visitors-private-block .stats-visitors-private-notice {
	margin: 0 auto 16px;
	max-width: 620px;
	text-align: center;
	color: #4b5563;
	line-height: 1.55;
}

.stats-mode-toggle.stats-mode-toggle-inline {
	/* Undo the fixed-position rules from the floating capsule.
	 * Centring is done by the parent (.stats-visitors-private-block
	 * has text-align: center) — the wrapper becomes inline-block so
	 * it inherits that horizontal centering. */
	position: static;
	left: auto;
	top: auto !important;
	z-index: auto;
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	/* Horizontal capsule: 64 wide × 34 tall. The base rule had
	 * 34 × 64 — these swaps invert the dimensions, then the knob /
	 * label rules below adapt the rest. */
	width: 64px;
	height: auto;
}

/* Label sits ABOVE the capsule, normal orientation. Override the
 * vertical-rl writing-mode + rotate(180deg) from section 5. */
.stats-mode-toggle.stats-mode-toggle-inline .stats-mode-label {
	position: static;
	right: auto;
	top: auto;
	writing-mode: horizontal-tb;
	text-orientation: mixed;
	transform: none;
	white-space: nowrap;
	/* Label colour inherits from base rule — green when ON, grey
	 * when is-off. No duplicate colour rule here. */
}

/* Horizontal capsule track. Same colours/shadow/border as the
 * vertical capsule (those rules still apply) — just dimensions
 * swap. */
.stats-mode-toggle.stats-mode-toggle-inline .stats-mode-switch {
	width: 64px;
	height: 34px;
	border-radius: 34px;
}

/* Horizontal knob: starts on the RIGHT when ON (Public Visible),
 * slides LEFT when off (Private Browsing). Mirror the vertical
 * "knob up = ON" convention from section 5 — in both, the knob
 * sits at the END of the affirmative direction. */
.stats-mode-toggle.stats-mode-toggle-inline .stats-mode-knob {
	top: 50%;
	left: auto;
	right: 4px;                /* ON position = right end */
	transform: translateY( -50% );
	transition: right 0.25s ease, left 0.25s ease;
}

.stats-mode-toggle.stats-mode-toggle-inline.is-off .stats-mode-knob {
	top: 50%;
	right: auto;
	left: 4px;                 /* OFF position = left end */
	transform: translateY( -50% );
}

/* The inline twin lives inside the section content, so the
 * @media (max-width: 1199.98px) hide rule from section 5 must NOT
 * apply to it. The floating capsule disappears on narrow screens;
 * the inline twin stays so mobile users have a path to flip too.
 *
 * We achieve that by RE-SHOWING the inline variant inside the same
 * media query block. !important is necessary because the section-5
 * rule used `display: none !important`.
 */
@media ( max-width: 1199.98px ) {
	.stats-mode-toggle.stats-mode-toggle-inline {
		display: inline-flex !important;
	}
}


/* ==================================================================
 * 9. Audience filter dropdown — "Your Stats Visibility" (1.5.0)
 *
 * Sits inside the Stats tab header, beside the "Profile Stats"
 * heading. Trigger button shows the placeholder label; clicking
 * pops a panel of checkboxes that decide which audiences can see
 * the owner's Stats tab.
 *
 * Disabled state (`.is-disabled` on the wrapper): rendered when
 * the owner is in Private Browsing. Trigger button is greyed,
 * checkboxes inert, panel can't be opened. The JS toggles this
 * class live on `stats-visibility:changed`.
 * ================================================================== */

.stats-audience-dropdown {
	position: relative;
	display: inline-block;
	margin: 6px 0 0 15px;       /* aligns under .stats-tab-title indent */
	font-size: 13px;
	font-family: inherit;
	color: #1f2937;
	vertical-align: middle;
}

.stats-audience-trigger {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 12px;
	background: #ffffff;
	border: 1px solid #d1d5db;
	border-radius: 6px;
	font-family: inherit;
	font-size: 13px;
	font-weight: 500;
	color: #374151;
	cursor: pointer;
	transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
	min-height: 32px;
	line-height: 1.2;
}
.stats-audience-trigger:hover,
.stats-audience-trigger:focus {
	border-color: #9ca3af;
	background: #f9fafb;
	outline: none;
}
.stats-audience-trigger-caret {
	font-size: 11px;
	opacity: 0.7;
	margin-left: 2px;
}

/* Disabled state — private mode locks the dropdown. */
.stats-audience-dropdown.is-disabled .stats-audience-trigger,
.stats-audience-trigger[disabled] {
	background: #f3f4f6;
	color: #9ca3af;
	border-color: #e5e7eb;
	cursor: not-allowed;
	pointer-events: none;
}
.stats-audience-dropdown.is-disabled .stats-audience-trigger-caret {
	opacity: 0.4;
}

/* Panel — popup with the checkbox list. */
.stats-audience-panel {
	position: absolute;
	top: calc( 100% + 6px );
	left: 0;
	min-width: 200px;
	max-width: 300px;
	background: #ffffff;
	background-clip: border-box;
	border: 1px solid #e5e7eb;
	border-radius: 8px;
	box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.08 ), 0 8px 24px rgba( 17, 24, 39, 0.12 );
	z-index: 100;
	padding: 8px 0;
	margin: 0;
}
.stats-audience-panel[hidden] {
	display: none !important;
}

.stats-audience-options {
	list-style: none;
	margin: 0;
	padding: 0;
}

.stats-audience-option {
	margin: 0;
	padding: 0;
}

.stats-audience-option label {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 14px;
	cursor: pointer;
	font-size: 13px;
	color: #1f2937;
	transition: background-color 80ms ease;
}
.stats-audience-option label:hover {
	background: #f3f4f6;
}

.stats-audience-option input[type="checkbox"] {
	margin: 0;
	width: 16px;
	height: 16px;
	flex: 0 0 16px;
	accent-color: #7db04a;
	cursor: pointer;
}

.stats-audience-option.is-locked label {
	cursor: default;
}
.stats-audience-option.is-locked input[type="checkbox"] {
	cursor: not-allowed;
	opacity: 0.85;
}
.stats-audience-option.is-locked .stats-audience-label {
	color: #4b5563;
	font-weight: 500;
}

/* Disabled state propagates inside the panel — every label fades. */
.stats-audience-dropdown.is-disabled .stats-audience-option label,
.stats-audience-dropdown.is-disabled .stats-audience-option input[type="checkbox"] {
	cursor: not-allowed;
	color: #9ca3af;
	opacity: 0.7;
}

/* Mobile — keep the dropdown legible on narrower headers. */
@media ( max-width: 520px ) {
	.stats-audience-dropdown {
		display: block;
		margin: 8px 0 0;
	}
	.stats-audience-panel {
		min-width: 100%;
		max-width: 100%;
	}
}


/* ==================================================================
 * 10. Stats tab header — title + dropdown on one line (1.6.0)
 *
 * The "Profile Stats" heading and the "Your Stats Visibility"
 * dropdown now share a single horizontal row via a flex container.
 * On narrow viewports the dropdown wraps below the heading.
 *
 * Implementation notes:
 *
 *   - `.stats-tab-title-row` carries the flex. align-items: baseline
 *     puts the dropdown's text on the same baseline as the heading's
 *     icon-flanked text, which reads as a single line of
 *     information rather than a heading + drifting widget.
 *
 *   - The `margin-left: 15px !important` and `margin-top: 30px !important`
 *     rules on .stats-tab-title (set in §3 per the original spec)
 *     still apply — they push the row down + indent the heading
 *     from the left edge of the panel.
 *
 *   - The dropdown's own `margin: 6px 0 0 15px` from §9 would push
 *     it out of alignment with the heading inside this flex row,
 *     so we zero it inside `.stats-tab-title-row` and let `gap`
 *     handle the spacing instead.
 * ================================================================== */

.stats-tab-title-row {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 14px;
}

.stats-tab-title-row .stats-tab-title {
	margin: 30px 0 0 15px !important;  /* preserve spec margins, drop bottom indent */
}

.stats-tab-title-row .stats-audience-dropdown {
	/* Reset the standalone-context margin from §9; gap on the
	 * flex row handles spacing now. The dropdown stays vertically
	 * aligned with the heading's baseline. */
	margin: 30px 0 0 0;
}

@media ( max-width: 520px ) {
	.stats-tab-title-row {
		gap: 6px;
	}
	.stats-tab-title-row .stats-audience-dropdown {
		/* On mobile the dropdown wraps to its own line — undo the
		 * top margin so it sits snug under the heading. */
		margin: 4px 0 0 15px;
	}
}


/* ==================================================================
 * 11. Audience-panel "Update Filter" button (1.6.2)
 *
 * The button has no persistence role — every checkbox change
 * autosaves via stats-audience.js. Its only job is to close the
 * panel as a finished-editing affordance, so the user has a
 * deliberate "I'm done" moment that confirms their edits landed.
 *
 * Visual treatment:
 *   - Sits in a footer strip below the checkbox list, divided by a
 *     thin top rule so the panel reads as "list + action".
 *   - Full-width inside the panel padding, matching the green
 *     accent the plugin uses for affirmative actions (same
 *     #7db04a / #6a9d3c on hover that the confirmation modal's
 *     Agree button uses, for design-system consistency).
 *   - Pill-rounded edges (border-radius: 25px) to match the
 *     Cancel/Agree buttons in the visibility-mode modal.
 * ================================================================== */

.stats-audience-panel-footer {
	margin: 6px 0 0;
	padding: 8px 10px 4px;
	border-top: 1px solid #f3f4f6;
}

.stats-audience-update {
	appearance: none;
	-webkit-appearance: none;
	display: block;
	width: 100%;
	padding: 7px 14px;
	background: #7db04a;
	color: #ffffff;
	border: 1px solid #16a34a;
	border-radius: 25px;
	font-family: inherit;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	cursor: pointer;
	text-align: center;
	transition: background-color 120ms ease, border-color 120ms ease;
}
.stats-audience-update:hover,
.stats-audience-update:focus {
	background: #6a9d3c;
	border-color: #138a3f;
	outline: none;
}

/* 1.6.3 — explicit negative top margin per spec. Pulls the button
 * up by 7px so it sits closer to the footer divider rule, undoing
 * the breathing room the .stats-audience-panel-footer padding-top
 * (8px) introduces. !important guards against the theme stack's
 * generic `button { margin: 0 }` resets that GP themes often
 * include with high specificity.
 *
 * Element-tag prefix (`button.`) ratchets the selector specificity
 * one above the class-only rule above so a CSS bundler that
 * sorts rules into a non-source order still resolves this last. */
button.stats-audience-update {
	margin: -7px auto 0 auto !important;
}

/* Private-mode lockdown carries through the footer too — same fade
 * the rest of the panel's controls pick up so the button doesn't
 * look like a live action while the dropdown is inert. */
.stats-audience-dropdown.is-disabled .stats-audience-update {
	background: #e5e7eb;
	color: #9ca3af;
	border-color: #e5e7eb;
	cursor: not-allowed;
	pointer-events: none;
}
