/* ============================================================
   RoleGrader — Aggregated screen styles
   Design tokens per DESIGN_SYSTEM.md. Mobile-first: base rules
   target the 390px Figma mobile frame; @media (min-width: 1024px)
   holds the 1440px desktop overrides.

   Component A (includes/rg-nav-bar.php) aliases its own --rg-ca-*
   tokens to the --color-* tokens declared below, so both stay in
   sync with a single source of truth. Component A's inline <style>
   is printed on wp_head at priority 5 (before this stylesheet's
   <link> tag), but that only affects output order, not var()
   resolution — both are parsed into the CSSOM before first paint.
   ============================================================ */

:root {
  /* Paired with the <meta name="color-scheme" content="light"> tag
     (rolegrader-plugin.php) — same "don't auto-dark-mode this" signal,
     for native form controls/scrollbars specifically rather than page
     content. See that tag's comment for why this exists: a browser's
     forced-dark heuristic was making the header's icons effectively
     invisible on Brave for Android while "successfully" but wrongly
     recoloring the rest of the page on other browsers. */
  color-scheme: light;

  /* Colors — palette loosely inspired by Strelitzia reginae (Bird of
     Paradise): blue-green leaves (primary), a deep plum spathe (crown,
     new family below), vivid orange sepals (accent/CTA), indigo-violet
     petals (the profile-header gradient's own deep purple). Refined
     2026-09 for more saturation/contrast than the original muted values —
     a design system should read as one deliberate story, not several
     unrelated pretty gradients. */
  --color-primary: #3d8177;
  --color-primary-dark: #1f4d48;
  --color-primary-light: #DCEEF5;

  /* Crown — the flower's plum-purple spathe. New first-class family (was
     previously only baked as raw hex into the profile-header gradient with
     no reusable token); gives secondary UI moments (badges, focus states,
     alternate emphasis) a real home in the palette instead of defaulting
     back to teal or orange every time. */
  --color-crown: #5c3d6e;
  --color-crown-dark: #3a2547;
  --color-crown-light: #c9b3d6;

  /* Accent — the flower's vivid sepal-orange. Brightened from the original
     muted/brown trio so it reads as a genuine complementary focal color
     (per Gestalt invariance: the one warm, saturated note in an otherwise
     cool palette) rather than a decorative afterthought. --color-accent-mid
     doubles as the primary CTA color — see .btn-primary. */
  --color-accent-start: #c2410c;
  --color-accent-mid: #f2650a;
  --color-accent-end: #fda61a;
  --color-text-primary: #111827;
  --color-text-muted: #323334;
  --color-border: #E5E7EB;
  --color-white: #FFFFFF;
  --color-black: #000000;
  /* Was a pure neon-lime #6dea2a — unambiguously "online" but read as a
     random default rather than a considered part of the palette. Shifted
     to a softer, more modern green in the same spirit as the rest of the
     refined tokens; still reads as clearly green/positive at a glance. */
  --color-online: #4ade80;

  /* BuddyX / BP-Nouveau accent override — the theme's default #ef5455 "red"
     shows through on still-native chrome (group-creation wizard, invite
     result cards rendered by BP's own JS). Redefining the theme's own custom
     properties here (rather than fighting individual selectors) recolors all
     of it to our teal in one place. --color-theme-red is left alone — that's
     a genuine danger/error color, not the accent, and matches our own
     .btn-danger use for destructive actions.

     These are literal hex, not var(--color-primary) — kept in sync by hand.
     Palette-editor updates to --color-primary need to touch these too. */
  --color-theme-primary: #3d8177 !important;
  --color-theme-loader: #3d8177 !important;
  --color-link-hover: #3d8177 !important;
  --color-link-active: #1f4d48 !important;
  --button-background-color: #3d8177 !important;
  --button-background-hover-color: #1f4d48 !important;
  --button-border-color: #3d8177 !important;
  --button-border-hover-color: #1f4d48 !important;
  --color-footer-link-hover: #3d8177 !important;
  --color-copyright-link-hover: #3d8177 !important;

  /* Typography */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-size-display: 32px;
  --font-size-h1: 28px;
  --font-size-h2: 24px;
  --font-size-h3: 20px;
  --font-size-lg: 16px;
  --font-size-base: 14px;
  --font-size-sm: 12px;
  --font-size-label: 12px;

  /* Spacing */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  --spacing-2xl: 48px;

  /* Border Radius */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 18px;
  --radius-full: 9999px;

  /* Shadows — two-layer "contact + ambient" technique (a tight, low-opacity
     shadow close to the element plus a broader, softer one further out)
     reads as a genuinely lifted surface rather than a flat drop-shadow.
     Tinted toward the palette's dark teal-navy (#0b1f26) instead of pure
     black so shadows feel like part of this specific design, not a
     generic default. */
  --shadow-sm: 0 1px 2px rgba(11, 31, 38, 0.06), 0 1px 1px rgba(11, 31, 38, 0.04);
  --shadow-md: 0 4px 10px rgba(11, 31, 38, 0.1), 0 2px 4px rgba(11, 31, 38, 0.06);
  --shadow-lg: 0 12px 28px rgba(11, 31, 38, 0.16), 0 4px 8px rgba(11, 31, 38, 0.08);

  /* Transitions */
  --transition-base: 0.2s ease-in-out;
  --transition-slow: 0.3s ease-in-out;
}

/* Desktop density rescale (2026-10) — the type/spacing/radius tokens above
   are the mobile-first base, tuned against the 390px Figma mobile frame
   (see this file's header comment) and used as-is at every width, desktop
   included. That's fine on a phone held close to the eye, but on an actual
   desktop monitor it reads as oversized — reported as "the site only looks
   right zoomed out to ~67-75%" — because nothing shrinks these mobile-sized
   values back down for a desktop viewing distance/density. This block is
   that missing desktop-only step, at the same ~0.72 ratio the reported
   zoom level implies, so desktop gets the equivalent of that zoom baked in
   natively instead of relying on every visitor finding it by hand.
   Deliberately only the :root tokens — not layout, not the <1024px rules
   above — so mobile (already reported as rendering correctly) is
   untouched; every component below inherits this automatically through
   the var(--font-size-*)/var(--spacing-*)/var(--radius-*) references
   already used almost everywhere in this file, rather than needing its
   own per-component override.
   --font-size-base lands at 10px here — small on paper, but it's the same
   rendered size the reported 67-75% zoom already produced from the 14px
   base, i.e. already visually approved; revisit this one value first if
   desktop body text ends up feeling too small in practice. */
@media (min-width: 1024px) {
  :root {
    --font-size-display: 23px;
    --font-size-h1: 20px;
    --font-size-h2: 17px;
    --font-size-h3: 14px;
    --font-size-lg: 12px;
    --font-size-base: 10px;
    --font-size-sm: 9px;
    --font-size-label: 9px;

    --spacing-xs: 3px;
    --spacing-sm: 6px;
    --spacing-md: 12px;
    --spacing-lg: 17px;
    --spacing-xl: 23px;
    --spacing-2xl: 35px;

    --radius-sm: 3px;
    --radius-md: 6px;
    --radius-lg: 9px;
    --radius-xl: 13px;
  }
}

/* ── Shared components (buttons, cards, icons) ─────────────── */

/* Base for the inline-SVG edit-affordance icons (camera/pencil) rendered by
   rolegraderplugin_icon_camera()/rolegraderplugin_icon_edit() in
   includes/templates/rg-shared-panels.php. These replaced WordPress's
   "dashicons" icon font, which — like BuddyX's own Font Awesome header
   icons (see rg-nav-bar.php) — was found to silently fail to render on
   Brave/Android. Per-button width/height are set by each button's own
   ".rg-icon-svg" rule below; this just fixes stroke behavior so the SVG
   always inherits its wrapper's currentColor rather than needing per-icon
   color overrides. */
.rg-icon-svg {
  display: block;
  stroke: currentColor;
  flex-shrink: 0;
}

.card {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-lg);
  box-shadow: var(--shadow-sm);
}

/* Content-card gradient scheme — applied to each screen's main content
   card. Border/radius match .card; the gradient itself was retuned from a
   generic blue-to-gray into a genuine teal-to-plum story that ties directly
   to --color-crown, so this card visually relates to the profile header's
   crown-purple gradient instead of introducing an unrelated third hue pair.

   2026-10: the "contrast call still holds" claim this comment used to make
   was never actually verified against WCAG's formula and didn't — measured
   against var(--color-text-primary), the original stops (#2a7a6c / #6b5478)
   were 3.46:1 and 2.67:1, both below the 4.5:1 AA threshold for body text,
   and plenty of native BuddyPress content inside this card (settings
   tables, plain <label>/<dt>/<li> text) was never caught by the color
   override below at all and inherited the theme's base gray (#505050) —
   1.57:1 / 1.22:1, essentially illegible. Both stops lightened (same hue
   and saturation, +16 lightness) to #3fb7a2 / #947ba3, which clears AA at
   both ends with margin (7.19:1 / 4.75:1) — confirmed by computing the real
   contrast ratio, not eyeballing it. The `color` declaration below is new
   too: previously only p/.description/.bp-description/.info were
   force-colored (see removed comment), which is how the settings
   tables/labels/lists above fell through; setting it once on the card
   itself is inherited by everything in it unless something more specific
   (a badge, a link color) already overrides it. */
.rg-card-gradient {
  background: linear-gradient(180deg, #3fb7a2 0%, #947ba3 100%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--spacing-lg);
  color: var(--color-text-primary);
}

/* Profile page's "About" card — was its own distinct gradient (darker,
   cyan-accented, #1b5569 -> #adf0f8), which read as a contrast mismatch
   against the Roles card below it. Reusing .rg-card-gradient's exact
   gradient instead (2026-10, user-requested) so both cards on the Profile
   page read as the same surface — a deliberate deviation from Figma's
   node 58:769, not drift; see FIGMA_STATE/profile-desktop.json's note on
   this node before "fixing" it back via figma-sync. */
.rg-card-gradient-about {
  background: linear-gradient(180deg, #3fb7a2 0%, #947ba3 100%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: var(--radius-lg);
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
  /* Explicit, matching .rg-card-gradient's own declaration for the same
     gradient (verified 7.19:1/4.75:1 against its two stops) — not relying
     on inheritance now that this card shares that gradient. */
  color: var(--color-text-primary);
}

/* Native BP "helper text" (Settings' .info/.description paragraphs,
   empty-state notices, etc.) ships with its own muted gray from
   BuddyX/BP-Nouveau core, sized for a plain white card — unreadable
   against this gradient's darker/gray tones. Force it to the same
   dark text used for everything else on this card. */
.rg-card-gradient p,
.rg-card-gradient .description,
.rg-card-gradient .bp-description,
.rg-card-gradient .info {
  color: var(--color-text-primary);
}

/* ── Rounded-corner fix for every <div>-based card/box ──────────────────
   BP-Nouveau/BuddyX ships its own reset — "body #buddypress div, ...li,
   select, textarea { border-radius: 2px; ... }" — scoped with an ID, so
   its specificity (1,0,2) beats every single-class selector above no
   matter what radius that class declares. The only reason .card/
   .rg-card-gradient/.rg-card-gradient-about (e.g. the "About" card) render
   correctly is that they're all applied to <section> elements, which that
   reset's tag list doesn't include — every one of the classes below is a
   <div>, sitting inside #buddypress, so it silently rendered at a flat 2px
   regardless of the --radius-* value it declared, until now. Confirmed via
   Chrome DevTools' matched-styles inspection, not guessed. !important is
   the same pattern already used elsewhere in this file for this exact
   category of theme-reset fight (e.g. .rg-profile-page .btn-primary). */
.rg-panel-d-ad,
.rg-panel-d-map,
.rg-location-modal,
.rg-team-card,
.rg-projects-list,
.rg-notifications-card,
.rg-feedback-history-item,
.rg-auth-card,
/* Teams/Projects/Members-directory/etc.'s equivalent of the Profile page's
   main card — same .rg-card-gradient class, but applied to a <div> on
   these screens instead of a <section> like Profile uses, so it needed
   its own entry here even though the class itself already declares the
   right radius. */
.rg-content-wrap,
.rg-team-members-grid .list-wrap {
  border-radius: var(--radius-lg) !important;
}

/* Same fix, smaller --radius-md cards/panels (a notch down from the
   --radius-lg group above, matching what each already declares). */
.rg-member-roles-compact,
.rg-rating-card,
.rg-member-search-results,
.bp-feedback {
  border-radius: var(--radius-md) !important;
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
  background: transparent;
  color: var(--color-primary);
  border: 1px solid var(--color-primary);
  padding: 8px var(--spacing-md);
  font: 600 var(--font-size-base) var(--font-sans);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--transition-base), color var(--transition-base);
}

.btn-secondary:hover {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

/* Primary CTA uses the accent (sepal-orange), not the primary teal — a
   button that's the same family as its own card background has no real
   focal point (Gestalt invariance). The book's own color-theory chapter
   makes this exact recommendation: pick a complementary color for CTAs so
   the one action that matters actually stands out. */
.btn-primary {
  display: inline-block;
  background: var(--color-accent-mid);
  color: var(--color-white);
  border: none;
  padding: 10px var(--spacing-md);
  font: 600 var(--font-size-base) var(--font-sans);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}

.btn-primary:hover {
  background: var(--color-accent-start);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.btn-primary:active {
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

.btn-danger {
  display: inline-block;
  background: #cf6767;
  color: var(--color-white);
  border: none;
  padding: 10px var(--spacing-md);
  font: 600 var(--font-size-base) var(--font-sans);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--transition-base);
}

.btn-danger:hover {
  background: #B52A39;
}

/* BP Nouveau core's ".buddypress .buddypress-wrap button" reset (0,2,1)
   beats a bare ".btn-primary"/".btn-danger" (0,1,0) for real <button>/
   <input type=submit> elements — same specificity fight documented
   below for .rg-project-save-btn etc. This is the rule that actually wins
   for every real .btn-primary button/input inside .rg-profile-page (i.e.
   nearly everywhere), so it needs to carry the same accent-orange CTA
   color as the base .btn-primary rule above — it was still teal from
   before that color was introduced, silently reverting every button that
   matched it (caught via "Create New Team" rendering teal despite
   .btn-primary + its own !important background both saying orange). */
.rg-profile-page .btn-primary {
  background: var(--color-accent-mid) !important;
  color: var(--color-white) !important;
  border: none !important;
}

.rg-profile-page .btn-primary:hover {
  background: var(--color-accent-start) !important;
}

.rg-profile-page .btn-danger {
  background: #cf6767 !important;
  color: var(--color-white) !important;
  border: none !important;
}

.rg-profile-page .btn-danger:hover {
  background: #B52A39 !important;
}

.icon {
  display: inline-block;
  line-height: 1;
}

.icon-16 { font-size: 16px; width: 16px; height: 16px; }
.icon-20 { font-size: 20px; width: 20px; height: 20px; }

/* ============================================================
   Profile Page (includes/templates/page-profile.php)
   ============================================================ */

.rg-profile-page {
  /* Break out of BuddyX's stacked container paddings (.container + BP's own
     #item-body each add their own side padding, ~15px apiece) so Panel_B/
     Panel_C/Panel_D reach the true viewport edges — matching Component A,
     which sits outside that wrapper chain, and matching every Figma frame
     (Panel_B/Panel_C/Panel_D are always x=0 / full frame width there, never
     inset from an outer "container"). Viewport-relative, so it holds
     regardless of how many ancestor paddings BuddyX stacks on, now or later. */
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  /* Same breakout logic, vertically: BuddyX's .site-wrapper (32px
     margin-top) + BP core's #item-body (15px padding-top) + a 1px border
     on .bp-wrap leave a 48px light gap between the nav bar and the cover
     photo, breaking the seamless dark page (visible as a stray pale strip
     — caught during a visual design pass). Pull it up to close the gap,
     same spirit as the horizontal breakout above. */
  margin-top: -48px;
  /* Figma's outer frame (every Panel-C screen) fills the full canvas with
     this dark teal — matches .rg-auth-page/.rg-project-single-page's own
     color exactly. Without it, BuddyX's default #f7f7f9 body background
     shows through around the panels and below short content. */
  background: #071f29;
}

.rg-profile-cover {
  position: relative;
  height: 120px;
  background: linear-gradient(129.59deg, #2a7575 0%, #9bcfc3 67.7%);
}

.rg-profile-cover-edit-btn {
  position: absolute;
  top: var(--spacing-sm);
  right: var(--spacing-sm);
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  color: var(--color-white);
  border-radius: var(--radius-full);
  text-decoration: none;
  transition: background var(--transition-base);
}

.rg-profile-cover-edit-btn:hover {
  background: rgba(0, 0, 0, 0.65);
}

.rg-profile-cover-edit-btn .rg-icon-svg {
  width: 18px;
  height: 18px;
}

.rg-profile-cover-image {
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
}

.rg-profile-accent-line {
  height: 4px;
  background: linear-gradient(90deg, var(--color-accent-start) 0%, var(--color-accent-mid) 20%, var(--color-accent-mid) 60%, var(--color-accent-end) 100%);
}

.rg-profile-header {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--spacing-sm);
  /* Bottom padding was --spacing-lg (24px) — trimmed to --spacing-md so
     this section (and the cover photo above it, since less of the avatar
     needs to sit inside this box once it overlaps the cover more — see
     .rg-profile-avatar's margin-top just below) takes up less of a small
     mobile screen, leaving more of the actual cover photo visible above
     it. Desktop keeps its own separate padding at the 1024px breakpoint
     below, untouched. */
  padding: 0 var(--spacing-md) var(--spacing-md);
  /* Retuned to the crown-purple family (see :root) so the name strip
     visually relates to the Roles card's gradient below it and to
     --color-crown used elsewhere, instead of introducing its own
     unrelated blue-violet. */
  background: linear-gradient(180deg, #b89bc9 0%, #6d4f82 100%);
}

.rg-profile-avatar {
  position: relative;
  display: inline-block;
  /* Was -60px (avatar is 120px tall, so exactly half sat inside
     .rg-profile-header's own box, the other half overlapping the 120px-
     tall cover photo above). Pulling it up further so more of the same
     120px avatar overlaps the cover instead — same avatar, same visible
     size, just less of it counted toward this section's own height,
     directly shortening the purple box without shrinking the avatar or
     cropping the cover photo (120px cover has enough headroom for an
     85px overlap). Desktop's own -80px override at the 1024px breakpoint
     is untouched — this is the mobile value only. */
  margin-top: -85px;
}

.rg-profile-avatar img {
  width: 120px;
  height: 120px;
  border-radius: var(--radius-full);
  border: 4px solid var(--color-white);
  box-shadow: var(--shadow-md);
  object-fit: cover;
}

/* Online-now indicator: the displayed user's (not the viewer's) border
   turns green when they were active in the last 5 minutes — see
   $is_online in rolegraderplugin_render_member_header(). Every Panel_B
   avatar rendition gets this for free since they all share this one
   template function; Component A's own small nav avatar is a separate
   render path (always the viewer's own avatar, always "online" while
   browsing) and deliberately isn't touched. */
.rg-profile-avatar.rg-avatar-online img {
  border-color: var(--color-online);
}

.rg-profile-avatar-edit-btn {
  position: absolute;
  bottom: 4px;
  right: 4px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-border);
  color: var(--color-text-primary);
  border: 2px solid var(--color-white);
  border-radius: var(--radius-full);
  text-decoration: none;
  transition: background var(--transition-base);
}

.rg-profile-avatar-edit-btn:hover {
  background: var(--color-primary-light);
}

.rg-profile-avatar-edit-btn .rg-icon-svg {
  width: 16px;
  height: 16px;
}

.rg-profile-name {
  font: 700 var(--font-size-h2) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0;
}

/* The theme's own heading rule gives this h1 24px top and bottom margins
   that beat the plain margin:0 above, which alone added ~48px of empty
   purple around the name on mobile — noticeably more purple than cover
   photo. Zeroed here for mobile only (desktop's row layout is untouched). */
@media (max-width: 1023px) {
  .rg-profile-header .rg-profile-name {
    margin: 0 0 2px !important;
  }
}

.rg-profile-last-seen {
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-muted);
  margin: 0;
}

.rg-profile-edit-btn {
  position: absolute;
  top: var(--spacing-md);
  right: var(--spacing-md);
  width: 44px;
  height: 44px;
  justify-content: center;
  border-radius: var(--radius-full);
}

.rg-profile-layout {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
  /* No horizontal padding — Panel_C/main/Panel_D sit flush to the now-full-
     width .rg-profile-page, matching Figma (they're always x=0 / flush to
     the frame edge there too; spacing between the three columns comes from
     this flex gap, not from an outer margin). Panel_C/Panel_D/card content
     each provide their own internal padding for breathing room. */
  padding: var(--spacing-lg) 0;
}

.rg-profile-main {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
  min-width: 0;
}

.rg-profile-card-header h2 {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-sm);
}

.rg-profile-card-body p {
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-muted);
  margin: 0;
}

.rg-profile-card-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--spacing-md);
}

.rg-edit-link {
  padding: var(--spacing-xs) var(--spacing-sm);
}

/* Icon-only pencil button for a card's bottom-right corner (About, Roles) —
   matches Figma's Button_Edit_About/Button_Edit_Roles (light-gray rounded
   square, pencil glyph, no visible label) rather than the left-aligned
   text-and-icon .rg-edit-link button these cards used before. */
.rg-card-edit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--color-border);
  color: var(--color-text-primary);
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--transition-base);
}

.rg-card-edit-btn:hover {
  background: var(--color-primary-light);
}

.rg-card-edit-btn .rg-icon-svg {
  width: 18px;
  height: 18px;
}

/* ── Edit Profile (buddypress/members/single/profile/edit.php override) ──
   Field-type-agnostic: BP's own dynamic xprofile fields (textbox,
   textarea, selectbox, radio, checkbox, datebox, ...) render untouched;
   these rules target generic element types/BP's own stable classes
   rather than trying to enumerate every field-type template. */

.rg-profile-edit-heading {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-md);
}

.rg-profile-edit-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-xs);
  list-style: none;
  margin: 0 0 var(--spacing-md);
  padding: 0;
  border-bottom: 1px solid var(--color-border);
  padding-bottom: var(--spacing-sm);
}

.rg-profile-edit-tabs a {
  display: inline-block;
  background: #F2F2F2;
  color: #4D4D4D;
  border-radius: var(--radius-sm);
  padding: 8px var(--spacing-md);
  font: 700 var(--font-size-sm) var(--font-sans);
  text-decoration: none;
}

.rg-profile-edit-tabs li.selected a,
.rg-profile-edit-tabs a.selected {
  background: var(--color-primary);
  color: var(--color-white);
}

.rg-profile-edit-group-title {
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-md);
}

.rg-profile-edit-field {
  margin: 0 0 var(--spacing-lg);
  padding-bottom: var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
}

.rg-profile-edit-field:last-of-type {
  border-bottom: none;
  padding-bottom: 0;
}

.rg-profile-edit-field fieldset {
  border: none;
  margin: 0;
  padding: 0;
}

.rg-profile-edit-field legend,
.rg-profile-edit-field > fieldset > label:first-child {
  display: block;
  font: 600 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-xs);
}

.rg-profile-edit-field input[type="text"],
.rg-profile-edit-field input[type="email"],
.rg-profile-edit-field input[type="url"],
.rg-profile-edit-field input[type="number"],
.rg-profile-edit-field input[type="tel"],
.rg-profile-edit-field textarea,
.rg-profile-edit-field select {
  width: 100%;
  max-width: 480px;
  padding: 8px var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  background: var(--color-white);
  box-sizing: border-box;
}

.rg-profile-edit-field textarea {
  max-width: 100%;
  resize: vertical;
}

.rg-profile-edit-field input[type="radio"],
.rg-profile-edit-field input[type="checkbox"] {
  accent-color: var(--color-primary);
  margin-right: var(--spacing-xs);
}

.rg-profile-edit-field .radio label,
.rg-profile-edit-field .checkbox label {
  display: block;
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-xs);
}

.field-visibility-settings-header {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: var(--spacing-sm) 0 0;
}

.field-visibility-settings-header .current-visibility-level {
  font-weight: 600;
  color: var(--color-text-primary);
}

.field-visibility-settings-header .text-button {
  background: none;
  border: none;
  color: var(--color-primary);
  font: 600 var(--font-size-sm) var(--font-sans);
  cursor: pointer;
  padding: 0 0 0 var(--spacing-xs);
}

.field-visibility-settings {
  margin-top: var(--spacing-sm);
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--color-primary-light);
  border-radius: var(--radius-md);
}

.rg-profile-edit-actions {
  margin-top: var(--spacing-lg);
}

.rg-profile-page .rg-profile-edit-actions button,
.rg-profile-page .rg-profile-edit-actions input[type="submit"] {
  background: var(--color-primary) !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 10px var(--spacing-lg);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-base) var(--font-sans);
  cursor: pointer;
}

/* ── Panel C: left profile nav (touch target 44px) ─────────── */

.rg-panel-c {
  display: flex;
  flex-direction: row;
  overflow-x: auto;
  background: #0b3540;
  /* Was var(--color-border) — a light gray outline that read as inconsistent
     against every content card's near-invisible dark border (similarity
     principle: visually equivalent containers should share a treatment). */
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.rg-panel-c-link {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: var(--spacing-md);
  flex: 1 0 auto;
  font: 700 var(--font-size-lg) var(--font-sans);
  color: var(--color-white);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--transition-base), color var(--transition-base);
}

/* "Viewing {Name}" — only rendered when Panel_C's links point at someone
   else's Profile/Teams/Projects instead of your own (see the "these links
   are deliberately contextual" comment in rolegraderplugin_render_panel_c()).
   Muted/small so it reads as a label, not another link — the links below
   it are still the visually dominant element. No display rule needed here:
   this renders in two places (the desktop sidebar .rg-panel-c and the
   mobile .rg-mobile-nav-dropdown), and both of those containers already
   fully control their own mobile-vs-desktop visibility — this label just
   inherits whichever one is currently shown. */
.rg-panel-c-viewing {
  margin: 0;
  font: 600 var(--font-size-sm) var(--font-sans);
  color: rgba(255, 255, 255, 0.6);
  white-space: nowrap;
}

.rg-panel-c-viewing strong {
  color: var(--color-white);
}

/* Desktop sidebar context — sits above the stacked links, same horizontal
   inset as each link's own padding so the label's edge lines up with the
   link text, not the link's full-width hit area. */
.rg-panel-c .rg-panel-c-viewing {
  padding: var(--spacing-sm) var(--spacing-md) 0;
}

/* Mobile dropdown context — matches .rg-mobile-nav-dropdown-link's own
   horizontal padding/divider convention so it reads as part of the same
   list, not a visually separate block. */
.rg-mobile-nav-dropdown .rg-panel-c-viewing {
  padding: var(--spacing-md) var(--spacing-lg) var(--spacing-sm);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.rg-panel-c-link:hover {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.rg-panel-c-link.active {
  background: var(--color-primary);
  color: var(--color-white);
}

/* ── Mobile nav: hamburger + dropdown (replaces Panel C below 1024px) ──
   Matches Figma's mobile frames (e.g. Profile_page_Mobile): a hamburger
   icon overlaid top-left on the cover photo toggles a full-width dropdown
   with the same Profile/Teams/Projects links Panel_C shows on desktop.
   .rg-panel-c itself is hidden here and restored at the 1024px breakpoint
   below, where these two are hidden instead — see rg-shared-panels.php's
   rolegraderplugin_render_panel_c() for why both are always rendered. */
.rg-panel-c {
  display: none;
}

/* !important throughout: BP-Nouveau's own native-<button> reset
   (".buddypress .buddypress-wrap button", specificity 0,2,7 — it also
   covers several link/button classes in the same rule) beats this
   single-class selector (0,1,0) and was silently overwriting nearly
   everything below — background (white instead of the intended
   translucent-black circle), border-radius (flattened to 0, not even the
   2px the plain <div> reset elsewhere in this file produces — this is a
   different, more aggressive rule), border, color, and padding/width
   (its own padding:.3em .5em plus width:auto were also quietly resizing
   the button off the intended 36px square). Confirmed via Chrome
   DevTools' matched-styles inspection, not guessed. */
.rg-mobile-nav-toggle {
  /* .rg-profile-cover is position:relative — nested inside it (see
     rolegraderplugin_render_mobile_nav_toggle()) so this anchors correctly
     without guessing header height, same technique as
     .rg-profile-cover-edit-btn's mirror-image right-side placement. */
  position: absolute !important;
  top: var(--spacing-sm) !important;
  left: var(--spacing-sm) !important;
  z-index: 5 !important;
  width: 36px !important;
  height: 36px !important;
  padding: 0 !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  background: rgba(0, 0, 0, 0.45) !important;
  color: var(--color-white) !important;
  border: none !important;
  border-radius: var(--radius-full) !important;
  cursor: pointer !important;
}

.rg-mobile-nav-dropdown {
  display: none;
  position: fixed;
  /* top is set inline by JS on open, to the real rendered header height
     (varies — the wp-admin toolbar adds ~46px for logged-in staff, etc.);
     0 here is just a sane pre-JS fallback. */
  top: 0;
  left: 0;
  right: 0;
  z-index: 99980;
  flex-direction: column;
  background: #0b3540;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
  /* Only the bottom two corners — this panel is edge-to-edge (left:0;
     right:0) and sits flush against the header above it, so top corners
     would never be visible even rounded (nothing but more header there to
     reveal the curve against); the bottom edge is the one actually
     floating over the page content below it. overflow:hidden clips the
     last link's own background (its :hover/.active states paint a solid
     fill) to that curve instead of it squaring off past the radius.
     !important: same BP-Nouveau/BuddyX <div> reset as the consolidated
     fix near the top of this file — this is a <div>, and a 4-value
     border-radius isn't a fit for that shared block, so it gets its own
     override here instead. */
  border-radius: 0 0 var(--radius-lg) var(--radius-lg) !important;
  overflow: hidden;
}

.rg-mobile-nav-dropdown.open {
  display: flex;
}

.rg-mobile-nav-dropdown-link {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: var(--spacing-md) var(--spacing-lg);
  font: 700 var(--font-size-lg) var(--font-sans);
  color: var(--color-white);
  text-decoration: none;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  transition: background var(--transition-base), color var(--transition-base);
}

.rg-mobile-nav-dropdown-link:hover {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.rg-mobile-nav-dropdown-link.active {
  background: var(--color-primary);
  color: var(--color-white);
}

/* ── Panel D: ad slots + location placeholder ──────────────── */

.rg-panel-d {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

/* Mobile: Figma's mobile frame puts the map above the ad slot, but the DOM
   order (ad, map, ad — see rolegraderplugin_render_panel_d()) matches
   desktop's ad/map/ad stacking instead. Reordering visually via flex
   `order` avoids touching markup shared with desktop, which already
   matches Figma there. Restored to DOM order at the 1024px breakpoint. */
.rg-panel-d-map {
  order: -1;
}

/* Floating mobile ad banner — Figma's mobile frame called for this ad to
   float at the bottom of the screen rather than sit in normal page flow
   (where it was only ever seen after scrolling all the way down), but a
   floating element doesn't translate cleanly into a static Figma frame so
   it never made it into the build. position:fixed takes it out of flow
   entirely, so no markup change was needed to avoid leaving a gap where it
   used to sit. Reset back to normal in-flow placement at the 1024px
   breakpoint below — desktop's Figma frame never floated this. */
/* Edge-to-edge and flush with the true bottom of the viewport (only
   env(safe-area-inset-bottom) keeps it clear of a notch/home-indicator,
   not a design gap) — deliberately matching the width and flush edges
   of a normal in-flow .rg-panel-d-ad slot (e.g. a screen's second ad,
   where ad_count > 1) rather than floating as a smaller inset card, so
   it reads as "the bottom of the screen", not an overlay sitting on
   top of the page. */
.rg-panel-d-ad-wrap {
  position: fixed;
  left: 0;
  right: 0;
  bottom: env(safe-area-inset-bottom, 0px);
  z-index: 500;
}

.rg-panel-d-ad-wrap .rg-panel-d-ad {
  margin: 0;
  box-shadow: var(--shadow-lg);
  /* Half the normal 160px min-height — floating over content rather
     than sitting in a list of cards, so it stays compact even at full
     width. Flush corners (not the shared --radius-lg, and not even the
     smaller --radius-sm floating cards elsewhere use) are the point
     here: rounded corners on a bar that's meant to read as the edge of
     the screen itself would break that illusion. Reset to the shared
     card treatment at the 1024px breakpoint below, where it's back in
     normal in-flow layout. !important to beat the BuddyX <div>
     border-radius reset this class is already fought against above
     (.rg-panel-d-ad's own !important rule) — a plain declaration here
     would lose to that regardless of this selector's higher
     specificity. */
  min-height: 80px;
  border-radius: 0 !important;
}

/* The placeholder creative inside fully overlaps the card above at the
   same size (see .rg-ad-placeholder's own comment) — it needs the same
   flush-corner override, or its own rounding would peek out past the
   now-square card behind it. */
.rg-panel-d-ad-wrap .rg-ad-placeholder {
  border-radius: 0 !important;
}

.rg-panel-d-ad {
  background: #0b3540;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  min-height: 160px;
  width: 100%;
}

/* Placeholder creative rendered inside a Panel D ad slot until a real
   ad network/direct-sold banner replaces it (see CLAUDE.md) — a CSS
   class instead of inline styles specifically so it can follow the
   same mobile-floating-vs-desktop-in-flow sizing the wrapper above
   does; a real ad's own HTML/image won't have this problem since this
   is dev-only filler content. Matches the mobile floating banner's
   compact size by default; restored to the desktop card size at the
   1024px breakpoint below, alongside the rest of that reset. */
.rg-ad-placeholder {
  background: #002246;
  /* !important: same BuddyX <div> border-radius reset fight as
     .rg-panel-d-ad above — this div fully overlaps that card at the
     same size, so letting the reset win here would peek a sharper,
     mismatched corner out past the card's own rounding. */
  border-radius: var(--radius-sm) !important;
  min-height: 80px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-family: var(--font-sans);
  text-align: center;
  padding: var(--spacing-sm);
}

.rg-ad-placeholder strong {
  font-size: 13px;
}

.rg-ad-placeholder span {
  opacity: 0.75;
  font-size: 11px;
  margin-top: 4px;
}

/* Figma's mobile frames only ever show a single ad slot, regardless of how
   many a given screen's rolegraderplugin_render_panel_d( $ad_count ) call
   requests for desktop (Profile/Teams List/etc. all pass 2) — confirmed by
   checking every mobile frame's ad nodes directly in Figma: always exactly
   one "AdFrame1", never two. The general sibling selector hides every ad
   past the first regardless of what sits between them (e.g. the map div on
   Profile), so it doesn't care about ad_count or ordering. Restored at the
   1024px breakpoint below.
   Selector targets .rg-panel-d-ad-wrap, not .rg-panel-d-ad: the first ad
   is nested one level deeper inside that wrap div (for the floating-banner
   treatment above), so it's no longer a true sibling of a later
   .rg-panel-d-ad — a plain `.rg-panel-d-ad ~ .rg-panel-d-ad` silently
   stopped matching anything the moment that wrapper was introduced,
   letting a screen's second ad slot render in normal page flow on
   mobile too (confirmed live: Profile's Slot 2 was showing up after the
   Roles card, full-width, unhidden). */
.rg-panel-d-ad-wrap ~ .rg-panel-d-ad {
  display: none;
}

.rg-panel-d-map {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-md);
  text-align: center;
}

.rg-panel-d-map-label {
  font: 700 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-xs);
}

.rg-user-location-mini-map {
  height: 160px;
  width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
}

.rg-user-location-map-empty {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: 0;
}

/* Own-profile mini-map is clickable — opens the [rg_set_user_location]
   widget in a modal (replaces the old, unreachable "Location" profile tab). */
.rg-panel-d-map-editable {
  position: relative;
  cursor: pointer;
  transition: box-shadow var(--transition-base);
}

.rg-panel-d-map-editable:hover,
.rg-panel-d-map-editable:focus-visible {
  box-shadow: var(--shadow-md);
  outline: none;
}

.rg-panel-d-map-edit-btn {
  position: absolute;
  top: var(--spacing-sm);
  right: var(--spacing-sm);
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  color: var(--color-white);
  border-radius: var(--radius-full);
  pointer-events: none;
}

.rg-panel-d-map-edit-btn .rg-icon-svg {
  width: 15px;
  height: 15px;
}

/* Other-profile mini-map: clickable too, but opens a bigger read-only map
   (RG_User_Location_Map_Widget::get_expanded_map_html()) instead of the
   location-editing widget — the mini-map's own interaction is disabled so
   it doesn't fight page scroll, which made it hard to tell what it showed. */
.rg-panel-d-map-viewable {
  cursor: pointer;
  transition: box-shadow var(--transition-base);
}

.rg-panel-d-map-viewable:hover,
.rg-panel-d-map-viewable:focus-visible {
  box-shadow: var(--shadow-md);
  outline: none;
}

.rg-user-location-map-expanded-label {
  font: 700 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-sm);
  text-align: left;
}

.rg-user-location-map-expanded {
  height: 420px;
  width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
}

.rg-location-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: var(--spacing-md);
}

.rg-location-modal {
  position: relative;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  max-width: 900px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  padding: var(--spacing-lg);
}

.rg-location-modal-close {
  position: absolute;
  top: var(--spacing-md);
  right: var(--spacing-md);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-border);
  color: var(--color-text-primary);
  border: none;
  border-radius: var(--radius-full);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  z-index: 1;
}

.rg-location-modal-close:hover {
  background: var(--color-primary-light);
}

.rg-location-modal .rg-set-location-container {
  margin: 0;
  padding: 0;
  background: transparent;
  max-width: 100%;
}

/* ============================================================
   Teams List (includes/templates/page-teams-list.php)
   ============================================================ */

/* Mobile-first base: a 2-column grid, not the icon+copy+button flex row
   the desktop override below switches to — at 390px-ish widths, that row
   had to squeeze a heading, a full sentence, and a button into whatever
   space was left after the icon, so each wrapped into its own cramped
   little column instead of reading as one clear block (reported directly
   from a phone screenshot). The grid keeps the icon beside the heading —
   there's room for that pairing — while the paragraph and button each
   get their own full-width row below, where cramming them in would have
   caused the wrapping in the first place.
   .rg-teams-banner-copy is display:contents here so its own children
   (h2, p) become direct grid items of .rg-teams-banner, able to land in
   different grid rows independently — the desktop override turns that
   back off since the row layout needs h2+p kept together as one column. */
.rg-teams-banner {
  display: grid;
  grid-template-columns: 36px 1fr;
  column-gap: var(--spacing-sm);
  row-gap: var(--spacing-sm);
  background: var(--color-primary-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--spacing-md) var(--spacing-lg);
  border-left: 4px solid var(--color-primary);
}

.rg-teams-banner-icon {
  grid-column: 1;
  grid-row: 1;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
}

.rg-teams-banner-copy {
  display: contents;
}

.rg-teams-banner-copy h2 {
  grid-column: 2;
  grid-row: 1;
  align-self: center;
  font: 700 var(--font-size-lg) var(--font-sans);
  color: var(--color-primary);
  margin: 0;
}

.rg-teams-banner-copy p {
  grid-column: 1 / -1;
  grid-row: 2;
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: 0;
}

/* "Create New Team" is the one real page-level CTA here (unlike the
   repeated per-card Join/Leave actions, deliberately left teal so they
   don't compete with it), so it should get the same accent-orange focal
   treatment .btn-primary gives everywhere else. Needs !important: BuddyX's
   own theme CSS applies background-color: var(--button-background-color)
   !important to anchors/buttons generically (same fight already resolved
   for the Save/Add Role buttons in the Role Proficiency widget), which
   otherwise beats this rule regardless of source order. */
.rg-teams-create-btn {
  /* Full-width, its own grid row, on mobile (base) — see
     .rg-teams-banner's comment above; the desktop override below shrinks
     it back to an inline, right-sitting button once there's room for the
     row layout. */
  grid-column: 1 / -1;
  grid-row: 3;
  width: 100%;
  text-align: center;
  background: var(--color-accent-mid) !important;
  color: var(--color-white) !important;
  border: none;
  padding: 10px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-base) var(--font-sans);
  text-decoration: none;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}

.rg-teams-create-btn:hover {
  background: var(--color-accent-start) !important;
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

/* Desktop: back to the original icon+copy+button row — plenty of width
   here for all three side by side, so the mobile grid (above) would just
   waste vertical space. Switches .rg-teams-banner-copy's display back to
   block (undoing display:contents) so h2+p form one column again instead
   of landing in separate grid rows. */
@media (min-width: 1024px) {
  .rg-teams-banner {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-md);
  }

  .rg-teams-banner-icon {
    flex: 0 0 36px;
  }

  .rg-teams-banner-copy {
    display: block;
    width: auto;
    flex: 1 0 0;
  }

  .rg-teams-banner-copy h2 {
    margin: 0 0 var(--spacing-xs);
  }

  .rg-teams-create-btn {
    flex: 0 0 auto;
    align-self: center;
    width: auto;
  }
}

/* margin-top/-bottom here (not on the elements before/after it) is the
   general, reusable version of this spacing — see the matching comment
   on .rg-team-filters below, the same "sort control sits between a
   block above and a card grid below" pattern reused on the Team Page
   Members tab and the Members directory. */
.rg-teams-sort {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  margin-top: var(--spacing-lg);
  margin-bottom: var(--spacing-lg);
}

.rg-teams-sort label {
  font: 600 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

.rg-teams-sort select {
  padding: 6px var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  background: var(--color-white);
}

.rg-teams-grid {
  display: grid;
  /* The ~428-460px estimate this comment used to cite predates the
     "Wide-desktop container width" fix further down this file (body.
     buddypress .container widens to 1600px at 1400px+ viewports) — that
     fix already reaches this page, so the real column count at typical
     desktop widths is 3+, verified directly (three cards land in the same
     grid row at 1440px). 210px/spacing-lg gives each card a bit more room
     than the original 190px/spacing-md pairing now that cards carry real
     visual weight (cover gradient, shadow, hover lift) instead of being
     flat and cramped. auto-fit (not auto-fill) so a lone card expands to
     fill the row instead of being squeezed into a narrow column with
     empty phantom tracks beside it. */
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--spacing-lg);
}

/* Glass card floating on the section's own .rg-card-gradient backdrop —
   was flat white with a khaki cover band, which read as unstyled native
   BuddyPress output next to the rest of the (now) considered palette.
   Frosted rather than solid white so the gradient still shows through at
   the edges, tying it visually to the same backdrop-card language used on
   Profile's Roles/Role Proficiency cards. */
.rg-team-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  padding-bottom: var(--spacing-md);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.rg-team-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

/* Leaf-teal to crown-purple — was a flat khaki band with no relationship
   to the rest of the palette; this ties every card's cover into the same
   Strelitzia-inspired story as the profile header/Roles card gradients. */
/* Gradient is the fallback for a team with no cover image uploaded — real
   covers are set inline via style="background-image:..." in
   page-teams-list.php (bp_attachments_get_attachment()), same pattern as
   the member cover photos on Location Search's cards
   (.rg-user-result-banner in rg-get-user-locations-widget.php). */
.rg-team-card-cover {
  width: 100%;
  height: 72px;
  background: linear-gradient(120deg, var(--color-primary) 0%, var(--color-crown) 100%);
  background-size: cover;
  background-position: center;
}

.rg-team-card-avatar {
  display: block;
  margin-top: -28px;
}

.rg-team-card-avatar img {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-full);
  border: 3px solid var(--color-white);
  box-shadow: var(--shadow-sm);
  object-fit: cover;
}

.rg-team-card-name {
  display: block;
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  text-decoration: none;
  margin-top: var(--spacing-sm);
}

.rg-team-card-meta,
.rg-team-card-active {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: var(--spacing-xs) 0 0;
}

.rg-team-card-action {
  margin-top: var(--spacing-md);
}

.rg-team-card-action a,
.rg-team-card-action button {
  display: inline-block;
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  padding: 8px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-sm) var(--font-sans);
  text-decoration: none;
  cursor: pointer;
}

.rg-teams-pagination,
.rg-teams-empty {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

/* ============================================================
   Projects List (rg-buddypress.php's existing project-list markup,
   wrapped by includes/templates/page-projects-list.php)
   ============================================================ */

.rg-projects-create-wrap {
  margin-bottom: var(--spacing-md);
}

.rg-projects-create-btn {
  display: inline-block;
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  padding: 10px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-base) var(--font-sans);
  text-decoration: none;
}

.rg-projects-count {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-sm);
}

.rg-projects-list {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.rg-project-item {
  padding: var(--spacing-sm) var(--spacing-md);
  border-bottom: 1px solid var(--color-border);
}

.rg-project-item:last-child {
  border-bottom: none;
}

.rg-project-item-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--spacing-sm);
}

.rg-project-item-main {
  flex: 1 0 0;
  min-width: 0;
}

.rg-project-title {
  font: 700 var(--font-size-base) var(--font-sans);
  display: block;
}

.rg-project-title-link {
  color: #1A59A6;
  text-decoration: none;
}

.rg-project-title-link:hover {
  text-decoration: underline;
}

.rg-project-desc {
  color: var(--color-text-muted);
  font: 400 var(--font-size-sm) var(--font-sans);
  display: block;
  margin-top: 2px;
}

.rg-project-status-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  margin-top: var(--spacing-xs);
}

.rg-project-badge {
  display: inline-block;
  font: 500 10px var(--font-sans);
  padding: 2px 8px;
  border-radius: 3px;
}

.rg-project-badge-active {
  background: #FCE8D8;
  color: #B5541E;
}

.rg-project-badge-completed {
  background: #D9F0E3;
  color: #1F7A54;
}

.rg-project-badge-promoted {
  background: #FCE8D8;
  color: #B5541E;
}

/* Membership/trust badges (rg_render_member_badge() in rg-membership.php)
   — Supporter, Verified, and later Promoted. Same small-pill convention
   as .rg-project-badge above, sized and aligned for sitting inline next
   to a name (e.g. .rg-profile-name) rather than standalone on a card. */
.rg-badge {
  display: inline-block;
  vertical-align: middle;
  font: 600 11px var(--font-sans);
  padding: 2px 9px;
  border-radius: var(--radius-full);
  margin-left: var(--spacing-xs);
  white-space: nowrap;
}

.rg-badge-supporter {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.rg-badge-verified {
  background: #FCE8D8;
  color: #B5541E;
}

.rg-project-rating {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

.rg-project-view-btn {
  flex: 0 0 auto;
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  padding: 8px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-sm) var(--font-sans);
  text-decoration: none;
  white-space: nowrap;
}

/* ============================================================
   Role Proficiency & Role Display widgets (widgets/rg-role-proficiency-widget.php,
   widgets/rg-role-display-widget.php), rendered inside the Profile
   page's .rg-profile-roles card (includes/templates/page-profile.php).
   Both widgets print their own scoped <style> block by default;
   these classes replace that inline styling to match Figma.
   ============================================================ */

/* Side-by-side columns (Ratings left, Proficiency editor right) — Figma
   was manually edited 2026-09-10 to put these two widgets next to each
   other instead of stacked full-width, since on a desktop-width screen a
   single stacked column left a lot of unused horizontal space. Columns
   are natural-height (align-items: flex-start, not stretch) — Figma's own
   two columns aren't equal height either, the shorter one just ends early
   against the shared gradient background. Only .rg-profile-roles uses
   this layout; the read-only (non-owner) view still renders a single
   full-width Ratings display, since there's no second widget to pair it
   with there. */
.rg-profile-roles-columns {
  display: flex;
  /* Stacked by default — Figma's mobile frame keeps Ratings above Role
     Proficiency rather than side-by-side, since there isn't room at mobile
     widths for two columns to stay legible. Switched to a row at the
     1024px breakpoint below, where there's space for both side by side. */
  flex-direction: column;
  /* stretch (not flex-start): at desktop, Role Proficiency usually runs
     taller than Ratings, which left a stretch of unexplained empty space
     under the shorter column — a divider gives that space a clear purpose
     (Gestalt common region) instead of it reading as a leftover gap.
     Matches a divider the user independently added in the Figma design
     too. Stretch is harmless in the stacked mobile layout (each column is
     already full-width, so there's no cross-axis to stretch against). */
  align-items: stretch;
  gap: var(--spacing-lg);
}

.rg-profile-roles-col {
  flex: 1 1 0;
  min-width: 0;
}

/* Divider between the two sections — a bottom border while stacked
   (mobile), switched to a right border once they sit side by side
   (desktop, see the 1024px breakpoint below). :not(:only-child) because
   the other-profile view (Issue 5) now reuses this same column markup for
   its lone Ratings card — with no second column to divide from, this rule
   would otherwise leave a divider orphaned at the bottom of a standalone
   card, the same "divider with nothing to separate" bug this file's own
   .rg-role-display-widget override above already had to fix once. */
.rg-profile-roles-col:first-child:not(:only-child) {
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  padding-bottom: var(--spacing-lg);
}

/* .rg-role-display-widget's own top border/margin exists to separate it
   from the Proficiency editor that used to sit directly above it in the
   old stacked layout — reused as-is (unscoped) elsewhere this widget
   renders standalone (e.g. member-card popups), where it still applies.
   In its own column here there's nothing above it, so the divider floats
   orphaned; strip it in this context only. */
.rg-profile-roles-col .rg-role-display-widget {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.rg-role-proficiency-widget h2,
.rg-role-display-widget h2 {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-md);
}

.rg-role-proficiency-widget {
  margin: 0 0 var(--spacing-lg);
}

.rg-role-form-row {
  display: flex;
  gap: var(--spacing-md);
  flex-wrap: wrap;
  margin-bottom: var(--spacing-md);
}

.rg-role-proficiency-widget #rg-role-select {
  flex: 1;
  min-width: 200px;
  padding: 8px var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  background: var(--color-white);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

/* Branded focus ring — without this, focusing the field falls back to the
   browser's default blue outline, which clashes against this palette and
   is the single most common "this wasn't finished" tell in a UI. */
.rg-role-proficiency-widget #rg-role-select:focus-visible {
  outline: none;
  border-color: var(--color-accent-mid);
  box-shadow: 0 0 0 3px rgba(242, 101, 10, 0.25);
}

/* Add Role / Save (the latter styled further down, where a pre-existing
   button[type=submit] rule already lived) are the two actions someone
   actually performs in this widget — the accent-orange gives them real
   focal contrast against the card's teal-to-plum background, same
   reasoning as .btn-primary. Scoped to this one widget rather than
   changing --button-background-color globally, since making every button
   on the site orange would just make orange the new default and erase the
   focal-point effect entirely. */
.rg-profile-page .rg-role-proficiency-widget #rg-add-role {
  background: var(--color-accent-mid) !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 8px var(--spacing-lg);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-base) var(--font-sans);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}

.rg-profile-page .rg-role-proficiency-widget #rg-add-role:hover {
  background: var(--color-accent-start) !important;
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.rg-profile-page .rg-role-proficiency-widget #rg-add-role:disabled {
  background: var(--color-primary-light) !important;
  color: var(--color-text-muted) !important;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

.rg-role-item {
  padding: var(--spacing-md) 0;
  border-top: 1px solid var(--color-border);
}

.rg-role-item p {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  margin: 0 0 var(--spacing-sm);
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
}

.rg-profile-page .rg-role-item .rg-remove-role {
  /* Pushed to the row's right edge instead of sitting immediately after
     the role name — with variable-length names ("Data Analyst" vs.
     "Database Administrator"), a button placed right after the text lands
     in a different spot every row. Right-aligning is self-adjusting and
     needs no guessed column width. */
  margin-left: auto;
  background: var(--color-white) !important;
  color: var(--color-text-primary) !important;
  border: 1px solid var(--color-border) !important;
  padding: 4px var(--spacing-sm);
  border-radius: var(--radius-sm);
  font: 500 var(--font-size-sm) var(--font-sans);
  cursor: pointer;
}

/* Custom filled-track slider — a bare native range input reads as an
   unfinished control on a card this considered. The filled portion is a
   background gradient sized by --fill (WebKit has no
   ::-webkit-range-progress, unlike Firefox's ::-moz-range-progress, so this
   is the standard cross-browser technique); --fill is kept live by
   rg-role-proficiency-widget.php's own input-event JS. Thumb uses the same
   accent-orange as the widget's buttons so the one interactive control and
   the one actionable CTA read as the same "this is where you act" color. */
.rg-role-item input[type="range"] {
  width: calc(100% - 90px);
  vertical-align: middle;
  -webkit-appearance: none;
  appearance: none;
  height: 6px;
  border-radius: var(--radius-full);
  background: linear-gradient(
    to right,
    var(--color-accent-mid) 0%,
    var(--color-accent-mid) var(--fill, 0%),
    rgba(255, 255, 255, 0.28) var(--fill, 0%),
    rgba(255, 255, 255, 0.28) 100%
  );
  outline: none;
  cursor: pointer;
}

.rg-role-item input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin-top: -6px;
  border-radius: var(--radius-full);
  background: var(--color-white);
  border: 3px solid var(--color-accent-mid);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.rg-role-item input[type="range"]::-webkit-slider-thumb:hover {
  transform: scale(1.15);
  box-shadow: var(--shadow-md);
}

.rg-role-item input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.28);
}

.rg-role-item input[type="range"]::-moz-range-progress {
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--color-accent-mid);
}

.rg-role-item input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  background: var(--color-white);
  border: 3px solid var(--color-accent-mid);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

/* var(--color-text-muted) is near-illegible directly on this
   card's own .rg-card-gradient background (#0d72a0 -> #8c828f) — same fix
   already applied to native BP helper text on this exact gradient (see
   ".rg-card-gradient p, .description, ..." near the top of this file). */
.rg-role-item .proficiency-label {
  display: inline-block;
  width: 80px;
  text-align: right;
  margin-left: var(--spacing-sm);
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  vertical-align: middle;
}

.rg-profile-page .rg-role-proficiency-widget button[type="submit"] {
  background: var(--color-accent-mid) !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 10px var(--spacing-lg);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-base) var(--font-sans);
  cursor: pointer;
  margin-top: var(--spacing-sm);
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}

.rg-profile-page .rg-role-proficiency-widget button[type="submit"]:hover {
  background: var(--color-accent-start) !important;
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.rg-role-display-widget {
  margin-top: var(--spacing-lg);
  padding-top: var(--spacing-lg);
  border-top: 1px solid var(--color-border);
}

.rg-role-display-widget ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rg-role-display-widget li {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--spacing-sm);
  padding: var(--spacing-sm) 0;
  border-top: 1px solid var(--color-border);
}

.rg-role-display-widget li:first-child {
  border-top: none;
}

.rg-role-display-widget li p {
  margin: 0;
}

/* Fixed-width name/proficiency columns — with these as plain gap-separated
   flex children, a longer role name ("Database Administrator" vs. "HVAC
   Technician") pushes everything after it further right, so the
   proficiency tags (and the Remove buttons in the editable widget, fixed
   the same way) never lined up row to row. A fixed basis turns them into
   real columns instead. Was 105px — too narrow to hold a name like
   "Electrical Engineer" on one line, which is what was forcing the whole
   card to look cramped/narrower than Role Proficiency next to it; widened
   together with .rg-profile-roles-col's own width above. */
.rg-role-display-widget li > p:first-child {
  flex: 0 0 160px;
}

.rg-role-display-widget li strong {
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
}

/* Same low-contrast-on-gradient fix as .rg-role-item .proficiency-label above. */
.rg-role-display-widget .proficiency-label {
  flex: 0 0 78px;
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  /* Was margin-right: auto, force-justifying the star rating to the row's
     far edge — reasonable when the row spanned a full-width column, but
     now that this card has a compact capped width (see the 1024px glass-
     card rules), that just leaves an oversized gap before the stars.
     Packed with the row's own gap instead. */
}

.rg-role-display-widget input[type="range"] {
  display: none;
}

.rg-role-display-widget .star-rating {
  display: inline-block;
  position: relative;
  font-size: 18px;
  line-height: 1;
  vertical-align: middle;
}

.rg-role-display-widget .rating-value {
  display: inline-block;
  vertical-align: middle;
  margin-left: var(--spacing-sm);
  font: 700 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

/* ============================================================
   Team Page (includes/templates/page-team-page.php +
   buddypress/groups/single/members.php override)

   .rg-team-members-grid is the exact BP-native #members-group-list div
   (data-bp-list="group_members" untouched — BP's own Backbone/JS renders
   into it) with one class added for scoping. All selectors below are
   scoped under it so they don't leak onto other BP member lists (e.g.
   the site-wide Members directory, which reuses .item-entry/.list-wrap).
   ============================================================ */

/* margin-top/-bottom (not on neighboring elements) is the reusable form
   of this spacing — same "sort/filter bar between a block above and a
   card/post list below" pattern as .rg-teams-sort above and
   .rg-members-active-page .subnav-filters below; keep all three's
   top/bottom values in sync if this ever changes. !important needed:
   BP core's own .single-item.group-members .item-body .filters (3
   classes) and BuddyX's .buddypress-wrap .subnav-filters both otherwise
   out-specificity this single-class selector regardless of source order
   (same fight already resolved elsewhere in this file, e.g. the ad
   banner's border-radius). */
.rg-team-filters {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  flex-wrap: wrap;
  margin-top: var(--spacing-lg) !important;
  margin-bottom: var(--spacing-lg) !important;
}

.rg-team-page-title {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin: var(--spacing-md) 0 0;
}

.rg-team-members-grid {
  display: grid;
  /* See .rg-teams-grid's comment above — same content-width tradeoff,
     same auto-fit (not auto-fill) reasoning. 220px matches the Location
     Search results grid's card minimum (widgets/rg-get-user-locations-
     widget.php's .rg-users-list) — that page's own 1200px container cap
     is what keeps it to ~4/row regardless of viewport, but 190px here was
     letting a wide desktop (no such cap on this content area) spread
     member cards far thinner than that reference size. */
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--spacing-md);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* BP's own CSS floats/list-item-sizes .item-entry (li) for a masonry-style
   directory; that fights CSS Grid's default item stretch, so the li and
   its .list-wrap child were shrinking to their content's intrinsic width
   instead of filling the grid cell. Force both to fill explicitly. */
.rg-team-members-grid li.item-entry {
  display: block;
  float: none;
  width: 100%;
}

.rg-team-members-grid .list-wrap {
  width: 100%;
  /* CSS Grid's default align-items:stretch already gives every <li> in a
     row the same height (the row's tallest item) regardless of how many
     skills a member has — this just makes the visible white card fill
     that stretched height instead of shrink-wrapping its own content. */
  height: 100%;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-bottom: var(--spacing-md);
}

.rg-team-members-grid .buddyx-mem-cover-wrapper {
  width: 100%;
  height: 80px;
  background: #D1C7AD;
}

/* !important: BuddyX's own .buddyx-mem-cover-img rule sets
   padding-top:52.56% (the classic responsive-aspect-ratio box trick,
   percentage padding resolving against the parent's WIDTH). With
   box-sizing:border-box, that forces the border-box height to at least
   fit the padding — ~184px here — no matter what `height` says, since
   padding can't be compressed to negative content height. That
   overflowed its 80px-tall wrapper (which has no overflow:hidden of its
   own) and, being position:relative, painted in the positioned-elements
   layer ABOVE the avatar/name below it in normal flow, hiding them
   entirely. Zeroing the padding is what actually fixes the height. */
.rg-team-members-grid .buddyx-mem-cover-img {
  width: 100%;
  height: 80px !important;
  padding-top: 0 !important;
  overflow: hidden;
}

/* Test members here have no cover image set — an empty src renders as a
   broken-image icon instead of nothing, so hide the <img> and let the
   wrapper's tan background (set on .buddyx-mem-cover-wrapper above) show
   through, matching Figma's plain color block. A real cover photo would
   still need this shown; revisit once real member covers exist. */
.rg-team-members-grid .buddyx-mem-cover-img img[src=""],
.rg-team-members-grid .buddyx-mem-cover-img img:not([src]) {
  display: none;
}

.rg-team-members-grid .buddyx-mem-cover-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* !important: same group-members-list override as the img rule below —
   its wrapper otherwise inherits a much larger -80px offset sized for
   the native 150px avatar. */
.rg-team-members-grid .item-avatar {
  margin-top: -28px !important;
}

/* !important: on the group-members list (Team Page), BP renders a much
   larger native avatar (class avatar-150, 150x150) than the directory's
   default — its own sizing rule otherwise wins here and overlaps the
   name below it (confirmed via computed-style diagnostics: rendered
   126px tall with a -80px top margin instead of this card's 56px/-28px). */
.rg-team-members-grid .item-avatar img {
  width: 56px !important;
  height: 56px !important;
  border-radius: var(--radius-full) !important;
  border: 3px solid var(--color-white);
  object-fit: cover;
}

/* Online status on member cards: match the Profile page's ring treatment
   (.rg-profile-avatar.rg-avatar-online img, above) instead of BuddyX's own
   small green dot (buddyx_user_status(), which prints a bare
   <span class="member-status online"> with no "offline" counterpart — only
   present in the DOM at all when the member is online). Hide the dot and
   recolor the avatar border via :has() instead of overriding the theme
   template, consistent with this card grid's existing "restyle BuddyX's
   native output" approach. */
.rg-team-members-grid .item-avatar .member-status {
  display: none;
}

/* !important: BuddyX's own ".buddypress-wrap .grid.bp-list>li .list-wrap
   .item-avatar img.avatar" rule (specificity 0,6,2) otherwise beats this
   selector's :has() (0,4,1) and keeps the border white. */
.rg-team-members-grid .item-avatar:has(.member-status.online) img {
  border-color: var(--color-online) !important;
}

.rg-team-members-grid .item,
.rg-team-members-grid .item-block,
.rg-team-members-grid .member-info-wrapper {
  width: 100%;
}

/* !important on font-size/line-height: BuddyX's own ".bp-list li .item
   .list-title" (loaded after this stylesheet, tied specificity — 3 classes
   each) was winning and forcing 22px/1.1 regardless of this rule, so the
   size/line-height below were silently never applying at all (confirmed via
   CSS.getMatchedStylesForNode) — not just the min-height fix, the whole
   rule. min-height:2.6em (2 lines' worth, in THIS rule's own em, which only
   works now that font-size above is actually being forced to
   --font-size-base) reserves room for a name that wraps to a second line
   ("Willie Westhuyzen", "Jan van der Merwe") — without it, a short one-line
   name let the roles box below start ~1 line higher than a neighbor with a
   wrapped name, so the boxes (and the Invite Member buttons pinned to their
   bottoms, per that rule's own comment above) lined up with each other but
   not with the row's wrapped-name cards. Same reasoning applies to the
   "Active X ago" line below. */
.rg-team-members-grid .list-title.member-name {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--font-size-base) !important;
  line-height: 1.3 !important;
  min-height: 2.6em;
  margin: var(--spacing-sm) 0 0;
}

.rg-team-members-grid .list-title.member-name a {
  color: var(--color-text-primary);
  text-decoration: none;
}

/* Was targeting only ".joined.item-meta", which turns out to be the class
   BP-Nouveau uses for this line on the Team Page member grid ("joined X ago")
   — but the site-wide Active Members directory renders the exact same line
   as <p class="item-meta last-activity"> ("Active X ago") instead, no
   ".joined" class at all, so half of this rule's job was dead code on that
   screen. Both selectors now, one rule, so the fix reaches both grids. Its
   font-size (12px, from BuddyX's ".bp-list li .item-meta" rule) already
   matches --font-size-sm on both, so no !important fight needed here, just
   the corrected selectors. */
.rg-team-members-grid .item-meta.last-activity,
.rg-team-members-grid .joined.item-meta {
  min-height: 2.6em;
  color: var(--color-text-muted);
}

/* Figma's card doesn't show a friend/action button — hidden here only
   (the feature itself is untouched, just not shown on this compact card). */
.rg-team-members-grid .member-action-wrapper {
  display: none;
}

/* min-height: this box only ever shows up to 3 roles (rg_rest_get_user_roles
   caps it) — 290px comfortably fits 3, measured against real 3-role members,
   with headroom for a role name wrapping to two lines. A member with fewer
   roles (or none — see the "No roles listed yet" placeholder in
   buildRolesHTML() above) gets the same box height instead of a shorter blue
   box with white space and a floating Invite Member button below it. The
   flex column + the button's margin-top:auto below is what actually pins the
   button to the box's bottom edge across every card. */
.rg-member-roles-compact {
  background: var(--color-primary-light);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-md);
  margin: var(--spacing-sm) var(--spacing-sm) 0;
  padding: var(--spacing-sm);
  text-align: left;
  width: calc(100% - 2 * var(--spacing-sm));
  min-height: 290px;
  display: flex;
  flex-direction: column;
}

.rg-role-item-empty {
  color: var(--color-text-muted);
  font: 400 var(--font-size-sm) var(--font-sans);
  font-style: italic;
}

.rg-member-roles-compact .rg-invite-member-btn {
  margin-top: auto;
  align-self: flex-start;
}

.rg-roles-title {
  color: var(--color-primary);
  font: 700 var(--font-size-sm) var(--font-sans);
  text-align: center;
  margin-bottom: var(--spacing-xs);
}

.rg-role-item-compact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: var(--spacing-xs);
}

.rg-role-item-compact:last-child {
  margin-bottom: 0;
}

.rg-role-name {
  flex: 1 1 auto;
  font: 700 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
}

/* Right-aligned on the name's row, matching the Figma card redesign —
   was previously on its own line under the name. Figma's pill background
   (#dceef5) is the exact same color as its parent .rg-member-roles-compact
   box (--color-primary-light) — it's meant to blend in and read as plain
   text, not stand out as a filled badge. Confirmed via get_design_context
   on the Members_page card (node 397:559): the "pill" is only visible at
   all because of its rounded corners, not a color contrast. */
.rg-role-proficiency {
  flex: 0 0 auto;
  margin-left: auto;
  background: var(--color-primary-light);
  color: var(--color-primary);
  font: 500 10px var(--font-sans);
  padding: 1px 8px;
  border-radius: var(--radius-full);
}

.rg-role-rating {
  flex: 1 0 100%;
  font-size: 12px;
  color: #FFC107;
}

.rg-role-rating .rating-number {
  color: var(--color-text-muted);
  font-size: 10px;
  margin-left: 4px;
}

/* Desktop density rescale, part 2 — the handful of this card's own
   dimensions that are hardcoded px rather than var(--font-size-*)/
   var(--spacing-*) references, so the :root override above doesn't reach
   them automatically. Without this, shrinking the tokens alone (part 1)
   left this card's TEXT smaller but its BOXES the original mobile size —
   most visibly .rg-member-roles-compact's 290px min-height (sized to fit
   3 roles at the original, larger font) suddenly had far more room than
   its now-smaller text needed, showing as dead white space under a
   member's roles. Same ~0.72 ratio as part 1, floored at 8px for the
   smallest text (rating-number/role-proficiency) rather than following
   the ratio all the way down to 7px — legible beats perfectly on-ratio
   for text that small. */
@media (min-width: 1024px) {
  .rg-member-roles-compact {
    min-height: 209px;
  }

  .rg-team-members-grid .buddyx-mem-cover-wrapper,
  .rg-team-members-grid .buddyx-mem-cover-img {
    height: 58px !important;
  }

  .rg-team-members-grid .item-avatar img {
    width: 40px !important;
    height: 40px !important;
  }

  .rg-team-members-grid .item-avatar {
    margin-top: -20px !important;
  }

  .rg-role-proficiency {
    font-size: 8px;
  }

  .rg-role-rating {
    font-size: 9px;
  }

  .rg-role-rating .rating-number {
    font-size: 8px;
  }
}

/* ============================================================
   Group Home / Activity (buddypress/groups/single/activity.php
   override — a group's default landing screen). BP's own post form,
   search/filter bar, and #activity-stream (Backbone-rendered activity
   list) are all untouched.

   The site's activity entries are rendered by the BuddyX theme's own
   activity template override (wp-content/themes/buddyx/buddypress/
   activity/entry.php), not BP-Nouveau's stock bundled activity/entry.php
   — its per-item markup is .activity-card-head + .activity-item-head
   (its own internal flex header row) + .activity-content +
   .activity-comments as siblings, not the .activity-avatar/
   .activity-header/.activity-meta shape BP-Nouveau ships. Forcing
   display:flex on li.activity-item here fought that internal layout and
   collapsed .activity-content to 0px (confirmed via computed-style
   diagnostics — the meta/action buttons were rendering outside the card
   entirely). So: only add card chrome (background/border/radius/spacing)
   to the <li> itself and leave BuddyX's own internal layout of its
   children alone. */

#whats-new-form {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-md);
  margin: var(--spacing-md) 0;
}

#whats-new-form textarea {
  width: 100%;
  min-height: 60px;
  padding: var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  box-sizing: border-box;
  resize: vertical;
}

.rg-profile-page #whats-new-form #aw-whats-new-submit {
  background: var(--color-primary) !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 8px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-sm) var(--font-sans);
  cursor: pointer;
}

.rg-team-activity-stream {
  list-style: none;
  margin: var(--spacing-md) 0 0;
  padding: 0;
}

.rg-team-activity-stream li.activity-item {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-md);
  margin-bottom: var(--spacing-md);
  overflow: hidden;
}

.rg-team-activity-stream .activity-avatar img,
.rg-team-activity-stream .activity-card-head img {
  border-radius: var(--radius-full);
  object-fit: cover;
}

.rg-team-activity-stream .activity-header,
.rg-team-activity-stream .activity-item-head {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
}

.rg-team-activity-stream .activity-header a,
.rg-team-activity-stream .activity-item-head a {
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: none;
}

.rg-profile-page .rg-team-activity-stream .activity-meta a.button,
.rg-profile-page .rg-team-activity-stream .generic-button a.button {
  background: var(--color-primary-light) !important;
  color: var(--color-primary-dark) !important;
  border: none !important;
  padding: 4px var(--spacing-sm);
  border-radius: var(--radius-sm);
  font: 600 12px var(--font-sans);
  text-decoration: none;
  cursor: pointer;
}

/* ============================================================
   Project Page (widgets/rg-project-widget.php, wrapped by
   includes/templates/page-project-page.php)
   ============================================================ */

/* Root Project_page/Project_page_ReadOnly Figma frames fill — same token
   CLAUDE.md documents as "Auth page background", also used here (originally
   #00424C, since retuned via the palette editor — kept in sync with
   .rg-auth-page below by hand, since they're two separate rules that just
   happen to share this value, not one selector). Fills the gaps around
   Panel_C/the content card/Panel_D (and below Panel_D's short ad stack)
   that were plain off-white instead of this teal — confirmed via
   get_design_context on node 588:638's root fill. Scoped to this screen
   only, not applied sitewide. */
.rg-project-single-page {
  background: #071f29;
}

.rg-project-page-title {
  font: 700 var(--font-size-h2) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0;
  /* Figma centers the title (and the back button below it) as a unit —
     confirmed on both the owner and read-only frames. */
  text-align: center;
}

/* !important: BuddyPress core's ".buddypress .buddypress-wrap button"
   reset (specificity 0,2,1) still beats a scoped ".rg-profile-page
   .rg-project-save-btn" class selector (0,2,0) for real <button>/
   <input type=submit> elements — confirmed via computed-style
   diagnostics, .rg-project-save-btn's background was silently losing.
   Same fix rg-nav-bar.php already uses throughout for overriding
   BuddyX/BP styles this plugin doesn't own. */
.rg-profile-page .rg-project-back-btn,
.rg-profile-page .rg-project-save-btn {
  display: inline-block;
  background: var(--color-primary) !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 10px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-base) var(--font-sans);
  text-decoration: none;
  cursor: pointer;
  margin-top: var(--spacing-sm);
}

/* Center the back button under the now-centered title (Figma treats them
   as one centered unit) without touching .rg-project-save-btn, which
   stays inline in its form context. */
.rg-profile-page .rg-project-back-btn {
  display: block;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
}

/* Plain text, no colored box — matches Figma exactly (get_design_context
   on node 588:638 shows "Description" + the text as two bare <p> tags,
   no background/padding/radius at all). Was styled as a light-blue card
   before, which doesn't exist in any of the 5 Project Page frames. */
.rg-project-description {
  margin-top: var(--spacing-md);
}

.rg-project-description h4 {
  margin: 0 0 var(--spacing-xs);
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
}

.rg-project-description p {
  margin: 0;
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

/* flex-wrap: completed projects show up to 6 fixed-width (150px) tabs, which
   is wider than the content card at desktop widths and was clipping the last
   ones ("Rate Project") off the right edge with no way to reach them. Wrapping
   keeps Figma's fixed tab size and just drops the overflow onto a second row. */
.rg-project-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-sm);
  border-bottom: 1px solid var(--color-border);
  margin-top: var(--spacing-md);
  padding-bottom: var(--spacing-sm);
}

/* !important: BuddyPress core's ".buddypress .buddypress-wrap button" reset
   (specificity 0,2,1) still beats this scoped ".rg-profile-page
   .rg-project-tab-btn" class selector (0,2,0) for a real <button> element —
   confirmed via computed-style diagnostics, border/border-radius/padding/
   font were silently falling back to BP's plain small-button look. Same fix
   rg-nav-bar.php and .rg-project-save-btn above already use throughout.
   Fixed 150x36px size (not content-hugging) matches Figma's spec exactly —
   confirmed identical across all 5 Project Page tab-state frames regardless
   of tab count/label length, so it's a deliberate fixed size, not a stretch
   layout. */
.rg-profile-page .rg-project-tab-btn {
  display: flex !important;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 150px !important;
  height: 36px;
  background: #F2F2F2 !important;
  color: #4D4D4D !important;
  border: none !important;
  border-radius: var(--radius-sm) !important;
  padding: 0 !important;
  font: 700 13px var(--font-sans) !important;
  cursor: pointer;
}

.rg-profile-page .rg-project-tab-btn.active {
  background: var(--color-primary) !important;
  color: var(--color-white) !important;
}

/* Wraps a wide table so it scrolls horizontally within its own card
   instead of either crushing every column illegibly or overflowing the
   page itself — reused for every data table on the site wide enough to
   run out of room (this one, and table.notifications further down).
   Reach for this on any future table in the same situation rather than
   writing a one-off fix per table. */
.rg-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.rg-member-table {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  margin-top: var(--spacing-md);
}

.rg-member-table th {
  background: #F5F5F5;
  color: #333;
  font: 700 var(--font-size-sm) var(--font-sans);
  text-align: left;
  padding: var(--spacing-sm);
}

.rg-member-table td {
  padding: var(--spacing-sm);
  border-bottom: 1px solid var(--color-border);
  font: 400 var(--font-size-base) var(--font-sans);
  color: #333;
}

.rg-member-table-center {
  text-align: center !important;
}

.rg-member-row-pending {
  opacity: 0.7;
}

.rg-project-badge-declined {
  background: #FFCCCC;
  color: #B5541E;
}

/* Same button[type=submit] specificity fight as .rg-project-save-btn above. */
.rg-profile-page .rg-member-remove-btn {
  background: #cf6767 !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 4px var(--spacing-sm);
  border-radius: var(--radius-sm);
  font: 600 11px var(--font-sans);
  cursor: pointer;
}

.rg-project-save-wrap {
  margin-top: var(--spacing-md);
}

.rg-project-note {
  background: var(--color-primary-light);
  border-left: 4px solid var(--color-primary);
  padding: var(--spacing-sm) var(--spacing-md);
  font: 400 var(--font-size-sm) var(--font-sans);
  color: #4D4D4D;
  margin: 0 0 var(--spacing-md);
}

/* ── Discussion tab (show_project_discussion) ──────────────── */

.rg-project-discussion-form {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-lg);
}

.rg-project-discussion-form textarea {
  width: 100%;
  padding: var(--spacing-sm) var(--spacing-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  resize: vertical;
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.rg-project-discussion-form textarea:focus-visible {
  outline: none;
  border-color: var(--color-accent-mid);
  box-shadow: 0 0 0 3px rgba(242, 101, 10, 0.25);
}

.rg-project-discussion-submit {
  align-self: flex-end;
}

.rg-project-discussion-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rg-project-discussion-item {
  padding: var(--spacing-md) 0;
  border-top: 1px solid var(--color-border);
}

.rg-project-discussion-list > .rg-project-discussion-item:first-child {
  border-top: none;
  padding-top: 0;
}

/* The avatar+body pair is its own flex row, separate from the <li> itself,
   so the threaded-replies <ul> (a sibling of this row, not a flex item
   inside it) stacks BELOW the post instead of squeezing in beside it —
   with both on the same flex line, the empty space the replies-ul claimed
   next to a short post was intercepting clicks meant for the Reply button. */
.rg-project-discussion-row {
  display: flex;
  gap: var(--spacing-sm);
}

.rg-project-discussion-avatar img {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  object-fit: cover;
}

/* Threaded replies — nested <ul>s indent further with each level, so a
   reply to a reply reads as visually "inside" its own parent, not just
   inside the original post. */
/* !important here beats BuddyX's own '.buddypress .entry-content ul'
   list reset (specificity 0-2-1, higher than this single-class rule's
   0-1-0) — the same category of theme-reset cascade fight this project
   already works around for .btn-primary buttons. Without it every level
   of reply collapsed to the same indentation (margin/padding both
   silently zeroed), even though the nesting itself was structurally
   correct — confirmed via Chrome DevTools' matched-styles inspection,
   not guessed. */
.rg-project-discussion-replies {
  list-style: none !important;
  margin: var(--spacing-sm) 0 0 !important;
  padding-left: var(--spacing-lg) !important;
  border-left: 2px solid var(--color-border);
}

.rg-project-discussion-reply-item {
  padding: var(--spacing-sm) 0;
  border-top: 1px solid var(--color-border);
}

.rg-project-discussion-replies > .rg-project-discussion-reply-item:first-child {
  border-top: none;
  padding-top: 0;
}

.rg-project-discussion-reply-item .rg-project-discussion-avatar img {
  width: 30px;
  height: 30px;
}

.rg-project-discussion-reply-item .rg-project-discussion-replies {
  margin-top: var(--spacing-xs);
}

.rg-discussion-reply-toggle {
  display: inline-block;
  background: none;
  border: none;
  padding: var(--spacing-xs) 0 0;
  margin: 0;
  font: 600 var(--font-size-sm) var(--font-sans);
  color: var(--color-primary);
  cursor: pointer;
}

.rg-discussion-reply-toggle:hover {
  color: var(--color-accent-mid);
  text-decoration: underline;
}

.rg-project-discussion-reply-form {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
  margin-top: var(--spacing-sm);
}

.rg-project-discussion-reply-form textarea {
  width: 100%;
  padding: var(--spacing-xs) var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  resize: vertical;
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.rg-project-discussion-reply-form textarea:focus-visible {
  outline: none;
  border-color: var(--color-accent-mid);
  box-shadow: 0 0 0 3px rgba(242, 101, 10, 0.25);
}

.rg-project-discussion-reply-submit {
  align-self: flex-end;
  font-size: var(--font-size-sm);
  padding: var(--spacing-xs) var(--spacing-md);
}

.rg-project-discussion-body {
  flex: 1 1 0;
  min-width: 0;
}

.rg-project-discussion-meta {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-sm);
  margin: 0 0 var(--spacing-xs);
  font: 400 var(--font-size-sm) var(--font-sans);
}

.rg-project-discussion-meta strong {
  font-weight: 700;
  color: var(--color-text-primary);
}

.rg-project-discussion-time {
  color: var(--color-text-muted);
}

.rg-project-discussion-content {
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  line-height: 1.5;
}

.rg-project-discussion-content p {
  margin: 0 0 var(--spacing-sm);
}

.rg-project-discussion-content p:last-child {
  margin-bottom: 0;
}

.rg-project-discussion-empty {
  color: var(--color-text-muted);
}

/* ── Settings tab (show_project_settings) + Create form (show_create_form) ── */

.rg-project-form-group {
  margin: 0 0 var(--spacing-md);
}

.rg-project-form-label {
  display: block;
  font: 600 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-xs);
}

.rg-project-form-input,
.rg-project-form-textarea,
.rg-project-form-select {
  width: 100%;
  padding: 8px var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  background: var(--color-white);
  box-sizing: border-box;
}

.rg-project-form-textarea {
  resize: vertical;
}

.rg-project-form-checkbox-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
}

.rg-project-form-checkbox-row input[type="checkbox"] {
  accent-color: var(--color-primary);
}

.rg-project-form-help {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: var(--spacing-xs) 0 0;
}

.rg-project-form-actions {
  display: flex;
  gap: var(--spacing-sm);
  margin-top: var(--spacing-md);
}

/* ── Add Members tab (show_add_members_form / show_member_search_results) ── */

.rg-project-info-box {
  background: #E7F3FF;
  border-left: 4px solid #2196F3;
  border-radius: var(--radius-sm);
  padding: var(--spacing-md);
  margin-bottom: var(--spacing-md);
}

.rg-project-info-box-title {
  display: block;
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-xs);
}

.rg-project-info-box p {
  margin: 0;
  font: 400 var(--font-size-sm) var(--font-sans);
  color: #333;
}

.rg-project-role-search-row {
  display: flex;
  gap: var(--spacing-sm);
  align-items: flex-end;
  margin-top: var(--spacing-sm);
}

.rg-project-role-search-row .rg-project-form-select {
  flex: 1;
}

.rg-member-search-results {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-top: var(--spacing-md);
}

.rg-member-result {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--spacing-md);
  padding: var(--spacing-sm) var(--spacing-md);
  border-bottom: 1px solid var(--color-border);
}

.rg-member-result:last-child {
  border-bottom: none;
}

.rg-member-result-name {
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  display: block;
}

.rg-member-result-email {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  display: block;
  margin-top: 2px;
}

.rg-member-result-meta {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: #999;
  display: block;
  margin-top: 4px;
}

/* Shown in place of the Send Invite button for a role-search result
   who's already a project member or already has a pending invite —
   same small-pill convention as .rg-project-badge, neutral/muted
   rather than that one's active/completed colors since this is just
   informational, not a state change to call attention to. */
.rg-member-result-status {
  display: inline-block;
  flex-shrink: 0;
  font: 500 11px var(--font-sans);
  padding: 4px 10px;
  border-radius: var(--radius-full);
  background: var(--color-border);
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* ── Ratings (show_ratings_readonly, show_rate_members_form, show_rate_project_form) ── */

.rg-rating-card {
  padding: var(--spacing-md);
  background: #F9F9F9;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: var(--spacing-md);
}

.rg-rating-card:last-child {
  margin-bottom: 0;
}

.rg-rating-card-overall {
  text-align: center;
}

.rg-rating-card-header {
  margin-bottom: var(--spacing-sm);
}

.rg-rating-card-header strong {
  font: 700 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
}

.rg-rating-card-header span {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin-left: var(--spacing-sm);
}

.rg-star-display {
  display: inline-block;
  position: relative;
  font-size: 22px;
  line-height: 1;
}

.rg-star-display-empty {
  color: var(--color-border);
  white-space: nowrap;
}

.rg-star-display-filled {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  color: #FFC107;
  white-space: nowrap;
}

.rg-star-display-value {
  color: var(--color-text-muted);
  font: 700 var(--font-size-base) var(--font-sans);
  margin-left: var(--spacing-md);
  vertical-align: middle;
}

/* ============================================================
   Members Active (BuddyPress Members Directory, wrapped by
   includes/templates/buddypress/members/index.php). No Panel_C on
   this screen — .rg-profile-layout's flex row just has two children
   (main + Panel_D) instead of three, so the base rules already fit.
   The member card grid reuses .rg-team-members-grid's styling
   (defined in the Team Page section above) as-is.
   ============================================================ */

.rg-members-active-page .component-navigation.members-nav {
  display: flex;
  gap: var(--spacing-lg);
  list-style: none;
  margin: 0 0 var(--spacing-md);
  padding: 0;
}

.rg-members-active-page .component-navigation.members-nav li {
  list-style: none;
}

/* Was #4D4D4D — only 2.26:1 against .rg-card-gradient's lightened teal
   stop (2026-10), the same under-contrast problem the rest of this card's
   text had. Same dark token the active tab already uses below; font-weight
   alone (400 here, 700 there) still carries the active/inactive distinction. */
.rg-members-active-page .component-navigation.members-nav a {
  display: inline-block;
  padding: var(--spacing-xs) var(--spacing-sm);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  text-decoration: none;
}

/* Matches Figma exactly (node 258:536: dark #111827 bold text for the
   active tab, no pill/background). The "safe against the gradient's fixed
   dark-blue start" reasoning this comment used to have described an older
   version of .rg-card-gradient (#0d72a0) that predates its current teal/
   plum stops — superseded, not re-verified against every subsequent
   gradient revision; the inactive-tab color right above is what actually
   keeps this readable now. */
.rg-members-active-page .component-navigation.members-nav li.selected a,
.rg-members-active-page .component-navigation.members-nav li.current a {
  font-weight: 700;
  color: #111827 !important;
}

.rg-members-active-page .component-navigation.members-nav .count {
  margin-left: var(--spacing-xs);
  color: inherit;
}

/* Same spacing values as .rg-teams-sort / .rg-team-filters — see their
   comments for why this is margin-top/-bottom on the sort/filter bar
   itself rather than on whatever sits above or below it. */
/* !important needed: BuddyX's .buddypress-wrap .subnav-filters is the
   same specificity (2 classes) and loads after this stylesheet, winning
   the cascade tie otherwise — same fight as .rg-team-filters above. */
.rg-members-active-page .subnav-filters {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md);
  flex-wrap: wrap;
  margin-top: var(--spacing-lg) !important;
  margin-bottom: var(--spacing-lg) !important;
}

.rg-members-active-page .subnav-search input[type="search"],
.rg-members-active-page .subnav-search input[type="text"] {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 8px var(--spacing-sm);
  font: 400 var(--font-size-sm) var(--font-sans);
  min-width: 260px;
}

.rg-members-active-page .rg-team-members-grid {
  margin-top: var(--spacing-md);
}

/* Any plain BP subnav (item-subnav's "My Projects/Create Project/
   Invites/Send Email Invite" and "Memberships/Invitations" tab strips
   — no rg- class of their own, styled by BuddyX's native subnav CSS)
   that ends up rendered inside a .rg-card-gradient wrapper needs the
   same white-pill treatment as the Active Members tabs above, since
   its default teal/muted text otherwise washes out against the
   gradient the same way. */
/* BuddyX's own ul.subnav ships a near-white background (#fafafa), sized
   for sitting on the plain page background it used to render on. Now that
   it's inside the gradient card, that background shows as a solid white
   box behind the tabs instead of transparent — invisible white-on-white
   text on top of it, on the tabs the gradient-aware color rules below
   don't otherwise catch. */
.rg-card-gradient .subnav.bp-priority-subnav-nav-items,
.rg-card-gradient .rg-notifications-subnav {
  background: transparent;
}

/* Was white — fine against the gradient's original, darker stops (5-6.6:1)
   but only 2.5-3.7:1 against the 2026-10 lightened ones (see
   .rg-card-gradient's own comment above), since lightening the background
   to support dark text everywhere else on the card pulled the rug out from
   under text that was relying on it staying dark. Matching the rest of the
   card's text to dark here too, rather than re-darkening just for this one
   element, keeps one consistent "dark text on this card" rule instead of
   two different strategies fighting the same background. */
.rg-card-gradient .subnav.bp-priority-subnav-nav-items a {
  color: var(--color-text-primary);
}

.rg-card-gradient .subnav.bp-priority-subnav-nav-items li.selected a,
.rg-card-gradient .subnav.bp-priority-subnav-nav-items li.current a {
  background: var(--color-white);
  color: var(--color-text-primary) !important;
  border-radius: var(--radius-sm);
  padding: 4px var(--spacing-sm);
}

/* The Members directory's #members-dir-list is populated client-side
   by BP-Nouveau's own Backbone views with one extra layer of nesting:
   <ul class="item-list ... grid three"> wrapping the <li> cards (Team
   Page's #members-group-list turned out to have the same nesting —
   see the matching fix below — despite an earlier assumption here that
   it didn't). With
   .rg-team-members-grid's display:grid landing on the OUTER div, that
   <ul> was being treated as a single grid item — sized to one column
   track — which is why this list was rendering as a single column
   no matter how much width was available (confirmed via computed-style
   diagnostics after the container-width fix above: #members-dir-list
   measured 1182px wide, plenty for several columns, but its only
   child — the <ul> — was still just 223px). Move the grid to the
   actual <ul> instead; .rg-team-members-grid's other descendant rules
   (card background, avatar sizing, etc.) already reach it fine via
   plain descendant selectors regardless of the extra nesting. */
.rg-members-active-page #members-dir-list.rg-team-members-grid {
  display: block;
}

/* !important: BuddyX's own "#buddypress.buddypress-wrap .grid.bp-list"
   (specificity 1,3,0 — exactly tied with the selector below, so the
   tie-break falls to stylesheet load order and BuddyX's wins) sets
   display:flex, which was collapsing every card to the full row
   width instead of a grid column. */
/* auto-fill, not auto-fit: with auto-fit, empty tracks collapse away, so
   a lone result's single occupied track is left as the ONLY track and its
   1fr stretches to the full container width. auto-fill keeps the full set
   of tracks the container width allows (just empty), so a lone card's
   track stays sized to its own minmax(190px, 1fr) share of that row —
   see the matching fix below for #members-group-list, which hit the
   identical "single Team member spans the whole card" bug. */
.rg-members-active-page #members-dir-list .item-list.grid {
  display: grid !important;
  /* 220px to match .rg-team-members-grid's own minimum — see its comment. */
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)) !important;
  gap: var(--spacing-md);
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

/* Team Page's #members-group-list turns out to have the exact same
   extra-nesting issue as the directory above (confirmed via computed-style
   diagnostics: its only children are the pagination rows and an inner
   <ul class="item-list members-group-list bp-list grid three"> — the <li>
   cards live in THAT ul, not as direct children of the div this grid class
   targets), so it needs the same fix — the comment above this block
   describing #members-group-list as an exception was incorrect. */
#members-group-list.rg-team-members-grid {
  display: block;
}

/* auto-fill, not auto-fit — see the matching comment on #members-dir-list
   above. This is the one that actually produced the reported bug: a Team
   with a single member rendered that member's card stretched the full
   width of the main canvas instead of as a standard-sized card. */
#members-group-list.rg-team-members-grid .item-list.grid {
  display: grid !important;
  /* 220px to match .rg-team-members-grid's own minimum — see its comment. */
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)) !important;
  gap: var(--spacing-md);
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

/* ============================================================
   Notifications (BuddyPress native notifications component,
   wrapped by includes/templates/buddypress/members/single/notifications.php)

   Note: BP's "Unread | Read" tabs are the native
   #member-secondary-nav item-subnav (same mechanism as Profile's
   "View | Edit | ..." row) — left as BP's native underline-style
   subnav per the earlier "leave native subnav visible" call on
   Profile, just restyled to match Figma's underline treatment
   instead of Project Page's pill tabs.
   ============================================================ */

.rg-notifications-subnav {
  display: flex;
  gap: var(--spacing-lg);
  list-style: none;
  margin: 0;
  padding: 0;
}

.rg-notifications-subnav li {
  list-style: none;
}

/* Was white for the same reason as .rg-card-gradient .subnav...a above
   (muted gray was invisible against the gradient) — now dark, matching
   that rule's own 2026-10 update, since the gradient was lightened
   specifically to carry dark text well. The active tab still gets a white
   pill + dark text via .rg-card-gradient .subnav.bp-priority-subnav-nav-
   items, below. */
.rg-notifications-subnav a {
  display: inline-block;
  padding: var(--spacing-sm) 0;
  font: 700 15px var(--font-sans);
  color: var(--color-text-primary);
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

/* !important: BP Nouveau/theme's own .selected/.current a color (an
   accent red) otherwise beats this — same specificity fight documented
   on the Project Page tab buttons. */
.rg-notifications-subnav li.selected a,
.rg-notifications-subnav li.current a {
  color: var(--color-primary-dark) !important;
  border-bottom-color: var(--color-primary) !important;
}

/* A Team's own primary nav (Home/Team Projects/Members/Invite/Manage) —
   see rolegraderplugin_render_team_nav(). BP-Nouveau's real markup (#object-
   nav > #group-primary-nav > li.bp-groups-tab > a), which ships as a
   VERTICAL list (BuddyX's default sidebar-style group menu) with no
   contrast treatment of its own — same category of fix as
   .rg-notifications-subnav above, flattened to a horizontal pill strip to
   match every other in-card tab bar in this plugin (Settings, Projects).
   No explicit color here: inactive tabs inherit .rg-card-gradient's own
   dark text for free; only the active state needs its own rule. */
/* !important throughout: BuddyX ships this exact nav (id="object-nav",
   classes include "vertical") as a tall 230px-wide SIDEBAR component —
   nav#object-nav.vertical { width:100%; flex:0 0 230px; float:left;
   min-height:50vh; background:#fdfdfd; padding:20px 0; ... } — since
   bp_nouveau_single_item_nav_classes() always adds "vertical" here (no BP
   template arg to opt out), that's a tall white box, not a tab strip. Its
   OWN stylesheet already has the flat-horizontal variant we actually want
   (#object-nav:not(.vertical) > ul { display:flex; flex-wrap:wrap; }) —
   same specificity tier (id + 1 class + type), so matching it property-
   for-property here, scoped under .rg-team-tabs, is what actually wins
   instead of fighting it rule-by-rule. */
.rg-team-tabs #object-nav {
  width: auto !important;
  flex: none !important;
  float: none !important;
  min-height: 0 !important;
  background: transparent !important;
  border: 0 !important;
  padding: 0 !important;
  margin: 0 0 var(--spacing-md) !important;
}

.rg-team-tabs #group-primary-nav {
  display: flex !important;
  flex-wrap: wrap;
  gap: var(--spacing-sm);
  list-style: none;
  width: auto !important;
  margin: 0;
  padding: 0;
}

.rg-team-tabs #group-primary-nav li {
  list-style: none;
}

.rg-team-tabs #group-primary-nav a {
  display: inline-block !important;
  width: auto !important;
  padding: 6px var(--spacing-sm) !important;
  margin: 0 !important;
  font: 700 14px var(--font-sans);
  text-decoration: none;
  border-radius: var(--radius-sm);
}

/* !important: same BP-Nouveau/theme .selected/.current a color fight as
   .rg-notifications-subnav above. */
.rg-team-tabs #group-primary-nav li.selected a,
.rg-team-tabs #group-primary-nav li.current a {
  background: var(--color-white) !important;
  color: var(--color-text-primary) !important;
}

.rg-notifications-card {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--spacing-md);
}

/* .rg-notifications-card and .rg-card-gradient are equal-specificity
   single-class selectors — since this rule comes later in the
   cascade, its white background would otherwise beat the gradient on
   Settings/Notifications/Messages, which carry both classes.
   Keep this in sync with .rg-card-gradient's own background above — this
   duplicate is exactly why the 2026-10 contrast fix there (lightened
   stops, #3fb7a2/#947ba3) silently missed Settings/Notifications/Messages
   the first time around: this more-specific rule kept serving the old,
   low-contrast #2a7a6c/#6b5478 pair underneath it. */
.rg-notifications-card.rg-card-gradient {
  background: linear-gradient(180deg, #3fb7a2 0%, #947ba3 100%);
}

.rg-notifications-card .subnav-filters {
  display: flex;
  justify-content: flex-end;
  margin-bottom: var(--spacing-md);
}

.rg-notifications-card .subnav-filters select {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 6px var(--spacing-sm);
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

/* BP-Nouveau's own per-thread checkbox (.thread-cb, inside each
   li.thread-item of the inbox/sentbox/starred list) ships with zero
   padding/margin of its own, so it sits flush against the list's left
   edge — cramped next to the ~40px of breathing room every other element
   in the row gets. Scoped to .rg-messages-card (not .rg-notifications-card
   generally) since the bulk "All Messages" select-all checkbox above the
   list uses the same flush-left position by design (its own label sits
   right next to it) and wasn't flagged as an issue. */
.rg-messages-card .thread-cb {
  padding-left: var(--spacing-md);
}

.rg-notifications-list .bp-feedback {
  background: var(--color-primary-light);
  border-left: 4px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: var(--spacing-sm) var(--spacing-md);
  color: var(--color-text-primary);
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
}

/* Same .rg-table-scroll treatment as .rg-member-table (see its comment)
   — applied directly to this wrapper (rather than adding a markup-level
   .rg-table-scroll div) since #notifications-user-list is BP-Nouveau's
   own client-side-rendered container (Underscore.js template, not PHP
   we control here), but it's already a stable, always-present wrapper
   around the table either way. */
.rg-notifications-list {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.rg-notifications-list table.notifications {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
}

.rg-notifications-list table.notifications thead tr {
  background: #F5F5F5;
}

.rg-notifications-list table.notifications th {
  text-align: left;
  padding: var(--spacing-sm);
  font: 700 var(--font-size-sm) var(--font-sans);
  color: #333;
}

.rg-notifications-list table.notifications th.icon,
.rg-notifications-list table.notifications th.bulk-select-all {
  width: 32px;
}

.rg-notifications-list table.notifications td {
  padding: var(--spacing-sm);
  border-bottom: 1px solid #EBEBEB;
  font: 400 var(--font-size-base) var(--font-sans);
  color: #333;
  vertical-align: middle;
}

.rg-notifications-list .notification-description a {
  color: #333;
  text-decoration: none;
}

.rg-notifications-list .notification-since {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  white-space: nowrap;
}

.rg-notifications-list .notification-actions {
  white-space: nowrap;
}

.rg-notifications-list .notification-actions a {
  color: #4D4D4D;
}

.rg-notifications-list .notifications-options-nav {
  display: flex;
  justify-content: center;
  margin-top: var(--spacing-md);
}

.rg-notifications-list #notification-select {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 6px var(--spacing-sm);
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
}

.rg-notifications-list .pag-data {
  text-align: center;
  color: var(--color-text-muted);
  font: 400 var(--font-size-sm) var(--font-sans);
  margin: var(--spacing-sm) 0 0;
}

/* ============================================================
   Messages (BuddyPress native Messages component — no plugin
   template override, this is pure theme/core markup being restyled).

   The thread preview/single-thread header (.preview-pane-header /
   .single-message-thread-header) splits into a Participants block and
   an "actions" icon row (delete/star/view full conversation) using two
   layered, unrelated rules: BP-Nouveau core's own
   ".bp-messages-content .actions { float:right; max-width:30% }" and
   BuddyX's "dl.thread-participants+.actions { position:absolute;
   right:20px }" (assets/css/platform.css) on top of it. Neither was ever
   adjusted for how narrow this card gets once the page drops to a single
   main column — confirmed live (390px viewport): the row of 3 icons
   (~40px each via BP-Nouveau's own .bp-icons padding, ~120px total)
   doesn't fit in the ~30%-of-340px card width (~102px) the two rules
   above leave it, and since .actions no longer participates in normal
   flow (position:absolute), the overflowing icons don't wrap onto a new
   line — the third one visibly spills past the card's own edge instead.
   Rather than patch the specific pixel math, drop the side-by-side split
   below this plugin's existing single-column breakpoint (1023px, same
   one used throughout this file) and stack actions as their own
   right-aligned row under Participants, which always has room. */
@media (max-width: 1023px) {
  .bp-messages-content .thread-participants {
    float: none;
    width: 100%;
  }

  .bp-messages-content dl.thread-participants + .actions,
  .bp-messages-content .actions {
    position: static;
    float: none;
    max-width: none;
    width: 100%;
    display: flex;
    justify-content: flex-end;
    margin-top: var(--spacing-xs);
  }
}

/* ============================================================
   Settings (BuddyPress native Settings component, wrapped by
   includes/templates/buddypress/members/single/settings.php).

   All seven settings/*.php sub-templates share the same
   form.standard-form / .settings-input / .button vocabulary, so
   this restyles that generically rather than per-screen — none of
   those sub-templates were edited.
   ============================================================ */

.rg-settings-card .screen-heading {
  font: 700 var(--font-size-h2) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-xs);
}

.rg-settings-card > form > p.info,
.rg-settings-card > form > p {
  color: var(--color-text-muted);
  font: 400 var(--font-size-base) var(--font-sans);
  margin: 0 0 var(--spacing-md);
}

.rg-settings-card label {
  display: block;
  font: 700 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  margin: var(--spacing-md) 0 var(--spacing-xs);
}

.rg-settings-card input[type="text"],
.rg-settings-card input[type="email"],
.rg-settings-card input[type="password"],
.rg-settings-card input[type="url"],
.rg-settings-card select,
.rg-settings-card textarea {
  width: 100%;
  max-width: 480px;
  padding: 10px var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  background: #F7F7F7;
  color: #737373;
}

/* !important: same BP Nouveau/theme button[type=submit] specificity
   fight documented on the Project Page's Save button. Includes a bare
   "button" selector because WP core's own Personal Data Export button
   (Export Data tab) ships with no class at all to hook a narrower
   selector onto. */
.rg-settings-card .button,
.rg-settings-card button,
.rg-settings-card input[type="submit"] {
  display: inline-block;
  background: var(--color-primary) !important;
  color: var(--color-white) !important;
  border: none !important;
  padding: 10px var(--spacing-md);
  border-radius: var(--radius-md);
  font: 600 var(--font-size-sm) var(--font-sans);
  cursor: pointer;
  margin-top: var(--spacing-sm);
}

.rg-settings-card .wp-pwd {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  flex-wrap: wrap;
  margin-top: var(--spacing-sm);
}

.rg-settings-card .wp-pwd label {
  width: 100%;
}

/* ── Desktop (1440px Figma frame; Panel C/D measured at 268px) ─ */

@media (min-width: 1024px) {
  /* A fixed 200px height with background-size:cover cropped the top and
     bottom off any cover image once the page was wider than the saved
     image's own proportions (BP's 1300x225 default is ~5.8:1; a 1920px-wide
     page at 200px tall is 9.6:1, so cover scaled the image to full width
     and cut ~65px from both edges) — the crop the member picked in the
     cover-image cropper wasn't what showed. Sizing the box by that same
     aspect ratio instead makes the box grow with the page width, so the
     whole cropped image is always visible, edge to edge. */
  .rg-profile-cover {
    height: auto;
    aspect-ratio: 1300 / 225;
  }

  .rg-profile-cover-image {
    position: absolute;
    inset: 0;
    height: auto;
  }

  .rg-profile-header {
    flex-direction: row;
    justify-content: center;
    text-align: left;
    padding: 0 var(--spacing-2xl) var(--spacing-lg);
  }

  /* Desktop density rescale: 160px/-80px (exactly half, an avatar
     straddling the cover/header boundary) down to ~0.72 ratio, same as
     the :root token rescale near the top of this file — this pair is
     desktop-only already (this whole block is @media min-width:1024px),
     so editing it in place can't affect the mobile avatar at all. */
  .rg-profile-avatar {
    margin-top: -58px;
  }

  .rg-profile-avatar img {
    width: 115px;
    height: 115px;
  }

  .rg-profile-layout {
    flex-direction: row;
    /* stretch (not flex-start): Figma's Panel_C/main/Panel_D are always the
       same explicit height regardless of how little content a given screen
       has (e.g. Teams List's Panel_C/Panel_D/content-card frames are all
       1686px tall even with just 1 team card) — the gradient content card
       is meant to fill the column, not shrink-wrap to its list items,
       which is what was leaving a plain white/gray gap below short content
       on screens like Active Members and Teams List. */
    align-items: stretch;
    padding: var(--spacing-lg) 0;
    /* Viewport-relative rather than a flat px value so this scales with the
       visitor's actual window height instead of only working at one size. */
    min-height: calc(100vh - 180px);
  }

  .rg-panel-c {
    display: flex;
    flex: 0 0 268px;
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
  }

  /* Mobile-only hamburger + dropdown — Panel_C is the permanent sidebar
     at this breakpoint, so neither of these should ever be reachable. */
  .rg-mobile-nav-toggle,
  .rg-mobile-nav-dropdown {
    display: none !important;
  }

  .rg-panel-c-link {
    justify-content: flex-start;
    /* 54px * ~0.72, same desktop density rescale as the avatar above. */
    height: 39px;
    /* Base rule's flex:1 0 auto is for the mobile row (equal-width tabs in
       a horizontal scroller) — at desktop, .rg-panel-c is now stretched
       tall to match the content card (see .rg-profile-layout above), and
       without this the 3 links would grow to fill that height as equal
       giant segments instead of sitting compact at the top the way
       Figma's Panel_C does (54px links, empty dark space below). */
    flex: 0 0 auto;
  }

  .rg-profile-main {
    flex: 1 0 0;
  }

  .rg-panel-d {
    flex: 0 0 268px;
  }

  /* Restore natural DOM order (ad, map, ad) — the mobile-only reorder above
     doesn't apply to Figma's desktop frame, which stacks ad/map/ad as-is. */
  .rg-panel-d-map {
    order: 0;
  }

  /* Desktop shows every ad slot a screen requests (Figma's mobile frames
     are the ones limited to a single ad — see the mobile-only rule above).
     Matches the wrap-based selector the mobile-hide rule now uses (see its
     own comment for why plain .rg-panel-d-ad ~ .rg-panel-d-ad stopped
     working once the first ad got wrapped for the floating treatment). */
  .rg-panel-d-ad-wrap ~ .rg-panel-d-ad {
    display: block;
  }

  /* The floating-bottom treatment is mobile-only — Figma's desktop frame
     keeps this ad in Panel D's normal flow alongside the map and the
     second ad slot, same as it always has. */
  .rg-panel-d-ad-wrap {
    position: static;
    left: auto;
    right: auto;
    bottom: auto;
    z-index: auto;
  }

  /* Back in normal flow alongside the other ad/map cards — match their
     shared sizing/radius instead of the mobile floating banner's
     compact-overlay treatment above. !important needed here too: the
     mobile rule's own !important (itself needed to beat the BuddyX
     <div> border-radius reset — see that rule's comment) would
     otherwise keep winning at this width purely on !important,
     regardless of this selector's identical specificity. */
  .rg-panel-d-ad-wrap .rg-panel-d-ad {
    min-height: 160px;
    border-radius: var(--radius-lg) !important;
  }

  /* Placeholder creative back to the full card size — see its own
     comment above for why this is a class, not inline styles. */
  .rg-ad-placeholder {
    border-radius: var(--radius-lg) !important;
    min-height: 160px;
  }

  /* The floating banner's own flush-corner override (mobile-only) would
     otherwise keep winning here too, same !important-vs-!important
     reasoning as .rg-panel-d-ad-wrap .rg-panel-d-ad just above. */
  .rg-panel-d-ad-wrap .rg-ad-placeholder {
    border-radius: var(--radius-lg) !important;
  }

  /* Let the shared content card absorb the extra height .rg-profile-main
     now gets from align-items:stretch above, instead of shrink-wrapping to
     its list items and leaving the stretched space blank. flex-basis:auto
     (not 0) so it never shrinks below its natural content size on tall
     content — it only grows on short content. On Profile (About card +
     this Roles card as two separate children) only the Roles card grows,
     which is the last/bottom one, so extra space lands at the bottom of
     the page as expected rather than being split awkwardly between both. */
  .rg-profile-main .rg-card-gradient {
    flex: 1 1 auto;
  }

  /* Profile page specifically: now that .rg-profile-page has a real
     background (see above), the Roles card no longer needs to stretch to
     hide a white gap beneath it — Figma's own Roles frame (58:747) is a
     tight ~435px hugging its content, with plain page background below it,
     not a stretched card. Overrides the general rule above for this one
     screen only; Teams List/Projects List/etc. still rely on the stretch
     since they haven't been re-verified against a real background fix. */
  .rg-profile-detail-page .rg-profile-main .rg-card-gradient {
    flex: 0 1 auto;
  }

  /* Side by side at desktop — there's room for both columns here, unlike
     mobile (see the stacked base rule above). Centered with capped widths
     rather than stretched: at wide viewports, two columns forced to split
     100% of the available width each grew far wider than their content
     needed (long sliders, name-to-star-rating gaps stretched apart by the
     extra room) — capping width and centering lets the row settle to a
     compact, deliberate size with real negative space around it instead. */
  .rg-profile-roles-columns {
    flex-direction: row;
    justify-content: center;
    align-items: flex-start;
    /* Was calc(var(--spacing-xl) * 2) — double the section's own side
       padding. Matched to the plain side padding instead, so the gap
       between the two cards and the margin around them read as the same
       breathing room rather than the gap looking like the "real" spacing
       and the outer margin an afterthought. */
    gap: var(--spacing-xl);
  }

  /* Each column becomes its own glass card floating on the section's
     gradient backdrop, instead of two plain columns sharing the section's
     own border/shadow — the gap between them now does the job the old
     border-right/border-bottom divider was doing, so that's dropped. */
  .rg-profile-roles-col {
    /* Was flex: 0 1 480px — a fixed basis that doesn't grow, so on any
       main-canvas wider than ~992px (2 cards + gap + padding) the leftover
       width had nowhere to go but the outer edges via justify-content:
       center below, producing a side gutter far wider than the gap between
       the cards (measured 147px of gutter against a 32px gap on a common
       desktop width, and a full 972px of dead gutter against a 32px gap
       measured on a 3840px-wide 4K/42" display) — not because Panel C/D's
       own width was leaking in (the main canvas here was already correctly
       excluding them), just unclaimed slack inside an already-correct
       canvas. flex-grow:1 lets both cards claim that slack equally
       instead, so the gutter always collapses down to exactly the
       section's own padding — which already equals the gap — with no
       leftover to center, on any monitor width. A max-width here (tried
       first) just relocates the same problem: once both cards hit the
       cap, leftover space piles up at the edges again exactly as before,
       only later. The card itself is deliberately uncapped now — see the
       widget-width rule just below for where the actual "don't let
       content get absurdly wide" cap now lives instead. */
    flex: 1 1 0;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    /* !important needed here too, same BP-Nouveau/BuddyX <div> reset as
       the consolidated fix near the top of this file — this one just uses
       its own --radius-xl rather than the shared --radius-lg, so it isn't
       covered by that block. */
    border-radius: var(--radius-xl) !important;
    box-shadow: var(--shadow-lg);
    padding: var(--spacing-lg);
  }

  /* Issue 5: another user's profile has no Role Proficiency widget to pair
     with Ratings, so this column renders alone — flex-grow:1 above would
     otherwise let it claim the WHOLE row (there's no sibling to split
     with), stretching the card itself edge-to-edge even though its inner
     widget is already capped below. Pin it to the same width either
     column would get if a sibling WERE present (container minus one gap,
     split in two), so a solo Ratings card on someone else's profile comes
     out the same size as the left column on your own — not just its text
     capped inside an oversized card, the whole card matches. */
  .rg-profile-roles-col:only-child {
    flex: 0 1 auto;
    width: calc((100% - var(--spacing-xl)) / 2);
  }

  /* The glass card itself (above) is intentionally uncapped so it grows to
     fill the canvas edge-to-edge alongside its gutter — but the actual
     widget content (role rows, the proficiency slider which scales to
     calc(100% - 90px) of its own width) would look genuinely broken
     stretched to the 1500px+ a card can reach on a 4K/42" display: a
     slider that long, or a huge gap between a role name and its star
     rating, isn't "using the space well," it's just illegible. Capping
     the widget and centering it inside its (now much roomier) card keeps
     the card visually proportional to the screen while keeping the
     interactive content itself at a sane, comfortable width. */
  .rg-profile-roles-col .rg-role-display-widget,
  .rg-profile-roles-col .rg-role-proficiency-widget {
    max-width: 480px;
    margin-left: auto;
    margin-right: auto;
  }

  /* The gradient stays as a colorful backdrop behind the glass cards, but
     loses its own border/shadow/tight padding so it reads as a backdrop
     the cards pop out of, not a second card wrapping the first ones. */
  .rg-profile-roles.rg-card-gradient {
    border: none;
    box-shadow: none;
    padding: var(--spacing-2xl) var(--spacing-xl);
  }
}

/* ── Wide-desktop container width ──────────────────────────────
   BuddyX's own grid is Bootstrap-style and stops growing at the
   "xl" breakpoint: .container caps at max-width:1170px for every
   viewport ≥1200px, all the way up through 1920px+ (confirmed via
   computed-style diagnostics — its own --container-xxl:1400px
   token exists in _custom-properties.css but is never actually
   applied at any breakpoint). On a 1920px/1080p screen that leaves
   ~750px of unused side margin, and since .rg-panel-c/.rg-panel-d
   are fixed at 268px while .rg-profile-main is flex:1 (fills
   whatever's left), that lost width comes straight out of the main
   column — the reason card grids (Team Page's member list, the
   Members Active directory, etc.) were only ever rendering a single
   column despite having grid-template-columns:
   repeat(auto-fill, minmax(190px, 1fr)) that would happily lay out
   3+ columns given the room. Scoped to BuddyPress pages only (not
   the theme's blog/page templates, which may genuinely want a
   narrower reading width) via the body.buddypress class BP adds
   everywhere. */
@media (min-width: 1400px) {
  body.buddypress .container {
    max-width: 1600px;
  }
}

/* ── Beta Feedback page ──────────────────────────────────────────────── */

.rg-feedback-intro {
  color: var(--color-text-muted);
  margin: 8px 0 20px;
  line-height: 1.5;
}

.rg-feedback-notice {
  padding: 12px var(--spacing-md);
  border-radius: var(--radius-md);
  margin-bottom: 20px;
  font-weight: 600;
}

.rg-feedback-notice-success {
  background: #d4edda;
  color: #155724;
}

.rg-feedback-notice-error {
  background: #f8d7da;
  color: #721c24;
}

.rg-feedback-field {
  margin-bottom: 22px;
}

.rg-feedback-label {
  display: block;
  font-weight: 700;
  color: var(--color-text-primary);
  margin-bottom: 10px;
  font-size: 1.05rem;
}

.rg-feedback-help {
  color: var(--color-text-muted);
  font-size: 0.875rem;
  margin: 0 0 8px;
}

/* Big friendly category cards instead of a technical dropdown */
.rg-feedback-category-options {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.rg-feedback-category-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
  flex: 1 1 220px;
}

.rg-feedback-category-option:hover {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
}

.rg-feedback-category-option input[type="radio"] {
  accent-color: var(--color-primary);
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.rg-feedback-category-option:has(input:checked) {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
}

.rg-feedback-category-emoji {
  font-size: 1.4rem;
  line-height: 1;
}

.rg-feedback-category-text {
  font-weight: 600;
  color: var(--color-text-primary);
}

.rg-feedback-form textarea,
.rg-feedback-form input[type="file"] {
  width: 100%;
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 1rem;
  box-sizing: border-box;
}

.rg-feedback-form textarea {
  resize: vertical;
}

.rg-feedback-submit-btn {
  border: none;
  cursor: pointer;
  font-size: 1rem;
}

/* Feedback history list */
.rg-feedback-history {
  margin-top: 24px;
}

.rg-feedback-history-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.rg-feedback-history-item {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 16px;
}

.rg-feedback-history-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

.rg-feedback-history-cat {
  font-weight: 600;
  color: var(--color-text-primary);
}

.rg-feedback-history-status {
  font-size: 0.8rem;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  white-space: nowrap;
}

.rg-feedback-status-fixed {
  background: #d4edda;
  color: #155724;
}

.rg-feedback-status-wont_fix,
.rg-feedback-status-duplicate {
  background: var(--color-border);
  color: var(--color-text-muted);
}

.rg-feedback-history-message {
  color: var(--color-text-primary);
  line-height: 1.5;
  margin: 0 0 8px;
}

.rg-feedback-history-screenshot-link img {
  max-width: 160px;
  max-height: 120px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  display: block;
  margin-bottom: 8px;
}

.rg-feedback-history-date {
  color: var(--color-text-muted);
  font-size: 0.8rem;
}

/* ============================================================
   Auth pages — Login (includes/rg-landing-page.php) & Register
   (includes/templates/buddypress/members/register.php)
   Matches Figma "Login" (51:1626) / "Register" (75:369) frames.
   ============================================================ */

/* Background: the shared landing-page photo, blurred — same technique as
   #rg-landing-root::before / #rg-about-root::before in rg-landing-page.php
   (scaled 110% so the blur's edge-softening never reveals an unblurred
   fringe at the container's edge), added 2026-10 so these pages don't read
   as a flat, empty teal field around a small white card. The actual photo
   URL arrives via the --rg-auth-bg custom property, set per-request by
   rg_inject_auth_page_bg_style() in rg-landing-page.php (wp_head) — static
   CSS here can't reach rg_landing_bg_image_id itself. #071f29 fallback
   matches this rule's own previous flat color, for the (practically never
   hit) case that custom property somehow isn't set.

   position:fixed (not absolute), 2026-10: .rg-auth-page itself lives
   inside BuddyX's own .container (max-width:1170px — see the theme's own
   markup, site-wrapper > .container > main > .entry-content), unlike
   Component A (the nav bar), which renders outside that container at full
   width. An absolutely-positioned ::before only ever covers ITS OWN
   parent's box, so it was filling just that narrower centered column
   instead of the full viewport Component A spans — exactly what was
   reported ("not filling the entire screen... compare to the width of
   Component A"). Fixed positioning anchors to the viewport instead,
   sidestepping the container entirely; inset:-5% + scale(1.1) still apply,
   just relative to the viewport now. Already consistent with the "fixed"
   background-attachment rg_landing_bg_style() has always used for the
   landing/about pages' own (viewport-sized, so this didn't matter there)
   backgrounds. overflow:hidden dropped from .rg-auth-page — no longer
   needed now that the bg layer isn't clipped to this box. */
.rg-auth-page {
  position: relative;
  min-height: 70vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--spacing-2xl) var(--spacing-md);
  margin: calc(-1 * var(--spacing-lg)) calc(-1 * var(--spacing-md)) 0;
}

.rg-auth-page::before {
  content: '';
  position: fixed;
  inset: -5%;
  background: var(--rg-auth-bg, #071f29);
  filter: blur(16px);
  transform: scale(1.1);
  z-index: 0;
}

/* Dark overlay, same as the landing/about pages — keeps the photo from
   reading as a bright, distracting field around the (opaque white, so
   unaffected either way) .rg-auth-card. Fixed for the same reason as
   ::before above — otherwise it'd only darken the narrower .container
   column, leaving the full-bleed photo on either side at full brightness. */
.rg-auth-page::after {
  content: '';
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 0;
}

.rg-auth-card {
  position: relative;
  z-index: 1;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--spacing-lg);
  width: 100%;
  max-width: 600px;
}

.rg-auth-title {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-lg);
}

/* BP's own notice aside (bp_nouveau_template_notices()) — info on a fresh
   visit, error after a failed validation. Same treatment as
   .rg-notifications-list .bp-feedback. */
.rg-auth-card .bp-feedback {
  background: var(--color-primary-light);
  border-left: 4px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: var(--spacing-sm) var(--spacing-md);
  color: var(--color-text-primary);
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  font: 400 var(--font-size-base) var(--font-sans);
  margin: 0 0 var(--spacing-lg);
}

.rg-auth-card .bp-feedback.error {
  background: #FBE1E1;
  border-left-color: #C0392B;
}

.rg-auth-card .bp-feedback p {
  margin: 0;
}

.rg-auth-card .bp-feedback .bp-icon {
  flex-shrink: 0;
}

/* WP core's password-strength-meter JS (enqueued by BP-Nouveau on the
   register page) ships its "Caps Lock is on" warning SVG unstyled outside
   wp-admin — no wp-admin/css/common.css on the frontend to size it, so it
   inherits the field's full width. Constrain it to the icon size wp-admin
   itself uses.

   display:none is the actual fix here, not just tidiness: wp-admin's own
   common.css (again, not loaded on the frontend) is also what hides this
   element by default — user-profile.js's bindCapsLockWarning() creates it
   and appends it WITHOUT calling .hide(), relying entirely on that missing
   stylesheet for the default-hidden state. Without it the warning shows
   unconditionally on page load, not only while caps lock is actually on.
   jQuery's .show()/.hide() toggle the inline style directly, so this base
   rule only needs to cover the hidden state — the icon/text spans below
   are inline-level on their own and don't need the parent to be flex to
   sit on one line, which sidesteps having to fight whatever display value
   .show() decides to set inline. */
.rg-auth-card .caps-warning {
  display: none;
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: var(--spacing-xs) 0;
}

.rg-auth-card .caps-warning .caps-icon {
  display: inline-flex;
  vertical-align: middle;
  margin-right: var(--spacing-xs);
}

.rg-auth-card .caps-warning svg {
  width: 16px;
  height: 16px;
  vertical-align: middle;
  fill: currentColor;
}

.rg-auth-divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--spacing-lg) 0 var(--spacing-md);
}

.rg-login-extras {
  text-align: center;
  font-size: var(--font-size-sm);
}

.rg-auth-link-primary,
.rg-auth-link-muted {
  display: inline-block;
  text-decoration: none;
  font: 600 var(--font-size-sm) var(--font-sans);
}

.rg-auth-link-primary {
  color: var(--color-primary);
  margin-bottom: var(--spacing-sm);
}

.rg-auth-link-muted {
  color: var(--color-text-muted);
  font-weight: 400;
  font-size: 11px;
}

/* Shared field styling for both #loginform (wp_login_form) and
   #signup-form's account-details fields (bare label+input pairs, not
   wrapped in a container BP's own markup doesn't provide one for). */
.rg-auth-card #loginform label,
.rg-auth-card #basic-details-section > label,
.rg-auth-card .user-pass1-wrap > label,
.rg-auth-card .user-pass2-wrap label {
  display: block;
  font: 600 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-xs);
}

.rg-auth-card #loginform input[type="text"],
.rg-auth-card #loginform input[type="password"],
.rg-auth-card #basic-details-section input[type="text"],
.rg-auth-card #basic-details-section input[type="email"],
.rg-auth-card #profile-details-section input[type="text"],
.rg-auth-card .password-entry,
.rg-auth-card .password-entry-confirm {
  width: 100%;
  padding: 10px var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
  background: var(--color-white);
  box-sizing: border-box;
  margin: 0 0 var(--spacing-md);
}

/* #profile-details-section (the xprofile field loop, e.g. "Name") was
   missing from the rule above, so it fell through unopposed to BuddyPress
   core's own .standard-form input[required]:invalid rule
   (bp-nouveau/css/buddypress.min.css) — a hardcoded red border on every
   required-but-empty field, including ones nobody has touched yet. The
   account-details fields above never showed this only because this rule's
   plain border already outranked it; extending the same rule here is the
   actual fix, not a new :invalid override. */
.rg-auth-card #loginform input[type="text"]:focus,
.rg-auth-card #loginform input[type="password"]:focus,
.rg-auth-card #basic-details-section input[type="text"]:focus,
.rg-auth-card #basic-details-section input[type="email"]:focus,
.rg-auth-card #profile-details-section input[type="text"]:focus,
.rg-auth-card .password-entry:focus,
.rg-auth-card .password-entry-confirm:focus {
  border-color: var(--color-primary);
  outline: none;
}

.rg-auth-card #loginform .forgetmenot {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  font: 400 var(--font-size-base) var(--font-sans);
  margin-bottom: var(--spacing-md);
}

.rg-auth-card #loginform input[type="checkbox"] {
  accent-color: var(--color-primary);
}

/* Primary submit — wp_login_form()'s <input type=submit> and BP's own
   bp_nouveau_submit_button() <button>, same treatment as the Figma CTA. */
.rg-auth-card #loginform .submit input[type="submit"],
.rg-auth-card .rg-auth-submit button,
.rg-auth-card .rg-auth-submit input[type="submit"] {
  display: block;
  width: 100%;
  padding: var(--spacing-md);
  background: var(--color-primary) !important;
  color: var(--color-white) !important;
  border: none !important;
  border-radius: var(--radius-md);
  font: 600 var(--font-size-lg) var(--font-sans);
  cursor: pointer;
  transition: background var(--transition-base);
}

.rg-auth-card #loginform .submit input[type="submit"]:hover,
.rg-auth-card .rg-auth-submit button:hover,
.rg-auth-card .rg-auth-submit input[type="submit"]:hover {
  background: var(--color-primary-dark) !important;
}

/* Register: section headers + password strength meter */
.rg-auth-card .register-section .bp-heading {
  font: 700 var(--font-size-h3) var(--font-sans);
  color: var(--color-text-primary);
  margin: var(--spacing-lg) 0 var(--spacing-md);
}

.rg-auth-card .register-section:first-of-type .bp-heading {
  margin-top: 0;
}

.rg-auth-card #pass-strength-result {
  display: inline-block;
  padding: 2px var(--spacing-sm);
  border-radius: var(--radius-sm);
  font: 600 var(--font-size-sm) var(--font-sans);
  margin: calc(-1 * var(--spacing-sm)) 0 var(--spacing-xs);
}

.rg-auth-card #pass-strength-result.short,
.rg-auth-card #pass-strength-result.bad {
  background: #FBE1E1;
  color: #C0392B;
}

.rg-auth-card #pass-strength-result.good {
  background: #FDEFD3;
  color: #92610C;
}

.rg-auth-card #pass-strength-result.strong {
  background: #D9EDD9;
  color: #337333;
}

.rg-auth-card .description.indicator-hint {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: 0 0 var(--spacing-md);
}

@media (min-width: 1024px) {
  .rg-auth-card {
    max-width: 859px;
    padding: var(--spacing-xl);
  }
}

/* ── First-time onboarding tour (js/rg-onboarding-tour.js) ──────────────
   High z-index (above .rg-invite-popup-overlay's 100000) since the tour
   should always win if it and any other overlay were ever somehow both
   on screen. Deliberately doesn't block clicks on the rest of the page
   (no pointer-events trap) — it's a guide, not a modal gate. */

.rg-tour-root {
  position: fixed;
  inset: 0;
  z-index: 100010;
  pointer-events: none;
}

.rg-tour-scrim {
  position: fixed;
  inset: 0;
  background: rgba(7, 31, 41, 0.55);
}

.rg-tour-highlight {
  position: fixed;
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 9999px rgba(7, 31, 41, 0.55), 0 0 0 3px var(--color-accent-mid);
  transition: top 0.25s ease, left 0.25s ease, width 0.25s ease, height 0.25s ease;
}

.rg-tour-tooltip {
  position: fixed;
  pointer-events: auto;
  width: 280px;
  max-width: calc(100vw - 24px);
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--spacing-md);
  font: 400 var(--font-size-base) var(--font-sans);
  color: var(--color-text-primary);
}

.rg-tour-tooltip--centered {
  width: 320px;
}

.rg-tour-tooltip-arrow {
  position: absolute;
  width: 14px;
  height: 14px;
  background: var(--color-white);
  transform: rotate(45deg);
}

.rg-tour-tooltip-arrow--down {
  top: -7px;
}

.rg-tour-tooltip-arrow--up {
  bottom: -7px;
}

.rg-tour-tooltip-step {
  font: 700 var(--font-size-label) var(--font-sans);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-accent-mid);
  margin-bottom: var(--spacing-xs);
}

.rg-tour-tooltip-title {
  font: 700 var(--font-size-lg) var(--font-sans);
  margin-bottom: var(--spacing-xs);
}

.rg-tour-tooltip-text {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  line-height: 1.5;
  margin-bottom: var(--spacing-md);
}

.rg-tour-tooltip-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm);
}

/* Single-button variant (js/rg-beta-feature-tour.js's "Got it"-only
   popup, no Skip counterpart) — plain space-between with one child
   aligns it flex-start, reading as oddly left-stranded for a single CTA. */
.rg-tour-tooltip-actions--single {
  justify-content: flex-end;
}

.rg-tour-btn-skip {
  background: none;
  border: none;
  padding: 0;
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  cursor: pointer;
  text-decoration: underline;
}

.rg-tour-btn-skip:hover {
  color: var(--color-text-primary);
}

.rg-tour-btn-next {
  background: var(--color-accent-mid);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-md);
  padding: var(--spacing-xs) var(--spacing-md);
  font: 700 var(--font-size-sm) var(--font-sans);
  cursor: pointer;
}

.rg-tour-btn-next:hover {
  background: var(--color-accent-start);
}

/* ── Cover image reposition/crop tool (js/rg-cover-image-crop.js) ───────
   Unlike the onboarding tour's overlay, this one genuinely blocks the
   rest of the page — crop precision matters, so accidental clicks
   elsewhere shouldn't be able to dismiss or interfere with it. */

#rg-cover-crop-overlay {
  position: fixed;
  inset: 0;
  z-index: 100020;
  background: rgba(7, 31, 41, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-md);
}

#rg-cover-crop-panel {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--spacing-lg);
  max-width: min(92vw, 1000px);
  max-height: 92vh;
  overflow-y: auto;
}

#rg-cover-crop-panel h3 {
  font: 700 var(--font-size-lg) var(--font-sans);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-xs);
}

.rg-cover-crop-hint {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-text-muted);
  margin: 0 0 var(--spacing-md);
}

#rg-cover-crop-stage {
  max-width: 100%;
  overflow: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  line-height: 0;
}

/* Jcrop's coordinate math assumes the image renders at its true natural
   pixel size — a common theme-wide `img { max-width: 100%; height: auto }`
   reset would silently break that 1:1 mapping, so this is pinned
   explicitly rather than relying on the absence of such a rule. */
#rg-cover-crop-image {
  max-width: none !important;
  height: auto !important;
  display: block;
}

#rg-cover-crop-status {
  font: 400 var(--font-size-sm) var(--font-sans);
  color: var(--color-primary);
  min-height: 1.4em;
  margin: var(--spacing-sm) 0 0;
}

.rg-cover-crop-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--spacing-md);
  margin-top: var(--spacing-sm);
}
