@font-face {
  font-family: 'InspireTWDC';
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url('../assets/fonts/InspireTWDC-Roman.woff2') format('woff2'),
       local('InspireTWDC Roman'), local('InspireTWDC-Roman'), local('Inspire TWDC Roman'), local('InspireTWDC');
}
@font-face {
  font-family: 'InspireTWDC';
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url('../assets/fonts/InspireTWDC-Medium.woff2') format('woff2'),
       local('InspireTWDC Medium'), local('InspireTWDC-Medium'), local('Inspire TWDC Medium');
}
@font-face {
  font-family: 'InspireTWDC';
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  src: url('../assets/fonts/InspireTWDC-Heavy.woff2') format('woff2'),
       local('InspireTWDC Bold'), local('InspireTWDC-Bold'), local('Inspire TWDC Bold');
}
@font-face {
  font-family: 'InspireTWDC';
  font-weight: 800;
  font-style: normal;
  font-display: swap;
  src: url('../assets/fonts/InspireTWDC-Heavy.woff2') format('woff2'),
       local('InspireTWDC Heavy'), local('InspireTWDC-Heavy'), local('Inspire TWDC Heavy');
}
@font-face {
  font-family: 'InspireTWDC';
  font-weight: 900;
  font-style: normal;
  font-display: swap;
  src: url('../assets/fonts/InspireTWDC-Black.woff2') format('woff2'),
       local('InspireTWDC Black'), local('InspireTWDC-Black'), local('Inspire TWDC Black');
}
@font-face {
  font-family: 'MultiplaneTWDC Display';
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url('../assets/fonts/MultiplaneTWDC-Display-Medium.woff2') format('woff2'),
       local('MultiplaneTWDC Display Medium'), local('MultiplaneTWDC_Display-Medium'), local('MultiplaneTWDC Display');
}

:root {
  /* EDL Primary — Gray */
  --gray-95:  #171C20;
  --gray-90:  #222A30;
  --gray-80:  #3A4652;
  --gray-70:  #526374;
  --gray-60:  #6A8095;
  --gray-50:  #8498A9;
  --gray-40:  #9EB0BD;
  --gray-30:  #B8C7D0;
  --gray-20:  #D4DEE3;
  --gray-15:  #E2E9EC;
  --gray-10:  #EFF3F5;
  --gray-05:  #F7F9FA;

  /* EDL Primary — Indigo */
  --indigo-95: #231267;
  --indigo-80: #2F139F;
  --indigo-70: #3611C8;
  --indigo-60: #3B0DF2;
  --indigo-50: #5432FB;
  --indigo-40: #705CFF;
  --indigo-30: #928AFF;
  --indigo-20: #B8B8FF;
  --indigo-15: #CFCFFF;
  --indigo-10: #E6E6FF;
  --indigo-05: #F3F3FF;

  /* EDL Extended — 50 level */
  --blue-50:   #1570C8;
  --teal-50:   #00838F;
  --green-50:  #178255;
  --purple-50: #7B2CB8;
  --cyan-50:   #0B6E7A;
  --slate-50:  #5B6F80;

  /* EDL Semantic */
  --green-70:  #059D6D;
  --red-70:    #A00032;

  /* EDL Toast palette (from EDL Toast Figma spec, node 15094:75972) */
  --green-60:  #00C274;
  --red-60:    #C20031;
  --orange-70: #D26700;
  --gray-95:   #171C20;

  /* Aliases */
  --white:    #FFFFFF;
  --black:    #000000;
  --input-border: var(--border-input);
  --ff: 'InspireTWDC', 'Inspire TWDC', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* ─── EDL Semantic theme tokens (Light defaults) ───
     Dark overrides live in [data-theme="dark"] below. Palette tokens above
     remain absolute colors; semantic tokens below remap to theme meaning. */

  /* Surfaces */
  --bg-app:            var(--gray-10);      /* page background behind cards */
  --bg-surface:        var(--white);        /* cards, tables, popovers, inputs */
  --bg-surface-raised: var(--white);        /* elevated dropdowns/menus */
  --bg-hover:          var(--gray-10);      /* row/button hover */
  --bg-hover-soft:     var(--gray-05);      /* softer hover */

  /* Nav */
  --nav-bg:            var(--indigo-70);
  --nav-link:          var(--indigo-10);
  --nav-link-active:   var(--white);
  --nav-divider:       var(--indigo-30);

  /* Text */
  --text-primary:      var(--gray-95);
  --text-secondary:    var(--gray-70);
  --text-muted:        var(--gray-60);
  --text-placeholder:  var(--gray-40);
  --text-on-brand:     var(--white);

  /* Borders */
  --border-subtle:     var(--gray-15);      /* hairline dividers */
  --border-default:    var(--gray-20);      /* card outline, table rows */
  --border-input:      var(--gray-30);      /* form controls */

  /* Brand / interactive */
  --brand:             var(--indigo-70);    /* solid button bg, checked checkbox */
  --brand-hover:       var(--indigo-80);
  --brand-text:        var(--indigo-70);    /* link text, outline button text */
  --brand-text-hover:  var(--indigo-80);
  --brand-bg-soft:     var(--indigo-05);    /* ghost hover bg */
  --brand-bg-selected: var(--indigo-10);    /* selected option bg */
  --brand-focus-ring:  var(--indigo-50);
  --brand-disabled-bg: #D9D9E8;
  --brand-disabled-fg: #9B9BB3;

  /* Shadows */
  --shadow-menu:  0 6px 24px rgba(16,17,19,0.14), 0 1px 3px rgba(16,17,19,0.10);
  --shadow-pop:   0 6px 20px rgba(0,0,0,0.10);
  --shadow-tip:   0 1px 3px rgba(16,17,19,0.24);
  --shadow-drawer: 4px 0 16px rgba(0,0,0,0.08);
  --overlay-scrim: rgba(23,28,32,0.40);

  /* R58 — Responsive content-container model (V4 list pages: Users,
     Roles, Teams). The deliberate design-system maximum content width
     a list card/table grows to before it stops and centers with equal
     outer whitespace. 1920px matches the ADS pilot's own upper
     desktop target (see `ads-design-system/design.md`, "Pilot
     constraint: 1440px and 1920px desktop") — the largest width the
     table/column system was actually designed against, so growth is
     deliberately held there rather than stretching further at 2560+. */
  --v4-content-max-width: 1920px;
}

/* ─── EDL Dark Theme ───
   Blue-toned dark surfaces (EDL dark navy family) for cards, tables, nav,
   popovers. Borders/dividers carry the same blue undertone. Interactive
   text uses EDL Indigo/20 for readable contrast on navy surfaces. */
[data-theme="dark"] {
  color-scheme: dark;

  --bg-app:            #0B1220;                         /* deep navy app bg */
  --bg-surface:        #131E33;                         /* navy card / table */
  --bg-surface-raised: #1E2B44;                         /* elevated menus/popovers */
  --bg-hover:          rgba(255,255,255,0.06);
  --bg-hover-soft:     rgba(255,255,255,0.04);

  --nav-bg:            #0B1424;                         /* deepest navy, top nav */
  --nav-link:          #D4DEE3;
  --nav-link-active:   #FFFFFF;
  --nav-divider:       #263654;

  --text-primary:      #FFFFFF;
  --text-secondary:    #A5B6CC;                         /* blue-tinted secondary */
  --text-muted:        #A5B6CC;
  --text-placeholder:  #8B9CB3;
  --text-on-brand:     #FFFFFF;

  --border-subtle:     #1F2C47;                         /* hairline row rule */
  --border-default:    #263654;                         /* card outline / table rows */
  --border-input:      #34466A;

  --brand:             var(--indigo-50);
  --brand-hover:       var(--indigo-40);
  --brand-text:        var(--indigo-20);
  --brand-text-hover:  var(--indigo-15);
  --brand-bg-soft:     rgba(184,184,255,0.10);
  --brand-bg-selected: rgba(184,184,255,0.16);
  --brand-focus-ring:  var(--indigo-30);
  --brand-disabled-bg: #1A2540;
  --brand-disabled-fg: #5A6C85;

  --shadow-menu:  0 8px 28px rgba(0,0,0,0.55), 0 1px 3px rgba(0,0,0,0.45);
  --shadow-pop:   0 6px 20px rgba(0,0,0,0.55);
  --shadow-tip:   0 1px 3px rgba(0,0,0,0.45);
  --shadow-drawer: 4px 0 16px rgba(0,0,0,0.50);
  --overlay-scrim: rgba(0,0,0,0.60);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Reserve the scrollbar gutter permanently so the page's available width
   (and everything centered/right-anchored within it, e.g. .tbar CTAs)
   doesn't shift by the scrollbar's width when switching between tabs
   with different content lengths (Users' 610-row table scrolls; Roles'
   11-row table and Teams often don't). Without this, .page/.card resolve
   against document.documentElement.clientWidth, which differs by the
   scrollbar's width depending on which tab is active. */
html { scrollbar-gutter: stable; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body { font-family: var(--ff); color: var(--text-primary); background: var(--bg-app); line-height: 1; }
a { text-decoration: none; color: inherit; }
button { border: none; background: none; cursor: pointer; font-family: inherit; font-size: inherit; color: inherit; line-height: 1; transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease; }
:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; }
select:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 0; }
input, select { font-family: inherit; }
table { border-spacing: 0; border-collapse: collapse; }

/* ─── NAV ─── 48px, bg indigo-70, pr-28 (Figma 368:57130) ─── */
.nav { display: flex; align-items: center; justify-content: space-between; height: 48px; background: var(--nav-bg); padding-right: 28px; position: sticky; top: 0; z-index: 100; }
.nav-l { display: flex; align-items: center; height: 100%; overflow: hidden; }
.nav-mod { display: flex; gap: 8px; height: 100%; align-items: center; padding: 10px 16px 10px 48px; }
/* Center cluster holds the primary nav links. In EDL Light/Dark this sits
   directly to the right of the logo group (legacy layout). ADS Preview
   overrides this to center the cluster in the bar (see ADS Preview block).
   `margin-right: auto` claims the slack so EDL's three-sibling flex
   still pins utilities to the right edge without redistributing space. */
.nav-c { display: flex; gap: 8px; height: 100%; align-items: center; margin-right: auto; }
.nav-logo-group { display: flex; gap: 12px; align-items: center; flex-shrink: 0; }
.nav-logo-link { display: flex; align-items: center; flex-shrink: 0; line-height: 0; border-radius: 4px; }
.nav-logo-link:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 3px; }
.nav-logo-img { width: 145px; height: 26px; display: block; }
.nav-divider { width: 1px; height: 30px; background: var(--nav-divider); flex-shrink: 0; }
.nav-a { display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 48px; padding: 0 12px; font-size: 16px; font-weight: 400; line-height: 21px; color: var(--nav-link); white-space: nowrap; }
.nav-a:hover { color: var(--nav-link-active); }
.nav-a.on { color: var(--nav-link-active); font-weight: 800; }
.nav-chev { flex-shrink: 0; width: 16px; height: 16px; }
.nav-r { display: flex; align-items: center; height: 100%; }
.nav-r-btn { display: inline-flex; align-items: center; justify-content: center; height: 48px; padding: 0 12px; border: none; background: none; cursor: pointer; color: var(--nav-link); }
.nav-avatar-img { width: 24px; height: 24px; border-radius: 50%; display: block; }
/* Ads DS-only icon glyphs.
   `.nav-ico`     — inline SVG used by the Ads bell + three-dot icons; the
                     legacy bell (`<img class="nav-bell-img">`) is the EDL
                     Light/Dark glyph and is shown by default.
   `.nav-r-btn-dots` — entire "More" button, ADS Preview only.
   Both are hidden in EDL themes so EDL Light/Dark render with their
   original bell + avatar pair only. ADS Preview override unhides them. */
.nav-r-btn .nav-ico { display: none; }
.nav-r-btn-dots { display: none; }

/* ═══ User menu (top-right profile dropdown) ═══ */
.user-menu { position: relative; display: inline-flex; height: 100%; }
.user-menu-pop {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 240px;
  background: var(--bg-surface);
  border-radius: 8px;
  box-shadow: var(--shadow-menu);
  padding: 4px 0;
  z-index: 200;
  font-family: var(--ff);
  display: none;
}
.user-menu.open .user-menu-pop { display: block; }

.user-menu-hdr { padding: 10px 16px 12px; }
.user-menu-name { font-size: 14px; font-weight: 700; line-height: 20px; color: var(--text-primary); letter-spacing: 0; }
.user-menu-email { margin-top: 2px; font-size: 13px; font-weight: 400; line-height: 18px; color: var(--text-muted); letter-spacing: 0; }

.user-menu-sep { height: 1px; background: var(--border-subtle); margin: 4px 0; }

.user-menu-row {
  position: relative;
  display: flex;
  align-items: center;
  height: 36px;
  padding: 0 16px;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--text-primary);
  cursor: pointer;
  user-select: none;
  outline: none;
}
.user-menu-row:hover,
.user-menu-row:focus-visible { background: var(--bg-hover); }
.user-menu-row:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: -2px; }
.user-menu-label { flex: 1 1 auto; min-width: 0; }
.user-menu-value { color: var(--text-muted); font-size: 14px; font-weight: 400; line-height: 20px; }
.user-menu-chev { flex-shrink: 0; color: var(--text-muted); }

/* Theme submenu — anchored to the left of the parent row.
   Column flex guarantees both options (EDL Light + EDL Dark) stack fully,
   and the elevated z-index / isolation keep the popup on top of any
   sibling stacking contexts (search, table cells, etc.). */
.user-menu-sub {
  position: absolute;
  top: -4px;
  right: calc(100% + 4px);
  min-width: 140px;
  background: var(--bg-surface);
  border-radius: 8px;
  box-shadow: var(--shadow-menu);
  padding: 4px 0;
  display: none;
  flex-direction: column;
  z-index: 9999;
  isolation: isolate;
}
.user-menu-row.has-sub:hover > .user-menu-sub,
.user-menu-row.has-sub[aria-expanded="true"] > .user-menu-sub,
.user-menu-sub:hover { display: flex; }

/* Theme submenu items inherit surface/hover/text tokens from the page-level
   theme (i.e. the <html> element), not from their own data-theme attributes.
   Without this reset, an item like <div data-theme="dark"> would pick up
   --bg-surface:#131E33 from the [data-theme="dark"] token block and appear
   dark navy even while the page is in EDL Light mode. */
.user-menu-sub .user-menu-sub-item {
  --bg-surface:   inherit;
  --bg-hover:     inherit;
  --text-primary: inherit;
}

.user-menu-sub-item {
  display: flex;
  align-items: center;
  flex: 0 0 36px;
  min-height: 36px;
  padding: 0 16px;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--text-primary);
  background: var(--bg-surface);
  cursor: pointer;
  white-space: nowrap;
}
.user-menu-sub-item:hover,
.user-menu-sub-item:focus-visible { background: var(--bg-hover); }
.user-menu-sub-item:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: -2px; }
.user-menu-sub-item.is-selected { color: var(--brand-text); font-weight: 500; }

/* EDL Indigo 70 selected state for dark and ADS Preview theme options.
   Uses the absolute palette token #3611C8 so it is immune to any
   per-element variable remapping above. */
.user-menu-sub-item.is-selected[data-theme="dark"],
.user-menu-sub-item.is-selected[data-theme="ads-preview"] {
  background: #3611C8;
  color: #FFFFFF;
}
.user-menu-sub-item.is-selected[data-theme="dark"]:hover,
.user-menu-sub-item.is-selected[data-theme="ads-preview"]:hover,
.user-menu-sub-item.is-selected[data-theme="dark"]:focus-visible,
.user-menu-sub-item.is-selected[data-theme="ads-preview"]:focus-visible {
  background: #2F139F;
  color: #FFFFFF;
}

/* ─── PAGE SHELL ─── full-width with responsive padding, capped at ultra-wide ─── */
.page { padding: 0 48px; max-width: 1440px; margin: 0 auto; }

/* ─── PAGE HEADER ─── Figma: title at y=77 (29px below nav), card at y=170 (33px below header) ─── */
.hdr { padding: 29px 0 33px; }
.hdr h1 { font-family: 'MultiplaneTWDC Display', var(--ff); font-size: 28px; font-weight: 500; line-height: 38px; color: var(--text-primary); letter-spacing: 0; margin-bottom: 8px; }
.hdr p { font-size: 14px; font-weight: 500; line-height: 20px; color: var(--text-secondary); }

/* ─── CARD ─── white, radius 8, outline border ─── */
.card { background: var(--bg-surface); border-radius: 8px; overflow: hidden; margin-bottom: 32px; box-shadow: 0 0 0 1px var(--border-default); }

/* ─── TABS ─── Figma 362:55886: h-56, pt-16 pb-8 px-16, items-center ─── */
.tabs-row { display: flex; align-items: center; height: 56px; padding: 16px 16px 8px; border-bottom: 1px solid var(--border-subtle); }

/* Extra breathing room below the tab underline before the toolbar.
   Applied to both panels (Users + Roles & Permissions) so the whole
   block — toolbar row (Filter / Search / CTA), column header row, and
   everything below — shifts down together by the same amount. Puts
   the padding on the panel (not `.tbar`) to avoid margin-collapsing
   through the un-styled panel wrappers. Internal spacing between
   toolbar → column headers → body → pagination is untouched. */
#usersPanel, #rolesPanel, #teamsPanel { padding-top: 12px; }
.tabs-row nav { display: flex; gap: 24px; align-items: flex-start; }
.tab-btn { display: inline-flex; align-items: flex-start; padding-bottom: 8px; font-size: 18px; font-weight: 800; line-height: 21px; color: var(--text-muted); position: relative; white-space: nowrap; }
.tab-btn.on { color: var(--brand-text); }
.tab-btn.on::after { content: ''; position: absolute; bottom: -1px; left: 0; right: 0; height: 2px; background: var(--brand); border-radius: 1px; }
.tab-btn:hover:not(.on) { color: var(--text-secondary); }
/* Inert third tab (Permission Management) — visually identical to other
   inactive tabs per Figma 770:19301; no .on toggle, no panel wired. The
   click is a no-op (handler-free), so the tab appears reachable but
   doesn't deceive users with empty content. aria-disabled in markup
   communicates the unavailable state to assistive tech. */
.tab-btn[aria-disabled="true"] { cursor: default; }
.tab-btn[aria-disabled="true"]:hover { color: var(--text-muted); }

/* ─── TOOLBAR ─── h-48 px-16 py-8 (Figma 362:55889) ─── */
/* Vertical rhythm: tabs → toolbar is ~16px via .tabs-row/.tbar padding;
   toolbar → table uses margin-bottom here so the table reads as a new section. */
/* Toolbar uses the shared 56px right-gutter rail (see .tbl-wrap above),
   so "+ Add Users" and "+ Create Role" — right-anchored by flex — land
   on the exact same vertical line as the Region / Create Date column's
   right edge and the pagination controls. Both panels use identical
   values; no per-panel override is needed.

   Vertical alignment contract: .tbar is a single horizontal flex row
   with align-items: center. Filter + Search (wrapped in .tbar-l — also
   align-items: center) and the CTA (.btn-ghost, direct child) all
   share the same center baseline. All three controls are 32px tall,
   centered in the 48px tbar (8px top / 8px bottom). Every control's
   `align-self` falls back to the container's `center`; we set it
   explicitly on the CTA to immunize against any future override. */
.tbar { display: flex; align-items: center; justify-content: space-between; height: 48px; padding: 8px 56px 8px 16px; margin-bottom: 16px; }
/* Users only: slightly less air between toolbar row and column headers (Roles unchanged). */
#usersPanel .tbar { margin-bottom: 10px; }
/* NOTE: Roles/Teams no longer carry their own padding-right override here.
   All three tabs' toolbars share ONE right-gutter value — see R33-6 below
   ([data-iam-version="v4"] .tbar { padding-right: 16px }) — so the primary
   CTA's right edge is identical across tabs instead of drifting per-panel. */
.tbar-l { display: flex; align-items: center; gap: 16px; }
.tbar .btn-ghost { align-self: center; margin-top: 0; margin-bottom: 0; }

/* EDL Standard button — secondary outline, 32px */
.btn-std { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border: 1px solid var(--brand-text); border-radius: 8px; background: var(--bg-surface); font-size: 14px; font-weight: 500; line-height: 16px; color: var(--brand-text); white-space: nowrap; transition: background-color 0.15s ease; }
.btn-std:hover { background: var(--brand-bg-soft); }
.btn-std:active { background: var(--brand-bg-selected); }
.btn-std:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-std:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }
.btn-std svg { flex-shrink: 0; }

/* EDL Search — 32px input with dropdown panel */
.search { position: relative; width: 310px; z-index: 10; }
.search input { width: 100%; height: 32px; padding: 0 32px 0 12px; border: 1px solid var(--input-border); border-radius: 8px; font-size: 14px; line-height: 21px; color: var(--text-primary); background: var(--bg-surface); outline: none; transition: border-color 0.15s ease, border-radius 0.1s ease; }
.search input::placeholder { color: var(--text-placeholder); font-weight: 400; }
.search input:focus { border-color: var(--brand-text); }
.search-ico { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); pointer-events: none; transition: opacity 0.1s ease; }

.search.open { z-index: 50; }
.search.open input { border-radius: 8px 8px 0 0; border-color: var(--brand-text); border-bottom-color: var(--border-default); }
.search.has-value .search-ico { opacity: 0; pointer-events: none; }

.search-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; color: var(--text-muted); background: none; border: none; cursor: pointer; padding: 0; z-index: 2; }
.search-clear:hover { color: var(--text-secondary); background: var(--bg-hover); }
.search-clear.hidden { display: none; }

.search-dropdown { display: none; position: fixed; background: var(--bg-surface); border: 1px solid var(--brand-text); border-top: 1px solid var(--border-default); border-radius: 0 0 8px 8px; box-shadow: var(--shadow-pop); padding: 16px; z-index: 9999; }
.search-dropdown.open { display: block; }

.search-dd-label { font-size: 14px; font-weight: 400; line-height: 21px; color: var(--text-muted); margin-bottom: 6px; }
.search-dd-item { display: flex; align-items: center; gap: 8px; padding: 5px 4px; cursor: pointer; border-radius: 4px; transition: background-color 0.1s ease; }
.search-dd-item:hover { background: var(--bg-hover-soft); }
.search-dd-item svg { flex-shrink: 0; color: var(--text-muted); }
.search-dd-item span { font-size: 14px; font-weight: 500; line-height: 21px; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.search-dd-info { font-size: 14px; font-weight: 500; line-height: 21px; color: var(--text-secondary); padding: 4px 0; }
.search-dd-info strong { color: var(--text-primary); font-weight: 700; }
.search-dd-divider { height: 1px; background: var(--border-subtle); margin: 10px 0; }
.search-dd-empty { font-size: 13px; line-height: 21px; color: var(--text-muted); padding: 4px 0; }

/* EDL toolbar primary CTA treatment for "+ Add Users" / "+ Create Role". */
/* CTA action buttons sit in .tbar which
   already anchors the right edge at 32px from the card (matching .pgn and
   .rp-act). Zero horizontal padding on the button keeps the icon+text
   optically aligned to that same right-side system instead of being inset
   by the button's own padding. Only the 6px icon→text gap is preserved.

   Line-height 16 matches .btn-std (Filter) exactly so the two buttons'
   internal text struts resolve to the same y-center. Without this, the
   native <button> UA layout resolves a taller strut (line-height: 20)
   differently from .btn-std's 16px strut and the glyphs can read as
   sitting ~1–2 px higher than Filter/Search on the same flex row. */
/* EDL Ghost button — text-only, transparent background */
.btn-ghost { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0; border: 0; border-radius: 8px; background: transparent; font-family: inherit; font-size: 14px; font-weight: 500; line-height: 16px; color: var(--brand-text); white-space: nowrap; overflow: visible; cursor: pointer; vertical-align: middle; transition: background-color 0.15s ease, color 0.15s ease; }
.btn-ghost svg { flex-shrink: 0; display: block; }
.btn-ghost:hover { background: var(--brand-bg-soft); color: var(--brand-text-hover); }
.btn-ghost:active { background: var(--brand-bg-selected); color: var(--brand-text-hover); }
.btn-ghost:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-ghost:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* EDL Primary CTA — toolbar "Add Users" / "Create Role" promoted to filled primary */
.tbar .btn-ghost {
  padding: 0 12px;
  background: var(--brand);
  color: var(--text-on-brand);
  border-radius: 8px;
}
.tbar .btn-ghost:hover {
  background: var(--brand-hover);
  color: var(--text-on-brand);
}
.tbar .btn-ghost:active {
  background: var(--indigo-95);
  color: var(--text-on-brand);
}
.tbar .btn-ghost:disabled {
  background: var(--brand-disabled-bg);
  color: var(--brand-disabled-fg);
  opacity: 1;
  cursor: not-allowed;
}

/* ─── EDL Multi-Segment Control ─── 32px, Gray/30 stroke, Indigo/10 selected ─── */
.seg-ctrl {
  display: inline-flex;
  align-items: center;
  height: 32px;
  margin-left: 8px;
  border: 1px solid var(--border-input);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-surface);
  flex-shrink: 0;
}
.seg-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-width: 96px;
  padding: 0 16px;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  color: var(--brand-text);
  white-space: nowrap;
  cursor: pointer;
  position: relative;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.seg-btn + .seg-btn { border-left: 1px solid var(--border-input); }
.seg-btn.on { background: var(--brand-bg-selected); color: var(--brand-text); }
.seg-btn:not(.on):hover { background: var(--brand-bg-soft); }
.seg-btn.on:hover { background: var(--brand-bg-selected); }
.seg-btn:active { opacity: 0.85; }
.seg-btn:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: -2px; z-index: 1; }
/* The table itself spans the full card width so the row-divider borders
   (.tbl tbody tr { border-bottom }) draw cleanly from edge to edge with
   no gap on the right. The 56px right-gutter rail that aligns the CTA
   with the rightmost column's visible content is implemented on that
   element individually (see .tbar below and the per-column padding on
   the rightmost cell — .rp-date for R&P; Users' .c-rg no longer does
   this — see its own rule further down for why). The pagination row
   intentionally uses a symmetric 16px
   horizontal padding (see .pgn below) so the left and right ends of
   the row feel visually balanced against each other; it does not
   share the CTA rail. Doing the rail via cell padding instead of
   wrap padding keeps the tr's border-bottom running all the way
   across the table. */
.tbl-wrap { overflow-x: auto; }
.tbl { width: 100%; table-layout: fixed; }
.tbl th, .tbl td { text-align: left; vertical-align: middle; padding: 0 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Compact row density per Figma 770:17428 (header 32px, body 48px).
   Body row of 48px fits the 40px avatar + name/email stack (21 + 16 line
   heights ≈ 37px) with comfortable breathing room top/bottom. */
.tbl th { height: 32px; }
.tbl td { height: 48px; }

/* Role assignment table: leading checkbox column per Figma 770:19301.
   Fixed-width 44px column (28px control + 16px ambient padding) so
   .alignRP() can keep the four content columns proportional. Only
   visual selection state is wired — there is no bulk-action toolbar
   in this prototype build, matching the Figma which shows checkboxes
   without surrounding multi-select chrome. */
.rp-tbl col.rp-col-sel { width: 44px; }
.tbl th.rp-sel, .tbl td.rp-sel { padding: 0; text-align: center; }
.rp-check { width: 16px; height: 16px; margin: 0; cursor: pointer; accent-color: var(--brand); }
.rp-check:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; }

/* ─── Column widths — proportional percentages, all columns participate ─── */
/* Column base widths are now set in the Figma-matched block below (after the c-ct/c-em hidden section). */

/* Checkbox column removed — its 3.86% returns to Role. The original
   28px left gutter (which previously came from the checkbox cell's padding)
   is re-applied to the new first column (rp-role) below so the table's left
   edge alignment is preserved and no empty gap is introduced. */
/* R&P table: four columns (Description removed per Figma, space given to
   Functions). Create Date is JS-aligned to the Create Role CTA; Role and
   Created By widths held stable in the column-resize handler. */
#rpColgroup col[data-rp-col="role"] { width: 15.00%; }
#rpColgroup col[data-rp-col="func"] { width: 58.00%; }
#rpColgroup col[data-rp-col="by"]   { width: 13.00%; }
#rpColgroup col[data-rp-col="date"] { width: 14.00%; }

.tbl thead tr { background: var(--bg-surface); border-bottom: 1px solid var(--border-default); }
.tbl th { font-size: 12px; font-weight: 400; line-height: 18px; color: var(--text-secondary); position: relative; }
th.c-nm { overflow: visible; text-overflow: clip; }

/* ─── Shared ADS sortable-header treatment (Figma 1003:17846) ───
   ONE rule set for every sortable column in every V4 table — User
   List (`[data-sort]`), Roles List (`[data-rp-sort]`), and Teams List
   (`[data-tm-sort]`) — so the click target, focus ring, hover
   feedback, and icon colors never drift between tables. The label/icon
   pair sits in `.th-inner` (flex, `align-items:center`, 4px gap — the
   exact Figma label-to-icon gap) so both always share one vertical
   centerline and the icon never shifts the label when the sort state
   changes.
     • Icon size    : 12×12 (Figma-exact)
     • Icon default : `--gray-30` #B8C7D0 (Figma "EDL Gray/30", the
                       exact unsorted-icon value from Dev Mode —
                       NOT the darker `--text-placeholder` alias that
                       resolves to #51585B under the ADS Preview
                       theme and was making unsorted icons read as
                       "active")
     • Icon hover   : `--text-secondary` (subtle lift, invites the
                       click without implying the column is sorted)
     • Icon active  : `--text-primary` on whichever arrow matches
                       the current direction (clear, high-contrast
                       state that a muted default can't be confused
                       with) */
.tbl th[data-sort],
.tbl th[data-rp-sort],
.tbl th[data-tm-sort] {
  cursor: pointer;
  user-select: none;
}
.tbl th[data-sort]:hover,
.tbl th[data-rp-sort]:hover,
.tbl th[data-tm-sort]:hover {
  color: var(--text-primary);
}
.tbl th[data-sort]:hover .sort-dn,
.tbl th[data-sort]:hover .sort-up,
.tbl th[data-rp-sort]:hover .sort-dn,
.tbl th[data-rp-sort]:hover .sort-up,
.tbl th[data-tm-sort]:hover .sort-dn,
.tbl th[data-tm-sort]:hover .sort-up {
  fill: var(--text-secondary);
}
.tbl th[data-sort]:focus-visible,
.tbl th[data-rp-sort]:focus-visible,
.tbl th[data-tm-sort]:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: -2px;
}
.th-inner { display: flex; align-items: center; gap: 4px; }
.sort-ico { display: flex; width: 12px; height: 12px; justify-content: center; align-items: center; flex-shrink: 0; }
.sort-dn, .sort-up { fill: var(--gray-30); transition: fill 0.15s ease; }
.tbl th.sort-asc .sort-up,
.tbl th.sort-desc .sort-dn {
  fill: var(--text-primary);
}

.tbl tbody tr { border-bottom: 1px solid var(--border-default); background: var(--bg-surface); }
.tbl td { font-size: 14px; line-height: 21px; color: var(--text-primary); }

/* ─── Name cell with avatar ─── */
td.c-nm { padding: 0 !important; overflow: visible !important; white-space: normal !important; }
.name-cell { display: flex; align-items: center; gap: 8px; height: 64px; padding: 0 0 0 32px; }
.name-cell-text { display: flex; flex-direction: column; justify-content: center; gap: 2px; min-width: 0; overflow: hidden; }
.name-cell-email { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Status column — icon only, centered. Tooltip is rendered at body level
   by app.js so table/card overflow cannot clip it. */
td.c-st { text-align: center; padding: 0 !important; }
th.c-st { text-align: center; }
th.c-st .th-inner { justify-content: center; }
.status-icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: default;
  border-radius: 4px;
}
.status-icon-wrap:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
.edl-status-tooltip {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 10000;
  display: block;
  pointer-events: none;
  opacity: 0;
  padding: 8px;
  border-radius: 8px;
  background: #3A4652;
  color: #FFFFFF;
  box-shadow: 0 1px 1.5px rgba(16, 17, 19, 0.24);
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  white-space: nowrap;
  transform: translateY(2px);
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.edl-status-tooltip::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 8px;
  height: 8px;
  background: #3A4652;
  transform: translateX(-50%) rotate(45deg);
}
.edl-status-tooltip.is-visible {
  opacity: 1;
  transform: translateY(0);
}
/* Compact row density (Figma 770:17428): avatar is 40px so the 48px row
   leaves 4px top/bottom breathing room and no clipping at the divider. */
.name-avatar { width: 40px; height: 40px; border-radius: 50%; background: #FFF; flex-shrink: 0; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.name-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.avatar-initials { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; border-radius: 50%; background: rgb(78, 136, 210); color: #FFFFFF; font-size: 16px; font-weight: 700; line-height: 1; letter-spacing: 0.5px; }
/* Users table — name link is the only row affordance; each name opens Edit User for that row.
   EDL Light: `--brand-text` is Indigo 70; Dark / ADS Preview remap for contrast. */
#usersPanel #usersTable tbody .name-link {
  display: block;
  min-width: 0;
  flex: none;
  align-self: auto;
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--brand-text);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
#usersPanel #usersTable tbody .name-link:hover {
  color: var(--brand-text-hover);
  text-decoration: underline;
}
#usersPanel #usersTable tbody .name-link:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ─── Role cell ─── */
.role-txt {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 14px;
  line-height: 21px;
  color: var(--text-primary);
}
.role-primary {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.role-extra { color: var(--brand-text); cursor: pointer; text-decoration: none; }
.role-extra:hover { text-decoration: underline; }

/* ─── PAGINATION ─── compact EDL control bar (matches 32px inputs / `.cr-dd-trigger`) ─── */
/* Symmetric 16px horizontal padding (EDL spec). The right side
   previously used 56px so the "Go to page" select's right edge would
   share a rail with the "+ Add Users" / "+ Create Role" CTA above,
   but that made the right end feel ~40px wider than the left end
   and unbalanced the row. Using the left value on both ends ties
   the two ends to the same visual rhythm; the centered page-number
   group shifts by ~20px (half of the reclaimed 40px) because the
   row uses justify-content: space-between, which is the subtle
   center nudge called out as acceptable in the brief. */
.pgn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 40px;
  min-height: 40px;
  padding: 0 16px;
  box-sizing: border-box;
  background: transparent;
}
.pgn-show, .pgn-jump { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.pgn-lbl {
  font-size: 12px;
  line-height: 18px;
  color: var(--text-primary);
  display: inline-flex;
  align-items: center;
}

/* Pagination: same EDL `.cr-dd` pattern as forms (no native <select>). */
.pgn-sel-wrap { position: relative; display: inline-flex; align-items: center; }
.pgn-dd.cr-dd {
  display: inline-block;
  vertical-align: middle;
  width: auto;
  min-width: 56px;
}
/* Lock to standard EDL field height (32px); same radius/border as `.cr-dd-trigger`. */
.pgn-dd .cr-dd-trigger {
  height: 32px;
  min-height: 32px;
  max-height: 32px;
  padding: 0 12px;
  box-sizing: border-box;
}
.pgn-dd .cr-dd-menu {
  width: 100%;
  min-width: 100%;
}

.pgn-pages { display: flex; align-items: center; gap: 10px; }
.pg-nav { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; color: var(--text-secondary); }
.pg-nav:hover:not(.off) { color: var(--brand-text); }
.pg-nav.off { opacity: 0.4; cursor: default; pointer-events: none; }
.pg-nums { display: flex; align-items: center; gap: 4px; }
.pg-n { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; font-size: 12px; line-height: 18px; color: var(--text-primary); border-radius: 2px; position: relative; }
.pg-n.on::after { content: ''; position: absolute; bottom: 0; left: 25%; right: 25%; height: 2px; background: var(--brand); border-radius: 1px; }
.pg-n:hover:not(.on) { background: var(--bg-hover); }
.pg-dots { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; font-size: 12px; color: var(--text-primary); }

/* Users pagination total count: lives where the old "Go to page" control was. */
#usersTotalLabel { color: var(--text-primary); font-weight: 400; }

/* ─── FILTER DRAWER ─── left-side HARPS panel ─── */
.flt-overlay { position: fixed; inset: 0; background: var(--overlay-scrim); z-index: 200; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; }
.flt-overlay.open { opacity: 1; pointer-events: auto; }

.flt-drawer { position: fixed; top: 0; left: 0; width: 400px; height: 100vh; background: var(--bg-surface); z-index: 201; display: flex; flex-direction: column; box-shadow: var(--shadow-drawer); transform: translateX(-100%); transition: transform 0.25s ease; }
.flt-drawer.open { transform: translateX(0); }

/* EDL dense drawer: header, body and footer tightened onto the 4px spacing
   grid. Heights, paddings and gaps use EDL tokens (20 / 16 / 6 / 36 / 56 / 64)
   — no new visual style, just a compact rhythm. */
.flt-header { display: flex; align-items: center; justify-content: space-between; height: 56px; padding: 0 20px; border-bottom: 1px solid var(--border-default); flex-shrink: 0; }
.flt-title { font-size: 20px; font-weight: 700; line-height: 26px; color: var(--text-primary); }
.flt-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 8px; color: var(--text-muted); }
.flt-close:hover { background: var(--bg-hover); color: var(--text-secondary); }

.flt-body { flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 16px; }

.flt-field { display: flex; flex-direction: column; gap: 6px; }
.flt-label { font-size: 14px; font-weight: 500; line-height: 20px; color: var(--text-secondary); }
.flt-input { width: 100%; height: 36px; padding: 0 12px; border: 1px solid var(--input-border); border-radius: 8px; font-size: 14px; line-height: 20px; color: var(--text-primary); background: var(--bg-surface); outline: none; transition: border-color 0.15s ease; }
.flt-input::placeholder { color: var(--text-placeholder); font-weight: 400; }
.flt-input:hover { border-color: var(--text-muted); }
.flt-input:focus { border-color: var(--brand-text); }

.flt-sel-wrap { position: relative; }
.flt-select { appearance: none; -webkit-appearance: none; width: 100%; height: 40px; padding: 0 36px 0 16px; border: 1px solid var(--input-border); border-radius: 8px; font-size: 14px; line-height: 21px; color: var(--text-placeholder); background: var(--bg-surface); cursor: pointer; outline: none; transition: border-color 0.15s ease; }
.flt-select:hover { border-color: var(--text-muted); }
.flt-select:focus { border-color: var(--brand-text); }
.flt-select:not(:invalid) { color: var(--text-primary); }
.flt-sel-chev { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); pointer-events: none; }

.flt-footer { display: flex; align-items: center; justify-content: space-between; height: 64px; padding: 0 20px; border-top: 1px solid var(--border-default); flex-shrink: 0; }
.flt-footer-r { display: flex; align-items: center; gap: 12px; }
.flt-btn-reset { display: inline-flex; align-items: center; border-radius: 8px; padding: 0 8px; height: 36px; font-size: 14px; font-weight: 500; line-height: 20px; color: var(--brand-text); background: none; transition: background-color 0.15s ease, color 0.15s ease; }
.flt-btn-reset:hover { background: var(--brand-bg-soft); color: var(--brand-text-hover); }
.flt-btn-reset:active { background: var(--brand-bg-selected); }
.flt-btn-reset:disabled { opacity: 0.5; cursor: not-allowed; }
.flt-btn-reset:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }
.flt-btn-cancel { display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 16px; border: 1px solid var(--brand-text); border-radius: 8px; font-size: 14px; font-weight: 500; line-height: 20px; color: var(--brand-text); background: var(--bg-surface); transition: background-color 0.15s ease; }
.flt-btn-cancel:hover { background: var(--brand-bg-soft); }
.flt-btn-cancel:active { background: var(--brand-bg-selected); }
.flt-btn-cancel:disabled { opacity: 0.5; cursor: not-allowed; }
.flt-btn-cancel:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }
.flt-btn-apply { display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 16px; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; line-height: 20px; color: var(--text-on-brand); background: var(--brand); transition: background-color 0.15s ease; }
.flt-btn-apply:hover { background: var(--brand-hover); }
.flt-btn-apply:active { background: var(--indigo-95); }
.flt-btn-apply:disabled { background: var(--brand-disabled-bg); color: var(--brand-disabled-fg); opacity: 1; cursor: not-allowed; }
.flt-btn-apply:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* Dense variant of the EDL combo input when it lives inside the filter drawer
   — keeps the standard EDL combo component intact elsewhere (menu is portaled
   to <body> and untouched). Drawer controls share a single 36px baseline. */
.flt-drawer .edl-combo-input {
  height: 36px;
  min-height: 36px;
  max-height: 36px;
  padding-right: 52px;
  padding-left: 12px;
  line-height: 36px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Filter drawer: trailing control slot is 8px from the edge. Clear (×) and
   chevron share the exact slot — mutual-exclusion rule above hides the
   chevron when a value is selected. */
.flt-drawer .edl-combo-clear { right: 8px; width: 18px; height: 18px; }
.flt-drawer .edl-combo-toggle { right: 8px; }

/* ─── EDL COMBO BOX ─── searchable dropdown, matches EDL select + list pattern ─── */
.edl-combo { position: relative; }

.edl-combo-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
  height: 40px;
  box-sizing: border-box;
}

/* Trigger: same fixed height as EDL text fields — single line, icons absolutely positioned (no height growth). */
.edl-combo-input {
  box-sizing: border-box;
  width: 100%;
  height: 40px;
  min-height: 40px;
  max-height: 40px;
  margin: 0;
  padding: 0 60px 0 16px;
  border: 1px solid var(--input-border);
  border-radius: 8px;
  background: var(--bg-surface);
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 40px;
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s ease, border-radius 0.1s ease;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.edl-combo-input::placeholder { color: var(--text-placeholder); font-weight: 400; }
.edl-combo-input:hover { border-color: var(--text-muted); }
.edl-combo-input:focus { border-color: var(--brand-text); }
.edl-combo.open .edl-combo-input { border-color: var(--brand-text); border-radius: 8px 8px 0 0; border-bottom-color: var(--border-default); }

.edl-combo-clear { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; color: var(--text-muted); background: none; border: none; cursor: pointer; padding: 0; z-index: 2; }
.edl-combo-clear:hover { color: var(--text-secondary); background: var(--bg-hover); }
.edl-combo-clear.hidden { display: none; }

.edl-combo-toggle { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; color: var(--text-placeholder); background: none; border: none; cursor: pointer; padding: 0; z-index: 2; }
.edl-combo-toggle:hover { color: var(--text-secondary); }
.edl-combo-toggle svg { transition: transform 0.2s ease; }
.edl-combo.open .edl-combo-toggle svg { transform: rotate(180deg); }

/* Mutual-exclusion rule: empty field shows the chevron only; selected field
   shows the EDL clear (×) only. Never both at once. Applies to every EDL
   combo instance globally (filter drawers, Add/Edit User, R&P filter, etc.). */
.edl-combo-input-wrap:has(.edl-combo-clear:not(.hidden)) .edl-combo-toggle {
  display: none;
}

.edl-combo-menu {
  display: none;
  position: fixed;
  background: var(--bg-surface);
  border: 1px solid var(--brand-text);
  border-top: 1px solid var(--border-default);
  border-radius: 0 0 8px 8px;
  box-shadow: var(--shadow-pop);
  z-index: 9998;
  padding: 4px 0;
  max-height: 260px;
  overflow-y: auto;
  /* Subtle EDL scrollbar: Gray 40 @ ~80% opacity, minimal 6px, no heavy track */
  scrollbar-width: thin;
  scrollbar-color: rgba(158, 176, 189, 0.8) transparent;
}
.edl-combo-menu.open { display: block; }
.edl-combo-menu::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.edl-combo-menu::-webkit-scrollbar-track {
  background: transparent;
}
.edl-combo-menu::-webkit-scrollbar-thumb {
  background: rgba(158, 176, 189, 0.8);
  border-radius: 999px;
  border: none;
}
.edl-combo-menu::-webkit-scrollbar-thumb:hover {
  background: var(--gray-50);
}

.edl-combo-item { display: flex; align-items: center; justify-content: space-between; height: 40px; padding: 0 16px; font-size: 14px; font-weight: 400; line-height: 21px; color: var(--text-primary); cursor: pointer; white-space: nowrap; transition: background-color 0.1s ease; }
/* IAM filter menus — comfortable row height. Add User uses `--add-user` with compact rows below. */
.edl-combo-menu--iam-roles {
  padding: 6px 0;
  max-height: min(50vh, 320px);
}
.edl-combo-menu--add-user {
  padding: 4px 0;
  max-height: min(50vh, 320px);
}
.edl-combo-menu--iam-roles .edl-combo-item {
  height: auto;
  min-height: 44px;
  padding: 10px 16px;
  box-sizing: border-box;
}
/* Add User field menus — compact row height (filters keep --iam-roles density above). */
.edl-combo-menu--add-user .edl-combo-item {
  height: auto;
  min-height: 40px;
  padding: 8px 16px;
  box-sizing: border-box;
}
.edl-combo-item.is-disabled {
  color: var(--text-placeholder);
  cursor: not-allowed;
  pointer-events: none;
}
.edl-combo-item:hover, .edl-combo-item.kb-highlight { background: var(--bg-hover-soft); }
.edl-combo-item.selected { background: var(--brand-bg-soft); font-weight: 500; }
.edl-combo-item.selected:hover, .edl-combo-item.selected.kb-highlight { background: var(--brand-bg-selected); }
.edl-combo-item:focus-visible { outline: 2px solid var(--brand-text); outline-offset: -2px; }

.edl-combo-check { flex-shrink: 0; width: 16px; height: 16px; color: var(--brand-text); display: none; }
.edl-combo-item.selected .edl-combo-check { display: block; }

.edl-combo-empty { padding: 10px 16px; font-size: 14px; line-height: 21px; color: var(--text-muted); }

/* ═══ EDL TOOLTIP / POPOVER — single dark family ═══
   Source of truth: Figma EDL Component Library
   https://www.figma.com/design/w16COHKBA2KtYTCPFEAQPp/EDL-Component-Library?node-id=4722-54080
   Tokens used:
     surface        EDL Gray/80   #3A4652   (var --gray-80)
     data-row rule  EDL Gray/70   #3E4D5B   (hardcoded, no matching token)
     meta / subheader EDL Gray/40 #9EB0BD   (var --gray-40)
     title / body / label  white            (var --white)
     shadow        0 1px 3px rgba(16,17,19,0.24)
     radius        8px
     tooth         8×4 triangle
     type          Icon/Definition  14px Medium / 16–20px line
     type          Data rows        12px Roman / 18px line (explicit Figma exception)
   Both surfaces share the same tokens so they read as one family. */

/* Icon/Definition tooltip (role hover on Users table) */
.edl-tooltip {
  position: fixed; z-index: 300;
  background: var(--gray-80);
  color: var(--white);
  border-radius: 8px;
  padding: 8px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s ease;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(16,17,19,0.24);
  font-family: var(--ff);
}
.edl-tooltip.visible { opacity: 1; }
.edl-tooltip::after {
  content: ''; position: absolute;
  bottom: -4px; left: 50%; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid var(--gray-80);
}
.edl-tooltip.below::after {
  bottom: auto; top: -4px;
  border-top: none;
  border-bottom: 4px solid var(--gray-80);
}
.edl-tooltip-line {
  font-family: var(--ff);
  font-size: 14px; font-weight: 500; line-height: 20px;
  color: var(--white);
  letter-spacing: 0;
}
.edl-tooltip-line + .edl-tooltip-line { margin-top: 2px; }

/* Tooltip caption ("Used in roles" on the PM table's Used-in cell).
   Sits above the role-name lines, in the same gray-80 surface and
   white text family, but at a slightly smaller weight + a divider
   underneath so the eye separates the label from the items. Scoped
   to .edl-tooltip-title so it only renders when the role-list
   variant calls for it; the existing single/multi-line variants
   keep their current visual untouched. */
.edl-tooltip-title {
  font-family: var(--ff);
  font-size: 12px;
  font-weight: 600;
  line-height: 16px;
  color: rgba(255, 255, 255, 0.72);
  letter-spacing: 0.2px;
  text-transform: none;
  padding-bottom: 4px;
  margin-bottom: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.16);
}

/* Permission Management "Used in" hover affordance. The visible
   text stays inline ("2 roles" / "1 role") so the column height
   is unchanged; the span only adds a hover trigger + keyboard
   focus ring. Inherits color from the parent .pm-used cell (which
   P4-15 sets to gray-95). */
.pm-tbl .pm-used-roles {
  display: inline;
  color: inherit;
  cursor: default;
  outline: none;
}
.pm-tbl .pm-used-roles:focus-visible {
  outline: 2px solid var(--brand-text);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Functions cell follows the default .tbl td truncation (overflow:hidden +
   text-overflow:ellipsis). The permission popover is position:fixed and lives
   on document.body, so it doesn't need the cell to have visible overflow. */
.rp-func-group { display: inline; color: var(--text-primary); }
.rp-func-app {
  color: var(--text-primary);
  font-weight: 400;
}
button.rp-func-link {
  all: unset;
  display: inline;
  color: inherit;
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  text-decoration: none;
}
.rp-func-link:hover .rp-func-access { text-decoration: underline; color: var(--brand-text-hover); }
.rp-func-link:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; border-radius: 2px; }
.rp-func-link[aria-expanded="true"] .rp-func-access { color: var(--brand-text-hover); }
.rp-func-access { color: var(--brand-text); font-weight: 500; }

/* Permission details popover */
.func-popover {
  position: fixed; z-index: 400;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(16,17,19,0.14);
  min-width: 300px;
  max-width: 360px;
  display: none;
  font-family: var(--ff);
  padding: 12px 14px 10px;
}
.func-popover.visible { display: block; }

/* Tooth — anchored via --caret-left set in JS; mirrors Icon tooltip tooth. */
.func-popover::before {
  content: ''; position: absolute;
  top: -4px; left: var(--caret-left, 16px); transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 4px solid var(--bg-surface);
}
.func-popover.above::before {
  top: auto; bottom: -4px;
  border-bottom: none;
  border-top: 4px solid var(--bg-surface);
}

.func-pop-title {
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
  color: var(--text-primary);
}
.func-pop-access {
  margin-top: 2px;
  font-size: 13px;
  font-weight: 500;
  line-height: 18px;
  color: var(--text-secondary);
}
.func-pop-permissions {
  margin-top: 10px;
  font-size: 13px;
  line-height: 18px;
}

/* ─── Filter input with clear button ─── */
.flt-input-wrap { position: relative; }
.flt-input-wrap .flt-input { padding-right: 32px; }
.flt-input-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; color: var(--text-muted); background: none; border: none; cursor: pointer; padding: 0; }
.flt-input-clear:hover { color: var(--text-secondary); background: var(--bg-hover); }
.flt-input-clear.hidden { display: none; }

.tbl td.empty-state { text-align: center; padding: 48px 24px; height: auto; white-space: normal; overflow: visible; text-overflow: clip; font-size: 14px; font-weight: 400; line-height: 21px; color: var(--text-muted); }

/* `[data-rp-sort]` cursor/hover/focus/icon rules now live in the
   shared sortable-header block above (with `[data-sort]`) — removed
   the duplicate pair that used to live here so Users List and Roles
   List can never drift out of sync again. */

/* ─── ROLES & PERMISSIONS TABLE ─── */
/* `min-width: 0` so the table always fits the card (never horizontally
   overflows `.tbl-wrap`). Previously this was `min-width: 1244px`,
   which forced the table wider than the card on sub-1340px viewports
   and caused the rightmost column (Create Date) to be visually clipped
   by the card's right edge — which broke the Create-Date → Create-Role
   CTA left-edge alignment even when the page-coordinate math was
   correct. Matches the Users table (`#usersTable { min-width: 0 }`)
   so both tabs behave identically at every viewport. */
.rp-tbl { min-width: 0; table-layout: fixed; }
/* Left-edge gutter for the first column (Role) — carries over the 28px
   content-start position previously provided by the removed checkbox cell. */
.rp-tbl th.rp-role,
.rp-tbl td.rp-role { padding-left: 28px !important; }
.rp-act  { text-align: right !important; padding-right: 32px !important; }
.rp-act .th-inner { justify-content: flex-end; }

/* Column resize handles */
.col-resize-handle { position: absolute; right: -1px; top: 25%; width: 3px; height: 50%; cursor: col-resize; z-index: 10; background: transparent; border-radius: 1.5px; transition: background 0.15s ease, opacity 0.15s ease; }
.col-resize-handle:hover { background: var(--border-input); opacity: 0.6; }
.col-resize-handle.active { background: var(--text-muted); opacity: 0.7; }
body.col-resizing { cursor: col-resize !important; user-select: none !important; }
body.col-resizing * { cursor: col-resize !important; user-select: none !important; }

.rp-check-input { width: 12px; height: 12px; accent-color: var(--brand-text); cursor: pointer; vertical-align: middle; }

td.rp-cb { text-align: left !important; padding-left: 28px !important; padding-right: 8px !important; }
td.rp-act { text-align: right !important; overflow: visible !important; }

/* EDL link treatment for clickable role name — brand color, underline on hover.
   Applied only to rows that opt-in via `.rp-role-link` (currently Core Planning
   Admin); other rows remain plain text. */
.rp-role-link { color: var(--brand-text); cursor: pointer; text-decoration: none; }
.rp-role-link:hover { color: var(--brand-text-hover); text-decoration: underline; }
.rp-role-link:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; border-radius: 2px; }

/* Permission Management table (Figma 770:20032). Mirrors .rp-tbl's
   layout contract (fixed table-layout, min-width:0) so it scales the
   same way the R&P table does at every viewport. Column widths are
   tuned to the Figma proportions: name 216, description 320, type 176,
   used 144, date 144 — proportionally rendered via the .rp-col-sel
   sibling + percentage fallback when table-layout: fixed redistributes. */
.pm-tbl { min-width: 0; table-layout: fixed; }
.pm-tbl col.rp-col-sel { width: 44px; }
.pm-tbl th.pm-name, .pm-tbl td.pm-name { padding-left: 28px !important; }
.pm-name-link { color: var(--brand-text); cursor: pointer; text-decoration: none; }
.pm-name-link:hover { color: var(--brand-text-hover); text-decoration: underline; }
.pm-name-link:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; border-radius: 2px; }
/* Used-in count column header reads as table-header secondary; data
   cell color is set in P4-15 below (EDL Gray 95 per Figma 770:20039). */
.pm-tbl th.pm-used { color: var(--text-secondary); }
/* .pm-tbl td.pm-type previously set color: var(--text-secondary) for
   the old plain-text rendering. With the chip taking over (Figma
   770:20039 / P4-14), color is owned by the chip itself, so that
   rule is removed. Body cell colors for .pm-used and .pm-date are
   driven by P4-15 below (EDL Gray 95). */

.rp-func-text {
  font-size: 14px;
  line-height: 21px;
  color: var(--text-primary);
  cursor: default;
  outline: none;
}
.rp-func-text:focus-visible {
  outline: 2px solid var(--indigo-50);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Action buttons */
.rp-action-wrap { display: inline-flex; align-items: center; gap: 0; }
.rp-action-btn { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 4px; border: none; background: none; cursor: pointer; padding: 0; transition: background-color 0.15s ease; }
.rp-action-btn:hover { background: var(--bg-hover); }
.rp-action-btn-edit { color: var(--brand-text); }
.rp-action-btn-delete { color: var(--brand-text); }

/* ═══ CREATE ROLE PAGE ═══ */
/* `scrollbar-gutter: stable` (back-nav standardization QA): this panel
   is its own scroll container (`overflow-y: auto`), and `.cr-shell`
   centers itself inside it. Without a reserved gutter, whether the
   scrollbar is present depends on content length alone, which shifts
   the centered shell — and therefore the back link, title, and every
   card — sideways by half a scrollbar-width between a short page
   (Create Role) and a taller one (Edit Role with many applications
   added). Reserving the gutter unconditionally keeps that left edge
   byte-for-byte identical across every state of the same page. */
/* Two-region page shell (Final-QA: "page-header background region",
   Figma 1023:22021) — see the matching `.au-page` comment above for
   the full rationale; `.cr-page` gets the identical treatment so
   Create/Edit Role stay visually consistent with Add/Edit User. */
.cr-page {
  position: fixed;
  inset: 0;
  top: 48px;
  background: var(--page-header-surface-bg);
  z-index: 90;
  overflow-y: auto;
  scrollbar-gutter: stable;
  display: flex;
  flex-direction: column;
}
.cr-page-header-surface {
  flex: 0 0 auto;
  /* Scrollbar-gutter bridge — see the matching `.au-page-header-surface`
     comment for the full rationale. */
  width: calc(100% + var(--v4-scrollbar-gutter-w, 0px));
  background: var(--page-header-surface-bg);
  display: flow-root;
}
.cr-page-main-surface {
  flex: 1 0 auto;
  width: calc(100% + var(--v4-scrollbar-gutter-w, 0px));
  background: var(--page-main-surface-bg);
  display: flow-root;
}
/* Card width matches Figma 1025:23238 Frame 2134099570 (992px card + 24px
   padding each side = 1040px content box within a 48px-padded shell -> 1144
   total, giving a ~1048px outer card footprint measured edge-to-edge).
   Top padding is 8px (not the previous 24px) — Figma's back-link sits only
   8px below the 56px top nav, matching the established `.au-shell` gap
   used by Add/Edit User (`margin: 8px auto ...`). */
.cr-shell { max-width: 1144px; margin: 0 auto; padding: 8px 48px 64px; }
/* Header/main shell variants — same shared width/padding formula as
   the base `.cr-shell` (never duplicated), just with vertical padding
   redistributed across the two surfaces above.

   Vertical-spacing audit (Figma 1023:22021) correction: the *total*
   header-to-first-card distance (24px) was already correct, but it
   used to live entirely inside `.cr-page-header-surface` — `.cr-header`'s
   own `margin-bottom: 24px`, contained by that surface's `flow-root`,
   painted the gap in the *header* tone (`--gray-10`) instead of the
   main-content tone (`--ads-surface-recessed`), which fails the "the
   visible space must belong to the gray main-content region" rule
   (confirmed by sampling the actual painted element at the gap's
   midpoint — it resolved to `.cr-page-header-surface`, not
   `.cr-page-main-surface`). Add/Edit User never had this bug because
   `.au-header` carries no such margin; its 24px comes from `.au-card`'s
   `margin-top`, which lives in the main surface.

   Fix: neutralize `.cr-header`'s margin-bottom only inside the header
   surface (`.cr-page-header-surface .cr-header`, just below) and move
   the equivalent 24px onto `.cr-main-shell`'s own `padding-top`
   instead. The header/main boundary now lands exactly at the header
   row's bottom edge (no change there), and the 24px gap before the
   first card is now painted by the main surface, matching Add/Edit
   User and the Figma reference. Total card position is unchanged. */
.cr-shell.cr-header-shell { padding: 8px 48px 0; }
.cr-shell.cr-main-shell { padding: 24px 48px 64px; }
.cr-page-header-surface .cr-header { margin-bottom: 0; }

/* ═══ Round 32 (2026-08-11) — Edit Role page-header spacing now
   matches Edit User's exactly. Edit User's header surface (`.au-
   header-shell`) carries `padding: 8px 0 12px` — 12px of breathing
   room below the helper text before the header/main boundary — and
   its title-to-subtitle gap is 11px (`.au-subtitle { margin-top:
   11px }`, with `.au-title` contributing no margin-bottom of its
   own). Edit Role's shared `.cr-header-shell`/`.cr-title`/`.cr-
   subtitle` rules above give Create Role a 0px bottom padding (the
   helper text sat flush against the boundary — the reported bug) and
   only an 8px title/subtitle gap (`.cr-title`'s own margin-bottom).
   Scoped to `#createRolePage.is-edit-mode` only — Create Role's
   header spacing is intentionally left as-is; this is an Edit-Role-
   only correction. The existing 24px boundary-to-first-card gap
   (`.cr-main-shell`'s own `padding-top: 24px`, unchanged) is
   untouched by this, so the two comfortable gaps now stack exactly
   like Edit User's do (12px within the header surface, then 24px
   within the main surface) instead of colliding into one. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-header-shell {
  padding-bottom: 12px;
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-title {
  margin-bottom: 0;
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-subtitle {
  margin-top: 11px;
}

/* ═══ Shared V4 back-navigation component ═══════════════════════════
   ONE style contract for every "Back to…" control in V4 — Add/Edit
   User (#auBack), Edit Team (#tmBack), Create/Edit Role (#crBack),
   and Permission Capability Detail (#pcBack). Matches the ADS
   Code-Connected "Label & Inline Button" component (Figma
   1003:21293: Button, hierarchy=demoted, size=32) — chevron-left
   icon + body/normal/md label, 14px/20px, SemiBold, brand-indigo.
   `.au-back` and `.cr-back` are two class names (one per page shell)
   pointed at this single rule set so no page ever needs its own
   font-size/spacing override again. */
.au-back,
.cr-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 32px;
  padding: 0 4px 0 0;
  margin: 0 0 16px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  letter-spacing: 0;
  color: var(--brand-text);
  white-space: nowrap;
  cursor: pointer;
}
.au-back svg,
.cr-back svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.au-back:hover,
.cr-back:hover {
  color: var(--brand-text-hover);
  background: rgba(15, 18, 20, 0.05);
}
.au-back:active,
.cr-back:active {
  background: rgba(15, 18, 20, 0.10);
}
.au-back:focus-visible,
.cr-back:focus-visible {
  outline: 2px solid #4045c2;
  outline-offset: 2px;
}

.cr-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin-bottom: 24px; }
.cr-header-left { flex: 1; min-width: 0; }
.cr-title { font-family: 'MultiplaneTWDC Display', var(--ff); font-size: 28px; font-weight: 500; line-height: 38px; color: var(--text-primary); letter-spacing: 0; margin-bottom: 8px; }
.cr-subtitle { font-size: 14px; font-weight: 500; line-height: 20px; color: var(--text-secondary); }

.cr-header-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; padding-top: 4px; }

/* Save Role button — Inspire TWDC 14/16, EDL Promoted 32px.
   Optical centering: InspireTWDC glyphs sit slightly above the line-box
   center, so mathematical centering (flex + equal padding) leaves the
   label visually high. Asymmetric padding (2px top / 0 bottom) with
   box-sizing: border-box nudges the text ~1px down without changing
   the 32px button height or the 16px horizontal padding. Same treatment
   is applied to every 32px label button in the action group and modal
   so centering stays consistent across them. */
.cr-btn-save { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 32px; padding: 2px 16px 0; border: none; border-radius: 8px; font-family: var(--ff); font-size: 14px; font-weight: 500; line-height: 16px; letter-spacing: 0; color: var(--text-on-brand); background: var(--brand); white-space: nowrap; cursor: pointer; transition: background-color 0.15s ease, opacity 0.15s ease; -webkit-font-smoothing: antialiased; }
.cr-btn-save:hover:not(:disabled) { background: var(--brand-hover); }
.cr-btn-save:active:not(:disabled) { background: var(--indigo-95); }
.cr-btn-save:disabled { background: var(--brand-disabled-bg); color: var(--brand-disabled-fg); cursor: not-allowed; opacity: 1; }
.cr-btn-save:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* Cancel button scoped override — matches Save Role dimensions and the
   same optical-centering padding so the two buttons feel balanced. */
#crCancel.btn-std { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 32px; padding: 2px 16px 0; font-family: var(--ff); font-size: 14px; font-weight: 500; line-height: 16px; border-radius: 8px; }

/* ─── Remove Role — legacy EDL text-action fallback ───
   This un-scoped rule is the pre-ADS fallback and is fully superseded
   in V4 by the higher-specificity `html[data-iam-version="v4"]
   .cr-btn-remove` rule (grouped with `.au-revoke-btn`/`.tm-delete-btn`
   further down this file — the shared 36px ADS ghost/text-button
   component, Edit Role header-actions QA round, 2026-08-11). That rule
   is this control's real rendered treatment; only `margin-right: 12px`
   below (not set by the shared component) actually reaches the
   rendered result, giving the same "slightly larger gap before the
   destructive action's neighbor" contract already established for
   `.au-revoke-btn`/`.tm-delete-btn` (12px base `.cr-header-actions`
   gap + this 12px margin = 24px). No-op while `[hidden]` (Create Role
   mode, where there is no persisted role yet to remove). */
.cr-btn-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 32px;
  padding: 2px 12px 0;
  margin: 0;
  margin-right: 12px;
  background: transparent;
  border: none;
  border-radius: 8px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  letter-spacing: 0;
  color: var(--brand-text);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
  -webkit-font-smoothing: antialiased;
}
.cr-btn-remove[hidden] { display: none !important; }
.cr-btn-remove:hover { background: var(--brand-bg-soft); }
.cr-btn-remove:active { background: var(--brand-bg-selected); }
.cr-btn-remove:disabled { opacity: 0.5; cursor: not-allowed; }
.cr-btn-remove:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* ─── Remove Role confirmation dialog ─── */
.cr-confirm-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(17, 24, 39, 0.48);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  padding: 24px;
}
.cr-confirm-backdrop[hidden] { display: none !important; }
.cr-confirm-dialog {
  background: var(--bg-surface);
  border-radius: 12px;
  box-shadow: 0 20px 48px rgba(0, 0, 0, 0.24);
  width: 100%;
  max-width: 480px;
  padding: 24px;
  box-sizing: border-box;
  font-family: var(--ff);
}
.cr-confirm-title {
  margin: 0 0 8px 0;
  font-family: var(--ff);
  font-size: 18px;
  font-weight: 600;
  line-height: 24px;
  color: var(--text-primary);
}
.cr-confirm-body {
  margin: 0 0 24px 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-secondary);
  word-wrap: break-word;
}
.cr-confirm-body strong { color: var(--text-primary); font-weight: 600; }
.cr-confirm-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}
/* Modal confirm Remove Role — EDL Promoted button, Indigo 70 solid.
   Uses the same visual language as .cr-btn-save so the modal action
   stays consistent with the rest of the EDL system. Same 2px-top / 0
   bottom optical-centering padding as the other 32px label buttons. */
.cr-btn-danger-solid {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 32px;
  padding: 2px 16px 0;
  border: none;
  border-radius: 8px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  color: var(--text-on-brand);
  background: var(--brand);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease;
  -webkit-font-smoothing: antialiased;
}
.cr-btn-danger-solid:hover { background: var(--brand-hover); }
.cr-btn-danger-solid:active { background: var(--indigo-95); }
.cr-btn-danger-solid:disabled { background: var(--brand-disabled-bg); color: var(--brand-disabled-fg); opacity: 1; cursor: not-allowed; }
.cr-btn-danger-solid:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* Modal Cancel scoped override — matches the modal confirm button's
   optical-centering so both labels look balanced inside 32px. */
#crConfirmCancel.btn-std,
#crAppRemoveCancel.btn-std,
#auInactiveConfirmCancel.btn-std,
#auRemoveUserCancel.btn-std,
#pcDeleteGroupCancel.btn-std { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 32px; padding: 2px 12px 0; font-family: var(--ff); font-size: 14px; font-weight: 500; line-height: 16px; border-radius: 8px; }

/* Permission Capability — Delete permission group dialog. Wider than
   the stock .cr-confirm-dialog so the impacted-roles list reads
   comfortably without truncation, and the body line keeps its
   24px bottom-margin (the original .cr-confirm-body rule applies
   unchanged — only the new .pc-impacted-roles block adds layout). */
.pc-delete-dialog { max-width: 520px; }
.pc-delete-dialog .cr-confirm-body { margin-bottom: 16px; }
.pc-impacted-roles {
  margin: 0 0 24px 0;
  padding: 12px 14px;
  border: 1px solid var(--border-subtle);
  border-radius: 8px;
  background: var(--bg-hover-soft);
}
.pc-impacted-roles-title {
  font-family: var(--ff);
  font-size: 13px;
  font-weight: 600;
  line-height: 18px;
  color: var(--text-primary);
  margin-bottom: 8px;
}
.pc-impacted-roles-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 180px;
  overflow-y: auto;
}
.pc-impacted-role-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.pc-impacted-role-item:last-child { border-bottom: 0; padding-bottom: 0; }
.pc-impacted-role-item:first-child { padding-top: 0; }
.pc-impacted-role-name {
  font-size: 13px;
  font-weight: 600;
  line-height: 18px;
  color: var(--text-primary);
}
.pc-impacted-role-meta {
  font-size: 12px;
  line-height: 16px;
  color: var(--text-secondary);
}
.pc-impacted-roles-empty {
  margin: 0;
  font-size: 13px;
  line-height: 18px;
  color: var(--text-secondary);
}

/* ─── Toast — canonical ADS Toast (Figma 70:62) ───────────────────────
   Anatomy is a single row: [status icon] [title + message, stacked]
   [close], left-bordered in the semantic color, white surface, 6px
   radius, elevation/30 shadow. These are the structural/EDL-light-
   default rules; the exact ADS token values (colors, elevation, the
   16px/12px/4px spacing scale) are layered on top for
   `html[data-iam-version="v4"][data-theme="ads-preview"]` further
   down this file (search "R52 — Toast"), since V4.1 can still be
   switched back to EDL Light/Dark via the theme menu. */
.edl-toast-container {
  position: fixed;
  top: 24px;
  right: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  z-index: 10001;
  pointer-events: none;
  max-width: calc(100vw - 48px);
}
.edl-toast {
  pointer-events: auto;
  width: 320px;
  max-width: 100%;
  box-sizing: border-box;
  background: var(--bg-surface);
  border-radius: 8px;
  border-left: 4px solid var(--brand-text);
  padding: 12px 16px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  box-shadow: 0 0 32px 0 rgba(23, 29, 35, 0.25);
  font-family: var(--ff);
  animation: edl-toast-in 180ms ease-out;
}
.edl-toast.is-leaving {
  animation: edl-toast-out 160ms ease-in forwards;
}
/* Entrance/exit motion origin matches the top-right anchor:
   slide in from -8px above, slide out back up on dismiss. Subtle,
   non-blocking, no bounce/overshoot — satisfies the ADS motion
   requirement without inventing a custom flashy animation. */
@keyframes edl-toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes edl-toast-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
  .edl-toast { animation: none; }
  .edl-toast.is-leaving { animation: none; }
}
.edl-toast-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.edl-toast-content {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.edl-toast-title {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  letter-spacing: 0;
  color: var(--brand-text);
  word-wrap: break-word;
}
.edl-toast-body {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--gray-95);
  word-wrap: break-word;
}
.edl-toast-body strong { font-weight: 600; }
.edl-toast-close {
  flex-shrink: 0;
  align-self: flex-start;
  width: 16px;
  height: 16px;
  padding: 0;
  margin: 0;
  background: transparent;
  border: none;
  border-radius: 2px;
  color: var(--gray-95);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/* Glyph keeps its native 10×10 size (not stretched to fill the box) —
   the surrounding padding on `.edl-toast-close` (8px under the ADS
   32×32 hit-target rule further down, reproducing Figma's 16px icon
   box around the 10×10 "x") supplies the correct inset. */
.edl-toast-close svg { width: 10px; height: 10px; display: block; }
.edl-toast-close:hover { opacity: 0.75; }
.edl-toast-close:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* Type variants — icon + title color; message/body stays neutral
   (gray-95) across every variant, matching the ADS spec where only
   the headline (not the supporting message) carries semantic color. */
.edl-toast--informative .edl-toast-title { color: var(--indigo-70); }
.edl-toast--informative .edl-toast-icon  { color: var(--indigo-70); }
.edl-toast--informative { border-left-color: var(--indigo-70); }
.edl-toast--success .edl-toast-title     { color: var(--green-60); }
.edl-toast--success .edl-toast-icon      { color: var(--green-60); }
.edl-toast--success { border-left-color: var(--green-60); }
.edl-toast--warning .edl-toast-title     { color: var(--orange-70); }
.edl-toast--warning .edl-toast-icon      { color: var(--orange-70); }
.edl-toast--warning { border-left-color: var(--orange-70); }
.edl-toast--error .edl-toast-title       { color: var(--red-60); }
.edl-toast--error .edl-toast-icon        { color: var(--red-60); }
.edl-toast--error { border-left-color: var(--red-60); }

.cr-card { background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 16px; padding: 16px 24px 24px; margin-bottom: 24px; }

/* Tightened section header spacing — pulled closer to the first field */
.cr-section-header { display: flex; align-items: center; gap: 8px; padding: 8px 0 4px 0; }
.cr-section-header[data-cr-toggle],
.cr-section-header[data-au-toggle] { cursor: pointer; user-select: none; }
.cr-section-header[data-cr-toggle]:focus-visible,
.cr-section-header[data-au-toggle]:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; border-radius: 4px; }
.cr-section-chev { flex-shrink: 0; color: var(--brand-text); transition: transform 0.15s ease; }
.cr-card.collapsed .cr-section-chev { transform: rotate(-90deg); }
@media (prefers-reduced-motion: reduce) {
  .cr-section-chev { transition: none; }
}
/* Round 28 (2026-08-11, Edit Role QA) — the chevron is wrapped in a
   real `<button>` (`#crBasicCard`/`#crFuncsCard` in index.html) per an
   accessibility requirement to use actual button elements for chevron
   controls. `tabindex="-1"`/`aria-hidden="true"` in the markup keep it
   from being a second, redundant tab stop — the header row itself
   (`role="button"`, `aria-expanded`, a dynamically-updated `aria-label`)
   remains the one real keyboard toggle target. At this default 16x16
   size (no padding/border/background) it is visually identical to the
   bare `<svg>` it replaces, so every consumer of this markup — Create
   Role included — renders pixel-for-pixel unchanged; only Edit Role's
   `#crBasicCard`/`#crFuncsCard` grow it to a ~32px clickable hit area
   (see the Edit-Role-scoped rule further down this file). */
.cr-section-chev-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  flex-shrink: 0;
  cursor: pointer;
}
/* `.cr-section-header-row` (Edit User's Basic Information header — the
   toggle + Revoke access button share this row, see index.html) must
   stay visible on collapse alongside `.cr-section-header` itself, so
   Revoke access remains reachable even while the card body is
   collapsed. Every other `.cr-card` consumer has no such wrapper, so
   this exclusion is a no-op for them. */
.cr-card.collapsed > :not(.cr-section-header):not(.cr-section-header-row) { display: none !important; }
.cr-section-title { font-size: 18px; font-weight: 800; line-height: 22px; color: var(--brand-text); }
.cr-section-summary { display: none; font-family: var(--ff); font-size: 14px; font-weight: 400; line-height: 22px; color: var(--text-muted); letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1 1 auto; }
.cr-card.collapsed .cr-section-summary { display: inline-block; }
.cr-card.collapsed .cr-section-summary:not(:empty)::before { content: "·"; margin-right: 8px; color: var(--text-placeholder); }

/* ═══ Shared V4 accordion collapsed-row contract ════════════════════
   ONE collapsed-state definition for every collapsible `.cr-card`
   section in V4 that must show ONLY its chevron + title when
   collapsed (no inline summary/metadata): Add/Edit User's Basic
   Information (#auBasicCard) and Roles & Permissions (#auRolesCard),
   and Create/Edit Role's Role Details (#crBasicCard) and Functions
   (#crFuncsCard) — Role Details + Functions QA pass, 2026-08-11,
   extending the exact contract Add/Edit User already used so all four
   cards render as visibly interchangeable instances of one component:
   same 10px/24px collapsed padding, same 44px header row min-height,
   same 8px chevron-to-title gap, same vertical centering, no summary
   text, no reserved space for removed content. (Previously `#crBasicCard`
   had its own bespoke 10/24/12 padding + 5px gap + a visible "· <role
   name>" summary, and `#crFuncsCard` had no collapsed override at all —
   two different, unequal collapsed rows. Both now fold into this one
   shared block instead of keeping separate CSS.) */
#auBasicCard.cr-card.collapsed,
#auRolesCard.cr-card.collapsed,
#crBasicCard.cr-card.collapsed,
#crFuncsCard.cr-card.collapsed {
  padding: 10px 24px;
}
#auRolesCard.cr-card.collapsed > .cr-section-header,
#crBasicCard.cr-card.collapsed > .cr-section-header,
#crFuncsCard.cr-card.collapsed > .cr-section-header {
  padding: 0;
  min-height: 44px;
  gap: 8px;
  align-items: center;
}
/* auBasicCard's toggle is one level deeper (nested inside
   `.cr-section-header-row`, see index.html) — restate the same
   collapsed-row padding/height reset on it directly so it matches
   every other card's collapsed geometry exactly. */
#auBasicCard.cr-card.collapsed > .cr-section-header-row > .cr-section-header {
  padding: 0;
  min-height: 44px;
  gap: 8px;
  align-items: center;
}
#auBasicCard.cr-card.collapsed .cr-section-summary,
#auRolesCard.cr-card.collapsed .cr-section-summary,
#crBasicCard.cr-card.collapsed .cr-section-summary,
#crFuncsCard.cr-card.collapsed .cr-section-summary {
  display: none !important;
}
#auBasicCard.cr-card.collapsed .cr-section-chev,
#auRolesCard.cr-card.collapsed .cr-section-chev,
#crBasicCard.cr-card.collapsed .cr-section-chev,
#crFuncsCard.cr-card.collapsed .cr-section-chev {
  display: block;
  flex-shrink: 0;
}

.cr-field { margin-top: 16px; }
.cr-field:first-of-type { margin-top: 12px; }
.cr-label { display: block; font-family: var(--ff); font-size: 14px; font-weight: 400; line-height: 21px; color: var(--text-muted); margin-bottom: 4px; }
.cr-req { color: #E52F52; }

.cr-input { width: 320px; height: 32px; padding: 0 12px; border: 1px solid var(--border-input); border-radius: 8px; font-family: var(--ff); font-size: 14px; font-weight: 400; line-height: 21px; color: var(--text-primary); background: var(--bg-surface); outline: none; transition: border-color 0.15s ease; }
/* Role Name (Create/Edit Role, Figma 1025:23238): the field is a
   narrow single-column input (~283px), not the generic 320px default
   used elsewhere in this form family. */
.cr-input-rolename { width: 283px; }
.cr-input::placeholder { color: var(--text-placeholder); }
.cr-input:hover { border-color: var(--text-muted); }
.cr-input:focus { border-color: var(--brand-text); }

.cr-textarea { width: 100%; height: 136px; padding: 8px 16px; border: 1px solid var(--border-input); border-radius: 8px; font-family: var(--ff); font-size: 14px; font-weight: 400; line-height: 21px; color: var(--text-primary); background: var(--bg-surface); outline: none; resize: vertical; transition: border-color 0.15s ease; }
.cr-textarea::placeholder { color: var(--text-placeholder); }
.cr-textarea:hover { border-color: var(--text-muted); }
.cr-textarea:focus { border-color: var(--brand-text); }

/* ═══ EDL CHECKBOX ═══ 16px, white→indigo-70 with white check */
.cr-help-text { margin-top: 6px; font-size: 12px; font-weight: 400; line-height: 18px; color: var(--text-secondary); }

.cr-check,
.cr-perm-check {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border: 1px solid var(--border-input);
  border-radius: 2px;
  background: var(--bg-surface);
  cursor: pointer;
  flex-shrink: 0;
  margin: 0;
  position: relative;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.cr-check:hover:not(:checked):not(:disabled),
.cr-perm-check:hover:not(:checked):not(:disabled) { border-color: var(--text-muted); }
.cr-check:focus-visible,
.cr-perm-check:focus-visible { outline: 2px solid var(--indigo-70); outline-offset: 2px; }
.cr-check:checked,
.cr-perm-check:checked {
  background: var(--brand);
  border-color: var(--brand-text);
}
.cr-check:checked::after,
.cr-perm-check:checked::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'><path d='M3.5 8.2 L6.6 11.3 L12.5 5.2' stroke='white' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
}
/* Indeterminate (e.g. the Users list select-all checkbox when some but
   not all filtered rows are selected). Previously only the ADS Preview
   theme (P5b block below) painted this state; added here so EDL Light/
   Dark — which share this same base `.cr-perm-check` pipeline — don't
   fall back to an unstyled native indeterminate glyph now that a real
   table (not just the Create Role matrix) relies on it. */
.cr-check:indeterminate,
.cr-perm-check:indeterminate {
  background: var(--brand);
  border-color: var(--brand-text);
}
.cr-check:indeterminate::after,
.cr-perm-check:indeterminate::after {
  content: '';
  position: absolute;
  left: 2.5px;
  right: 2.5px;
  top: 50%;
  height: 1.5px;
  background-color: #FFFFFF;
  transform: translateY(-50%);
  border-radius: 1px;
}
.cr-access-level-row {
  margin-top: 14px;
  flex-shrink: 0;
}
.cr-access-level-row .cr-label { margin-bottom: 8px; }
.cr-access-level-wrap {
  display: flex;
  align-items: center;
  width: 100%;
}
.cr-access-level-dd {
  width: 248px;
  max-width: 100%;
}
.cr-access-level-trigger {
  height: 32px;
  min-height: 32px;
}
.cr-access-level-value {
  font-weight: 500;
  color: var(--text-primary);
}
/* Summary body (filled by JS); visual card is .cr-access-summary-card */
.cr-access-summary {
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  width: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}
.cr-access-summary-top {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
  flex-shrink: 0;
}
.cr-access-level-title {
  font-size: 16px;
  font-weight: 600;
  line-height: 22px;
  color: var(--text-primary);
}
.cr-access-level-subtitle {
  font-size: 12px;
  line-height: 18px;
  color: var(--text-muted);
  margin-top: 0;
  font-weight: 400;
}
/* Permission details: fixed label column + one comma-separated values string. */
.permission-detail-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  width: 100%;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 22px;
}
.permission-row {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr);
  column-gap: 24px;
  align-items: start;
  width: 100%;
  min-width: 0;
}
.permission-label {
  font-weight: 600;
  white-space: nowrap;
  color: var(--text-primary);
}
.permission-values {
  width: 100%;
  min-width: 0;
  display: block;
  font-weight: 500;
  color: var(--text-primary);
  white-space: normal;
  word-break: normal;
  overflow-wrap: normal;
  line-height: inherit;
}
.cr-access-summary-list {
  flex: 0 1 auto;
  min-height: 0;
}
.cr-access-summary-empty { margin-top: 4px; font-size: 14px; line-height: 22px; color: var(--text-primary); flex: 0 1 auto; }
/* Functions: text CTAs — no underline (Atlas / EDL link-button language) */
.cr-customize-link {
  margin-top: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-text);
  font-family: var(--ff);
  font-size: 14px;
  line-height: 22px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  -webkit-font-smoothing: antialiased;
}
.cr-customize-link:hover { color: var(--brand-text-hover); }
.cr-customize-link:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; border-radius: 2px; }
.cr-collapse-all-link { margin-top: 14px; }
/* Create Role Permissions only: `.cr-summary-cta` is not used on Add/Edit User. */
#createRolePage .cr-access-summary-card .cr-summary-cta {
  margin-top: 24px;
  padding-top: 0;
  position: static;
  align-self: center;
  flex-shrink: 0;
}
#createRolePage .cr-app-section:not([data-expanded="true"]):not([data-access-level="Custom"]):not([data-access-level="Custom Access"]) {
  min-height: 388px;
}
#createRolePage .cr-app-section:not([data-expanded="true"]):not([data-access-level="Custom"]):not([data-access-level="Custom Access"]) .cr-access-level-row {
  margin-bottom: 10px;
}
#createRolePage .cr-app-section:not([data-expanded="true"]):not([data-access-level="Custom"]):not([data-access-level="Custom Access"]) .cr-summary-stack,
#createRolePage .cr-app-section:not([data-expanded="true"]):not([data-access-level="Custom"]):not([data-access-level="Custom Access"]) .cr-access-summary-card {
  flex: 1 1 auto;
}
#createRolePage .cr-app-section:not([data-expanded="true"]):not([data-access-level="Custom"]):not([data-access-level="Custom Access"]) .cr-access-summary-card .cr-summary-cta {
  margin-top: auto;
  padding-top: 12px;
}

/* ═══ EDL DROPDOWN ═══ Exact Figma fidelity (node 390:15700, 390:15519) */
.cr-dd { position: relative; display: inline-block; width: 283px; }
.cr-dd-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 32px;
  padding: 0 16px;
  border: 1px solid var(--border-input);
  border-radius: 8px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
  background: var(--bg-surface);
  cursor: pointer;
  outline: none;
  text-align: left;
  transition: border-color 0.15s ease;
  -webkit-appearance: none;
  appearance: none;
}
.cr-dd-trigger:hover { border-color: var(--text-muted); }
.cr-dd.open .cr-dd-trigger,
.cr-dd-trigger:focus-visible { border-color: var(--brand-text); }
/* Open: connected list surface (matches search dropdown seam, not a floating popover). */
.cr-dd.open .cr-dd-trigger {
  border-radius: 8px 8px 0 0;
  border-bottom-color: var(--border-default);
}
.cr-dd-value {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
}
.cr-dd-value.is-placeholder { color: var(--text-placeholder); }
.cr-dd-chev { flex-shrink: 0; color: var(--text-muted); margin-left: 10px; transition: transform 0.15s ease; }
.cr-dd.open .cr-dd-chev { transform: rotate(180deg); }

.cr-dd-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  width: 283px;
  background: var(--bg-surface);
  border-radius: 8px;
  box-shadow: var(--shadow-pop);
  padding: 0;
  z-index: 1000;
  overflow: hidden;
  display: none;
}
.cr-dd.open .cr-dd-menu { display: flex; flex-direction: column; }
/* Portaled under trigger: fixed layer, same width, seam to field — no layout reflow in page. */
.cr-dd-menu.is-layered {
  display: flex !important;
  flex-direction: column;
  position: fixed;
  margin: 0;
  left: 0;
  top: 0;
  width: auto;
  min-width: 0;
  border-radius: 0 0 8px 8px;
  border: 1px solid var(--brand-text);
  border-top: 1px solid var(--border-default);
  box-shadow: var(--shadow-pop);
  max-height: min(50vh, 320px);
  overflow-x: hidden;
  overflow-y: auto;
}
.cr-dd-option {
  display: flex;
  align-items: center;
  width: 100%;
  height: 48px;
  padding: 0 16px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
  background: var(--bg-surface);
  cursor: pointer;
  user-select: none;
  transition: background-color 0.1s ease;
  box-sizing: border-box;
}
.cr-dd-option:hover:not(.is-disabled),
.cr-dd-option.is-active:not(.is-disabled) { background: var(--bg-hover); }
.cr-dd-option.is-selected,
.cr-dd-option.is-selected:hover { background: var(--brand-bg-selected); color: var(--text-primary); }
.cr-dd-option.is-disabled { color: var(--text-placeholder); cursor: not-allowed; }
.cr-dd-option.is-disabled:hover { background: var(--bg-surface); }

/* Type-to-filter search row inside "Select applications" (Create
   Role Functions card) — the ADS searchable-select treatment for a
   `.cr-dd` menu. Visually matches `.edl-combo-input` (same border,
   radius, typography) but lives inside the menu rather than being the
   trigger itself, since this field keeps its explicit two-step
   Select → Add flow. */
.cr-dd-search-wrap { flex-shrink: 0; padding: 8px; border-bottom: 1px solid var(--border-default); }
.cr-dd-search {
  width: 100%;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border-input);
  border-radius: 6px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
  background: var(--bg-surface);
  outline: none;
  box-sizing: border-box;
  transition: border-color 0.15s ease;
}
.cr-dd-search::placeholder { color: var(--text-placeholder); }
.cr-dd-search:hover { border-color: var(--text-muted); }
.cr-dd-search:focus { border-color: var(--brand-text); }
.cr-dd-options { flex-shrink: 0; overflow-y: auto; max-height: 240px; }
.cr-dd-empty {
  padding: 16px;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 21px;
  color: var(--text-muted);
  text-align: center;
}

/* Add-application row (dropdown + Add button).
   The row hugs its content on the left so the Add button sits
   directly beside the dropdown with a normal 12px gap — no
   stretching, no space-between, no max-width trap. The field
   column does NOT grow to fill remaining width; instead it sizes
   to its child (.cr-dd is 283px wide via line 1748), which keeps
   the Add button glued to the dropdown's right edge.
   (Frances QA 2026-05-31 — previously the field column had
   `flex: 1 1 auto; max-width: 320px`, which expanded the column
   to 320px and pushed the Add button 37px further right than
   intended.) */
.cr-app-row { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.cr-app-row-field { display: flex; flex-direction: column; flex: 0 0 auto; min-width: 0; }

.cr-btn-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 16px;
  border: 1px solid var(--brand-text);
  border-radius: 8px;
  background: var(--bg-surface);
  color: var(--brand-text);
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  -webkit-font-smoothing: antialiased;
}
.cr-btn-add svg { flex-shrink: 0; }
.cr-btn-add { align-self: flex-end; }
.cr-btn-add:hover:not(:disabled) { background: var(--brand-bg-soft); }
.cr-btn-add:active:not(:disabled) { background: var(--brand-bg-selected); }
.cr-btn-add:disabled {
  border-color: var(--border-input);
  color: var(--text-placeholder);
  cursor: not-allowed;
  background: var(--bg-surface);
}
.cr-btn-add:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* Create Role / Edit Role override — filled EDL primary visual,
   same token family as .cr-btn-save (Save Role / Save Permission).
   Matches Figma 924:14107 ("+ Add" filled-purple) and the latest
   Create Role brief's "use EDL disabled styling already used
   elsewhere" instruction. Scoped to #createRolePage so the
   Permission Management toolbar Add button (.pc-page) keeps its
   existing outlined visual. */
#createRolePage .cr-btn-add {
  border: none;
  background: var(--brand);
  color: var(--text-on-brand);
}
#createRolePage .cr-btn-add:hover:not(:disabled) { background: var(--brand-hover); }
#createRolePage .cr-btn-add:active:not(:disabled) { background: var(--indigo-95); }
#createRolePage .cr-btn-add:disabled {
  background: var(--brand-disabled-bg);
  color: var(--brand-disabled-fg);
  border-color: transparent;
  cursor: not-allowed;
  opacity: 1;
}

/* Figma 924:14107 matrix layout: each added application occupies a
   single full-width row, with the function/action matrix table
   rendered beneath the app title. Reverted from the prior 2-column
   grid because the matrix needs the full content width to land all
   Read/Create/Update/Delete/Assign columns without wrapping. */
#createRolePage .cr-perms-content {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: stretch;
}
.cr-app-section {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  align-self: start;
  height: auto;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: 10px;
  padding: 18px 18px 16px;
  box-sizing: border-box;
  overflow-x: visible;
  transition: border-color 0.18s ease, box-shadow 0.22s ease;
}
.cr-app-section:hover { border-color: #d6d9df; box-shadow: 0 2px 8px rgba(17, 24, 39, 0.06); }
.cr-app-section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 2px;
  flex-shrink: 0;
}
.cr-app-section-head:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; border-radius: 4px; }
.cr-app-head-left { display: flex; flex-direction: row; align-items: center; gap: 8px; min-width: 0; }
/* Round 28 (2026-08-11) — the nested "Core Planning"-style accordion
   chevron is wrapped in a real `<button>` (see `buildAppSectionHtml`
   in app.js), matching the same pattern used for Role Details/
   Functions above. Default 16x16, no padding/border/background,
   keeps it visually identical to the bare `<svg>` it replaces —
   `#createRolePage.is-edit-mode` (further down this file) is the only
   place that grows it to a ~32px clickable hit area. */
.cr-app-head-chev-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  flex-shrink: 0;
  cursor: pointer;
}
.cr-app-title {
  margin: 0;
  font-family: var(--ff);
  font-size: 18px;
  font-weight: 700;
  line-height: 24px;
  color: var(--text-primary);
  letter-spacing: 0;
}
.cr-app-remove {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 24px;
  padding: 0;
  background: none;
  border: none;
  border-radius: 2px;
  font-family: var(--ff);
  font-size: 13px;
  font-weight: 500;
  line-height: 20px;
  color: var(--brand-text);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.cr-app-remove > svg { display: block; flex-shrink: 0; width: 16px; height: 16px; color: currentColor; }
.cr-app-remove:hover { color: var(--brand-text-hover); background: var(--brand-bg-soft); }
.cr-app-remove:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; }

.cr-app-body { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; min-width: 0; width: 100%; overflow-x: visible; }
.cr-summary-stack {
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: stretch;
  margin-top: 12px;
  min-height: 0;
  min-width: 0;
  width: 100%;
}
.cr-access-summary-card {
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: stretch;
  min-height: 0;
  min-width: 0;
  width: 100%;
  /* Slightly tighter side padding so summary text has a bit more horizontal room
     without changing the outer app card shell. */
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  box-sizing: border-box;
}
/* Preset access: detail panel hidden until expanded. Custom: show accordion panel, hide preset summary. */
.cr-custom-area {
  margin-top: 0;
  border-top: 0;
  padding-top: 0;
  max-height: 0;
  opacity: 0;
  min-width: 0;
  width: 100%;
  overflow: hidden;
  transition: max-height 320ms cubic-bezier(0.33, 1, 0.68, 1), opacity 240ms ease, margin-top 200ms ease, padding-top 200ms ease;
}
.cr-app-section[data-expanded="true"] .cr-custom-area,
.cr-app-section[data-access-level="Custom"] .cr-custom-area,
.cr-app-section[data-access-level="Custom Access"] .cr-custom-area {
  margin-top: 20px;
  border-top: 1px solid var(--border-subtle);
  padding-top: 18px;
  max-height: min(72vh, 640px);
  opacity: 1;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.cr-app-section[data-access-level="Custom"] .cr-summary-stack,
.cr-app-section[data-access-level="Custom Access"] .cr-summary-stack {
  display: none !important;
}
.cr-app-section[data-expanded="true"] [data-show-all],
.cr-app-section[data-access-level="Custom"] [data-show-all],
.cr-app-section[data-access-level="Custom Access"] [data-show-all] {
  display: none !important;
}
.cr-module { margin-top: 12px; min-width: 0; width: 100%; }
.cr-module:first-child { margin-top: 0; }
.cr-module-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 4px;
  margin: 0 -4px;
  border: 0;
  border-radius: 6px;
  background: none;
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  color: var(--indigo-70);
  cursor: pointer;
  text-align: left;
  transition: background-color 0.12s ease;
}
.cr-module-head-main {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.cr-module-summary {
  font-family: var(--ff);
  font-size: 12px;
  font-weight: 500;
  line-height: 18px;
  color: var(--text-muted);
  flex-shrink: 0;
  white-space: nowrap;
}
.cr-module-head:hover { background: var(--bg-hover); }
.cr-module-head:focus-visible { outline: 2px solid var(--indigo-50); outline-offset: 2px; }
/* Same language as page accordions: collapsed = chevron right, expanded = chevron down */
.cr-module-chev {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  color: var(--brand-text);
  transition: transform 0.15s ease;
  transform: rotate(-90deg);
}
.cr-module-head[aria-expanded="true"] .cr-module-chev { transform: rotate(0deg); }
.cr-module-body { margin-top: 8px; min-width: 0; width: 100%; }
.cr-perm-group { margin-bottom: 0; }
.cr-perm-group-title { font-size: 13px; font-weight: 600; line-height: 18px; color: var(--text-secondary); margin-bottom: 8px; display: none; }
.cr-perm-grid { display: block; min-width: 0; width: 100%; }
.cr-perm-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; width: 100%; }
.cr-perm-item { display: flex; align-items: flex-start; gap: 8px; }
.cr-perm-check { margin-top: 3px; }
.cr-perm-label { min-width: 0; font-family: var(--ff); font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-primary); cursor: pointer; user-select: none; white-space: normal; overflow-wrap: normal; word-break: normal; }

/* ─── Create Role: Functions matrix (Figma 924:14138) ───────────────
   Each added application renders a single matrix table beneath an
   inline app heading: one row per resource, one column per action
   union (Read / Create / Update / Delete / Assign). The app section
   lives directly inside the Functions card — no nested borders,
   no inner card chrome — so visually it reads as a sub-section, not
   a nested card. Scoped tightly to #createRolePage so we don't leak
   styles to any other data table in the app.

   Round 9 (2026-06-09): override the base `.cr-app-section`
   `align-self: start` (which shrinks the section to the matrix's
   intrinsic width) with `align-self: stretch` + explicit `width:
   100%`. This is what makes the Remove application action line up
   on the same right edge across every application — previously,
   Disney Ads Agent's narrow `Functions | Read` table caused its
   section (and Remove button) to sit ~268px to the left of Core
   Planning's. */
#createRolePage .cr-app-section.cr-app-section--matrix {
  background: transparent;
  border: 0;
  border-radius: 0;
  /* Round 17 (2026-06-09): match Figma 924:14150 section frame.
     Each app section is inset 16px on the left and 16px on the right
     from the parent (.cr-perms-content). The matrix table fills the
     full content area between these insets — same left edge, same
     right edge, same width across every application (Core Planning,
     Identity and Access Management, Inventory Catalog Manager,
     Targeting Options Manager, Disney Ads Agent). Chevron + app
     name + Remove application all sit on the same 16/16 inset rails
     as the table below. Replaces the previous asymmetric `padding: 0`
     + 32px body indent which made the matrix start at section.left+32
     and end at section.right (asymmetric).

     Round 24 (2026-06-09 — nested-accordion alignment QA): the
     `padding: 0 16px` is dropped so the per-app section frame sits
     flush with the parent `.cr-perms-content` content edge. Combined
     with the tightened `.cr-matrix-fn` / `.cr-matrix-th-fn` left
     padding (16 → 4) below, this brings the matrix row labels into
     the same x-position as the parent "Functions" title text instead
     of 28px to its right. App headers receive their own
     `padding-left` rule below so chevron + app title + Remove
     application stay visually nested under the parent section, while
     the table content lines up with the parent grid. The Remove
     button's right edge now sits flush with the table's right edge
     (1242 ≈ parent content right edge), keeping the cross-app
     right-alignment that Round 9 first established. */
  padding: 0;
  align-self: stretch;
  width: 100%;
  /* Override the legacy preset-summary min-height (line ~1732) so the
     matrix section sizes naturally to its table content. The pre-existing
     selector at ~1732 uses three :not() pseudo-classes (specificity
     (1,4,0)) so we double the class (id + class*2 = (1,2,0)) plus the
     attribute selector below for higher specificity. */
  min-height: 0;
}
#createRolePage .cr-app-section.cr-app-section--matrix:not([data-expanded="true"]):not([data-access-level="Custom"]):not([data-access-level="Custom Access"]) {
  min-height: 0;
}
#createRolePage .cr-app-section--matrix:hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
/* Round 11 (2026-06-09): lighter app title — 16/600 Indigo 70 reads
   as a sub-section heading (not a card heading), which calms the
   visual weight of having 5 stacked sections inside the Functions
   card. Color and Indigo-70 affordance preserved per brief. */
#createRolePage .cr-app-section--matrix .cr-app-title {
  font-family: var(--ff);
  font-size: 16px;
  font-weight: 600;
  line-height: 22px;
  color: var(--brand-text);
  /* Round 33 (2026-08-11): truncate unusually long application names
     instead of overlapping "Remove application" — the native `title`
     attribute set in `buildAppSectionHtml()` (app.js) supplies the
     full-name tooltip. Requires the sibling `min-width: 0` already set
     below (flex items don't shrink past their content size otherwise). */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Section head padding tightened so each app block reads as a
   compact subsection rather than a card. The first section gets a
   slightly smaller top padding; subsequent sections inherit the
   hairline separator from `.cr-app-section--matrix + .cr-app-section--matrix`
   below.

   Round 28 (2026-08-11 — nested "Core Planning" header QA): the
   toggle target grew from `.cr-app-head-left` (chevron+title only) to
   this whole row (`role="button"` now lives here, see app.js), so it
   needs its own `cursor`/`user-select`/`gap`. The three children
   (chevron button, title, Remove application) are now flat flex
   siblings — `justify-content: space-between` is dropped in favor of
   `.cr-app-title { flex: 1 1 auto }` below, which grows to consume the
   row's remaining width and is what actually pushes Remove
   application (and, in Edit Role, the chevron) to the row's right
   edge; `gap` sets the fixed spacing between whichever two children
   end up adjacent. `order` values below keep Create Role's original
   "chevron+title left / Remove right" visual exactly as it was; only
   `#createRolePage.is-edit-mode` (further down this file) reorders to
   "title left / Remove application + chevron grouped at the right". */
#createRolePage .cr-app-section--matrix .cr-app-section-head {
  padding: 12px 0 8px;
  margin-bottom: 0;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  cursor: pointer;
  user-select: none;
}
#createRolePage .cr-app-section--matrix .cr-app-head-chev-btn {
  order: 0;
}
#createRolePage .cr-app-section--matrix .cr-app-title {
  order: 1;
  flex: 1 1 auto;
  min-width: 0;
}
#createRolePage .cr-app-section--matrix .cr-app-remove {
  order: 2;
}
#createRolePage .cr-app-section--matrix .cr-app-head-chev {
  color: var(--brand-text);
  flex-shrink: 0;
  transition: transform 0.18s ease;
}
/* Collapsed state: rotate the chevron from down (default) to
   right, and hide the matrix wrapper. Checkbox state is preserved
   because the inputs stay in the DOM. */
#createRolePage .cr-app-section--matrix.cr-app-section--collapsed .cr-app-head-chev {
  transform: rotate(-90deg);
}
#createRolePage .cr-app-section--matrix.cr-app-section--collapsed .cr-app-section-body {
  display: none;
}
/* Round 17 (2026-06-09): matrix body flush with section content
   area. The section itself owns the 16px left/right insets (see
   `.cr-app-section--matrix { padding: 0 16px }` above), so the body
   no longer needs its own left padding. This matches Figma 924:14150
   where the table sits at the same left x-position as the chevron +
   app name in the section header — both inset 16px from the section
   frame edge. Was `padding-left: 32px` in Round 14 (a different,
   nested-indent treatment that placed the matrix 32px to the right
   of the chevron, which is not the Figma 924:14138 spec). */
#createRolePage .cr-app-section--matrix .cr-app-section-body {
  padding-left: 0;
}
/* Nested indentation: application sections sit one level inside
   the Functions card content. The Functions card's helper text
   and "Add application" controls remain aligned with the card's
   content edge; only the per-app sections receive the indent so
   the hierarchy reads:
       Functions
         Choose which applications...
         Add application
           Core Planning
             matrix
           IAM
             matrix
   Remove stays inside the section head's space-between row, so
   it naturally aligns with the right edge of the indented section
   (= right edge of the matrix table). */
#createRolePage .cr-perms-content {
  padding-left: 20px;
}
/* Round 13 (2026-06-09): section spacing only — the duplicate
   horizontal-divider artifact (last row `border-bottom` stacked
   against the section `border-top`) is replaced with vertical
   spacing alone. The end of each table's last `<tr>` already has a
   `1px var(--border-default)` bottom border, which provides the
   single hairline that separates one application section from the
   next. The first section has neither, keeping the very top of the
   matrix clean below "Add application".

   Round 19 (2026-06-09 — layout-only QA pass for Figma 924:14138):
   the previous `padding-top: 4px` here made the asymmetric padding
   inspection (first section `0px 16px`, the rest `4px 16px 0px`)
   that does not exist in Figma — every app section in the Figma
   frame uses `px-[16px]` only, no vertical padding. We replace the
   4px padding-top with pure margin so every section has the same
   structural insets and the vertical rhythm comes from one source
   (margin) instead of two (margin + padding). Visual gap between
   sections stays ~16px (was margin 12 + padding 4 = 16 before; now
   pure margin: 16). */
#createRolePage .cr-perms-content .cr-app-section--matrix + .cr-app-section--matrix {
  margin-top: 16px;
}
/* Round 13: every matrix table spans the section width — same left
   edge, same right edge, same total width across all five
   applications. Column widths are still locked via <colgroup>:
     - `.cr-mcol-fn { width: 240px; }` — Functions column. Same
       column width across every app; first row labels (Orders,
       Users, Offerings, Targeting Options, Forecasting) all start
       at the same x-position.
     - `.cr-mcol-act { width: 100px; }` — every action column. Same
       column width whether the app has 1 action (Disney Ads Agent)
       or 5 actions (IAM, TOM).
     - `.cr-mcol-spacer { width: auto; }` — trailing column with no
       explicit width. With `table-layout: fixed; width: 100%;` the
       browser distributes the remaining section width entirely to
       this column. That's what lets Disney Ads Agent end at the
       same right edge as the wider apps without distorting the
       Functions / Read columns and without adding fake disabled
       action columns. */
#createRolePage .cr-matrix {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-family: var(--ff);
  margin-top: 0;
}
#createRolePage .cr-matrix .cr-mcol-fn     { width: 240px; }
/* Round 17 (2026-06-09): same 136px action column width. After moving
   the 16/16 inset onto the section (instead of a one-sided 32px body
   indent), the matrix table fills the section content area:
     section.width 964 − padding 16×2 = 932px available
       5 × 136 + 240 = 920px →  12px spacer for IAM, TOM
       4 × 136 + 240 = 784px → 148px spacer for Core Planning, ICM
       1 × 136 + 240 = 376px → 556px spacer for Disney Ads Agent
   The spacer column absorbs the remainder so every app's table ends
   at the same right edge (section.right − 16). */
#createRolePage .cr-matrix .cr-mcol-act    { width: 136px; }
#createRolePage .cr-matrix .cr-mcol-spacer { width: auto; }
/* Spacer <th> / <td> — render empty space with the same row borders
   so the trailing whitespace continues the table's visual grid
   (single hairline at the row bottom, no checkbox, no label). */
#createRolePage .cr-matrix .cr-matrix-th-spacer {
  padding: 0;
  border-bottom: 1px solid var(--border-default);
  background: transparent;
}
#createRolePage .cr-matrix .cr-matrix-cell-spacer {
  padding: 0;
  height: inherit;
  background: var(--bg-surface);
}
#createRolePage .cr-matrix thead th {
  border-bottom: 1px solid var(--border-default);
  background: transparent;
  text-align: left;
  vertical-align: middle;
  /* Round 11: thinner header (~36-40px target). Was 8px 16px (~42px). */
  padding: 6px 16px;
  font-family: var(--ff);
  /* Round 26 (2026-06-09 — header typography): bumped from 12px/18px
     to 14px/20px so the header labels (Functions, Read, Create,
     Update, Delete, Assign, Access) read as peer-level table chrome
     instead of getting visually overpowered by the larger row
     checkboxes and 14px body row labels. Weight stays at 500 so the
     header still reads as a header — heavier than the 400 body row
     labels — without crossing into the bold/heavy territory used by
     the application titles (16px / 600).
     Letter-spacing 0.02em (a small-caps-style tweak that made sense
     at 12px) is dropped at 14px where it would only loosen the label
     and undermine the "clearly readable" goal in the brief. Color
     stays Gray 70 / `--text-secondary` per Figma 924:14138 so the
     header remains muted readable rather than competing with row
     content. */
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  color: var(--text-secondary);
  white-space: nowrap;
}
#createRolePage .cr-matrix-th-inner {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
#createRolePage .cr-matrix thead th.cr-matrix-th-fn {
  /* Width is driven by <col class="cr-mcol-fn">; this rule owns the
     left padding so the "Functions" header label lines up with the
     row label's left padding (`.cr-matrix-fn { padding-left: 4px }`).

     Round 24 (2026-06-09 — nested-accordion alignment QA): reduced
     from 16px to 4px because the section frame no longer carries
     its own 16px left inset (Round 24 removed
     `.cr-app-section.cr-app-section--matrix { padding: 0 16px }`).
     With section padding 0 + table padding 4, the Functions header
     text lands at the same x-position as the parent Functions
     title text in `.cr-perms-card`, satisfying the "align row
     labels with the main Functions content grid" rule.

     Selector promoted to `.cr-matrix thead th.cr-matrix-th-fn` to
     out-specify the more-specific
     `#createRolePage .cr-matrix thead th { padding: 6px 16px }`
     rule above (same specificity trap that R23 had to fix on the
     row-label side). Without the promotion the 16px would silently
     win and the Functions header text would render at x=294 while
     the row labels rendered at x=282. */
  padding-left: 4px;
}
#createRolePage .cr-matrix-th-act {
  /* Round 11: width is driven by <col class="cr-mcol-act">; remove
     the legacy `min-width: 110px` so the colgroup wins. */
  text-align: center;
}
#createRolePage .cr-matrix-th-act .cr-matrix-th-inner {
  justify-content: flex-start;
}
/* Column-level select-all in each action header. The checkbox
   reuses `.cr-perm-check` for EDL visuals (border, hover, focus,
   checked); the wrapper sets pointer cursor + vertical centering
   and prevents text-selection so clicking the label doesn't
   highlight it. */
#createRolePage .cr-matrix-col-head {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
}
#createRolePage .cr-matrix-col-head:hover .cr-matrix-col-head-label {
  color: var(--text-primary);
}
#createRolePage .cr-matrix-col-head-label {
  font: inherit;
  color: inherit;
}
/* Round 12 (2026-06-09 header checkbox quieting):
   the column-header select-all checkbox is a *table control*, not
   a selected-data indicator. Previously it inherited the full
   `.cr-perm-check` visual — solid Indigo 70 fill in `:checked` and
   `:indeterminate` — which made every fully-selected column show
   another purple square in the header row, reading as "a wall of
   purple boxes" on top of the already-purple row cells.
   The new treatment keeps EDL semantics (Indigo 70 affordance,
   accessible focus ring, hover hint) but switches every state to a
   subtle outlined / tinted look that's lighter than row cells:
     • Unchecked: white bg, Gray 40 outline, 14×14 (vs row 16×16).
     • Hover (unchecked): Gray 70 outline only.
     • Checked: Indigo 70 outline + Indigo 5 tinted bg + small
       Indigo 70 check — no solid fill.
     • Indeterminate: white bg + Gray 40 outline + Indigo 70 dash.
     • Focus: keeps the EDL focus ring from `.cr-perm-check`.
   All selectors are anchored to `#createRolePage .cr-matrix-col-toggle`
   so row `.cr-perm-check` cells inside the same matrix are untouched
   and continue to render the original loud, clear selected style. */

/* Default unchecked + size — overrides `.cr-perm-check` base only
   for the column-header toggle. */
#createRolePage .cr-matrix-col-toggle {
  width: 14px;
  height: 14px;
  border-color: var(--gray-40, #9EB0BD);
  background: var(--bg-surface);
}
#createRolePage .cr-matrix-col-toggle:hover:not(:checked):not(:indeterminate):not(:disabled) {
  border-color: var(--text-muted);
}

/* Checked — tinted, not solid. Indigo 70 outline + Indigo 05 wash +
   Indigo 70 check so the affordance reads "selected" but at a
   lower visual weight than the row cells' solid Indigo 70 fill.
   The SVG check is recoloured to Indigo 70 to match the outline
   instead of the previous white-on-purple combination. */
#createRolePage .cr-matrix-col-toggle:checked {
  background: var(--indigo-05);
  border-color: var(--brand-text);
}
#createRolePage .cr-matrix-col-toggle:checked::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16' fill='none'><path d='M3.5 8.2 L6.6 11.3 L12.5 5.2' stroke='%233611C8' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Indeterminate — keep the table-control feel: white bg, muted
   outline, Indigo 70 dash. Explicitly overrides the previous
   purple-fill rule for this selector. */
#createRolePage .cr-matrix-col-toggle:indeterminate {
  background: var(--bg-surface);
  border-color: var(--gray-40, #9EB0BD);
}
#createRolePage .cr-matrix-col-toggle:indeterminate::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16' fill='none'><path d='M4 8h8' stroke='%233611C8' stroke-width='1.75' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
}

/* Vertical alignment: the global `.cr-perm-check { margin-top: 3px }`
   rule was sized for `.cr-perm-item` flex layouts; inside the matrix
   header label this would push the smaller 14×14 box slightly off the
   text baseline. Reset to 0 so the checkbox sits centered next to the
   muted action label. */
#createRolePage .cr-matrix-th .cr-matrix-col-toggle {
  margin-top: 0;
}
#createRolePage .cr-matrix tbody td {
  border-bottom: 1px solid var(--border-default);
  padding: 0;
  vertical-align: middle;
  background: var(--bg-surface);
}
#createRolePage .cr-matrix tbody td.cr-matrix-fn {
  /* Round 17 (2026-06-09): 11px vertical padding → 44px row height
     to land at the upper end of the brief's 40–44px range, moving
     closer to the Figma 48px row without exceeding the brief.

     Round 23 (2026-06-09 — alignment QA): selector promoted from
     `#createRolePage .cr-matrix-fn` to
     `#createRolePage .cr-matrix tbody td.cr-matrix-fn` so it can
     out-specify the more-specific
     `#createRolePage .cr-matrix tbody td { padding: 0; }` rule above
     (which carries one extra type-selector and was silently zeroing
     out the intended 16px inset). Without that promotion the row
     labels collapsed to x=294 while the Functions header sat at
     x=310, visibly misaligned across every app section.

     Round 24 (2026-06-09 — nested-accordion alignment QA): left
     padding reduced from 16px to 4px (paired with the matching
     `.cr-matrix-th-fn { padding-left: 4px }` change above and the
     `.cr-app-section--matrix { padding: 0 }` change above) so the
     "Functions" header and every row label (Orders, Users,
     Offerings, Targeting Options, Plan Queries, …) land at the
     same x-position as the parent Functions title text in
     `.cr-perms-card`. This collapses the 28px drift between the
     parent Functions title and the per-app row labels that the
     brief screenshot flagged via the green guide. Vertical padding
     (11px top + 11px bottom) is unchanged so row height stays at
     44px. */
  padding: 11px 4px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
  white-space: nowrap;
  /* Defensive: truncate long resource names rather than expand the
     locked-width Functions column. */
  overflow: hidden;
  text-overflow: ellipsis;
}
#createRolePage .cr-matrix-cell {
  /* Round 14 (2026-06-09): 44px row height matches `.cr-matrix-fn`
     padding above (11px top + 22px line + 11px bottom). */
  height: 44px;
  text-align: left;
  padding: 0 16px;
}
#createRolePage .cr-matrix-cell--empty {
  background: var(--bg-surface);
}
/* The matrix has no disabled / "not available" cell state for
   *standard* CRUD function rows — every cell within an app's column
   set renders as a real checkbox (per Figma 924:14107 and the Create
   Role brief). The previous `.cr-matrix-cell--na` / `.cr-matrix-na`
   em-dash treatment was removed for that reason; per-app columns are
   controlled by the union of each resource's `support` array in
   `CR_MATRIX_RESOURCES_BY_APP`.

   Sensitive Data Access / Regional Data Access are the one exception:
   they are not CRUD functions, only expose Read + Create, and must
   render Update/Delete/Assign as fully empty, non-interactive cells
   rather than clickable checkboxes (2026-08-10 Create Role rebuild,
   Figma 1025:23238 + Final-QA follow-up: unsupported cells must stay
   visually empty — no dash/em-dash/placeholder glyph of any kind).
   `.cr-matrix-row--data-access` marks the row; `.cr-matrix-cell-
   unsupported` is the empty cell itself — no content, no focus
   target, `aria-hidden` so screen readers skip straight past it. Its
   height/padding are kept so the column width and row height stay
   identical to every other function row even though the cell renders
   nothing. */
#createRolePage .cr-matrix-row--data-access .cr-matrix-fn {
  color: var(--text-primary);
}
#createRolePage .cr-matrix-cell-unsupported {
  height: 44px;
  padding: 0 16px;
  user-select: none;
}
/* Subtle grouping cue: a slightly heavier top border on the first of
   the two trailing data-access rows reads as "these two belong to a
   distinct group at the end of the table" without a colored panel or
   extra chrome (per brief: no large colored panels, no separate
   global-settings look). */
#createRolePage .cr-matrix-row--data-access[data-data-access-key="sensitive"] td {
  border-top: 1px solid var(--border-default);
}
#createRolePage .cr-matrix-check-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 4px;
  cursor: pointer;
  margin-left: 8px;
}
#createRolePage .cr-matrix-check {
  margin: 0;
}
#createRolePage .cr-matrix-check-visual {
  display: none;
}
/* Drop the legacy hover shadow on the matrix card — Figma shows a
   static white card with no elevation lift on hover. */
#createRolePage .cr-app-section--matrix:hover {
  border-color: var(--border-default);
  box-shadow: none;
}

/* Functions section helper paragraph (Figma copy) */
#createRolePage .cr-section-help {
  margin: 4px 0 12px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-muted);
}
/* When the Functions card is collapsed via the chevron, hide the
   helper text in the same pass as the rest of the body. */
#createRolePage .cr-card.collapsed .cr-section-help { display: none; }

/* ═══ ADD USERS PAGE ═══ */
/* `scrollbar-gutter: stable` — see the matching comment on `.cr-page`.
   Same root cause here: Edit User (Access card + effective-access
   table) is taller than Add User Step 2 (no Access card yet), so only
   Edit User was tall enough to trigger this panel's own scrollbar,
   shifting the centered `.au-shell` — and its back link/title — ~7.5px
   left of Add User's identical shell. Reserving the gutter always
   keeps `#auBack`/`#auPageTitle` at the exact same left edge whether
   the page is in Add or Edit mode. */
/* Two-region page shell (Final-QA: "page-header background region",
   Figma 1023:22021) — `.au-page` is now a flex column of exactly two
   full-bleed surfaces (header, then main-content), each spanning the
   complete width right of the sidebar. `.au-page` itself keeps the
   canvas color as its own background so there's no seam if a surface
   is ever shorter than the viewport (there isn't, today, since
   `.au-page-main-surface` uses flex:1 to always reach the bottom). */
.au-page {
  position: fixed;
  inset: 0;
  top: 48px;
  background: var(--page-header-surface-bg);
  z-index: 90;
  overflow-y: auto;
  scrollbar-gutter: stable;
  display: flex;
  flex-direction: column;
}
/* Edit Team (#editTeamPage) now shares the identical two-region
   page-header background as Add/Edit User and Create/Edit Role
   (Vertical-spacing audit, Figma 1023:22021 — see the HTML comment on
   `#editTeamPage` for the full rationale). It no longer needs its own
   background override: `.au-page-header-surface` / `.au-page-main-surface`
   fully cover the panel with the same tokens every other detail page uses. */
/* Full-width header-region surface: back nav + title + description +
   actions. `display: flow-root` gives it its own block-formatting
   context so `.au-header-shell`'s padding/centering can't visually
   escape it — the surface's painted background always matches exactly
   what it structurally contains. */
.au-page-header-surface {
  flex: 0 0 auto;
  /* Bridges the reserved `scrollbar-gutter: stable` track on `.au-page`
     (see `measureV4ScrollbarGutter()` in app.js) so this surface's
     painted background reaches `.au-page`'s true right edge instead of
     stopping one scrollbar-width short of it. Falls back to a plain
     100% before the JS measurement runs (first paint) or if it never
     runs at all — a same-color header still sits flush against
     `.au-page`'s own background in that instant, so there is no
     visible seam even without the compensation applied yet. */
  width: calc(100% + var(--v4-scrollbar-gutter-w, 0px));
  background: var(--page-header-surface-bg);
  display: flow-root;
}
/* Full-width main-content surface: every `.au-card`. `flex: 1 0 auto`
   makes it reach the bottom of the viewport even when the page's
   content is shorter than one screen (e.g. Add User before any
   applications are assigned), so the background boundary is never a
   short rectangle floating above empty canvas-colored space. */
.au-page-main-surface {
  flex: 1 0 auto;
  /* See `.au-page-header-surface` comment above — same scrollbar-gutter
     bridge, needed even more here since this surface's wash color
     differs from `.au-page`'s own fallback background. */
  width: calc(100% + var(--v4-scrollbar-gutter-w, 0px));
  background: var(--page-main-surface-bg);
  display: flow-root;
}
.au-shell { width: min(1048px, calc(100% - 96px)); margin: 8px auto 56px; }
/* Header/main shell variants — same shared width formula as the base
   `.au-shell` (never duplicated), just with the old single top/bottom
   margin redistributed onto the two surfaces above as padding instead
   (padding can never collapse, so the boundary lands exactly where
   Figma shows it regardless of content height). `au-header-shell`'s
   8px top + 12px bottom padding matches Figma's exact measured gaps
   (back-nav sits 8px below the header surface's top edge; the
   description sits 12px above the header/main-content boundary).
   `au-main-shell` needs no extra padding of its own — `.au-card`'s
   existing `margin-top: 24px` (unchanged) already reproduces Figma's
   24px gap from the boundary to the first card, and `flow-root` on
   `.au-page-main-surface` keeps that margin from collapsing out the
   top of the surface. The existing 56px bottom breathing room moves
   to the main surface's own padding-bottom for the same reason. */
.au-shell.au-header-shell {
  margin: 0 auto;
  padding: 8px 0 12px;
}
.au-shell.au-main-shell {
  margin: 0 auto;
  padding: 0 0 56px;
}
/* .au-back — see the shared back-navigation component defined once,
   next to `.cr-back`, near the top of this file. */
.au-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; }
.au-header-left { min-width: 0; }
.au-title { font-family: "MultiplaneTWDC Display", var(--ff); font-size: 28px; font-weight: 500; line-height: 38px; color: var(--text-primary); }
.au-subtitle { margin-top: 11px; font-size: 14px; font-weight: 500; line-height: 20px; color: var(--text-secondary); }
.au-header-actions { display: inline-flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 16px; margin-top: -2px; }
.au-remove-user-link {
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  color: var(--brand-text);
  cursor: pointer;
  text-decoration: none;
}
.au-remove-user-link:hover { color: var(--brand-text-hover); text-decoration: underline; }
.au-remove-user-link:focus-visible { outline: 2px solid var(--brand-text); outline-offset: 2px; border-radius: 4px; }
.au-remove-user-link[hidden] { display: none !important; }

.au-btn-save { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 32px; padding: 2px 16px 0; border: none; border-radius: 8px; font-family: var(--ff); font-size: 14px; font-weight: 500; line-height: 16px; color: var(--text-on-brand); background: var(--brand); white-space: nowrap; cursor: pointer; transition: background-color 0.15s ease; -webkit-font-smoothing: antialiased; }
.au-btn-save:hover:not(:disabled) { background: var(--brand-hover); }
.au-btn-save:active:not(:disabled) { background: var(--indigo-95); }
.au-btn-save:disabled { background: var(--brand-disabled-bg); color: var(--brand-disabled-fg); cursor: not-allowed; opacity: 1; }
.au-btn-save:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

.au-card { margin-top: 24px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 16px; padding: 12px 24px 18px; }
/* Padding corrected to 16/24/24 for Edit User specifically (Figma node
   1003:20186, Basic Information + Access card wrappers:
   `pt-[16px] px-[24px] pb-[24px]`) — matches `.cr-card`'s own default
   padding. Scoped to `#addUsersPage` rather than restating the base
   `.au-card` rule above, because Edit Team's cards
   (`.tm-details-card` / `.tm-members-card`) also carry the `.au-card`
   class and were relying on the old 12/24/18 value; changing the base
   rule would have silently altered Edit Team's padding too, which is
   out of scope for this pass. */
html[data-iam-version="v4"] #addUsersPage .au-card {
  padding: 16px 24px 24px;
}
/* Add User accordion bodies (Create Role uses `.cr-field` siblings; AU wraps grid + roles in one node). */
#addUsersPage .au-section-body { min-width: 0; }
#addUsersPage .cr-section-header[data-au-toggle] {
  padding: 6px 0 4px;
}

.au-grid { margin-top: 8px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.au-field { min-width: 0; }
/* Basic Information now shares ONE identity-row + 4-field layout across
   BOTH Add and Edit modes (Figma 1023:22053 / 847:16172 — same visual
   foundation). Name, First/Last name, Email, Status, and the
   "Profile picture" note field are retired from the visible grid in
   both modes: identity (avatar/name/email/status) lives in
   `.au-id-block` instead, and Status silently defaults to Active
   (still tracked via the hidden `#auStatusValue` input for Save logic). */
.au-field-edit-only { display: none; }
#addUsersPage .au-field-first,
#addUsersPage .au-field-last { display: none; }
#addUsersPage .au-field-email { display: none; }
#addUsersPage .au-field-status { display: none; }
#addUsersPage .au-profile-field { display: none; }
#addUsersPage .au-field-preferred { order: 3; }
#addUsersPage .au-field-region { order: 4; }
#addUsersPage .au-field-team { order: 5; }
#addUsersPage .au-field-timezone { order: 6; }
/* Status: label stacked above Active/Inactive toggle (same rhythm as other Basic fields). */
.au-field-status {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.au-field-status .au-label {
  display: block;
  width: 100%;
  margin-bottom: 4px;
}
.au-field-status .au-status-seg {
  align-self: flex-start;
}
.au-label { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 4px; font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-muted); }
.au-req { color: #E52F52; }
.au-info { width: 12px; height: 12px; color: var(--text-muted); }
.au-input {
  box-sizing: border-box;
  width: 100%;
  height: 32px;
  min-height: 32px;
  max-height: 32px;
  margin: 0;
  padding: 5px 12px;
  border: 1px solid var(--border-input);
  border-radius: 8px;
  background: var(--bg-surface);
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s ease;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.au-input::placeholder { color: var(--text-placeholder); }
.au-input:hover { border-color: var(--text-muted); }
.au-input:focus { border-color: var(--brand-text); }
.au-input-readonly,
#addUsersPage.is-edit-mode #auEmail {
  color: var(--text-secondary);
  background: var(--bg-hover-soft);
  border-color: var(--border-input);
  cursor: default;
}
.au-input-readonly:hover,
#addUsersPage.is-edit-mode #auEmail:hover {
  border-color: var(--border-input);
}
.au-input-readonly:focus,
#addUsersPage.is-edit-mode #auEmail:focus {
  border-color: var(--border-input);
}
#addUsersPage.is-edit-mode .au-field-email .au-req { display: none; }
#addUsersPage.is-edit-mode .au-field-status .au-req { display: none; }
/* Add User selects: official EDL combo — full width, 32px trigger; chevron/clear stay vertically centered. */
#addUsersPage .au-field-dd.edl-combo {
  display: block;
  width: 100%;
  margin: 0;
}
#addUsersPage .au-field-dd.edl-combo .edl-combo-input-wrap {
  height: 32px;
  min-height: 32px;
  max-height: 32px;
  box-sizing: border-box;
}
#addUsersPage .au-field-dd.edl-combo .edl-combo-input {
  box-sizing: border-box;
  height: 32px;
  min-height: 32px;
  max-height: 32px;
  margin: 0;
  /* One trailing control (chevron OR clear), same slot as Figma IAM */
  padding: 5px 36px 5px 12px;
  line-height: 20px;
}
/* Chevron and clear: same 20×20 hit target, 12×12 glyph; vertically centered in 32px field.
   Mutual-exclusion between the two trailing icons is enforced by the global rule
   `.edl-combo-input-wrap:has(.edl-combo-clear:not(.hidden)) .edl-combo-toggle { display:none }`. */
#addUsersPage .au-field-dd.edl-combo .edl-combo-clear,
#addUsersPage .au-field-dd.edl-combo .edl-combo-toggle {
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  box-sizing: border-box;
}
#addUsersPage .au-field-dd.edl-combo .edl-combo-clear svg,
#addUsersPage .au-field-dd.edl-combo .edl-combo-toggle svg {
  width: 12px;
  height: 12px;
  display: block;
}
/* Assign Roles: same column shell as Region/Team (`.au-field` + `.cr-dd`) — flex sizing on wrapper, not on `.cr-dd`. */
#addUsersPage .au-role-row > .au-role-dd-field {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
}
.au-status-seg {
  margin-top: 0;
  display: inline-flex;
  width: auto;
  max-width: 100%;
  height: 32px;
  box-sizing: border-box;
  align-items: stretch;
  border: 1px solid var(--border-input);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-surface);
}
.au-status-opt {
  flex: 0 0 92px;
  min-width: 92px;
  min-height: 0;
  height: auto;
  align-self: stretch;
  padding: 0 12px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-right: 1px solid var(--border-input);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.14s ease, color 0.14s ease;
}
.au-status-opt:last-child { border-right: 0; }
.au-status-opt:hover { background: var(--bg-hover); color: var(--text-primary); }
.au-status-opt.is-selected { background: var(--brand-bg-selected); color: var(--brand-text); }
.au-status-opt:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: -2px; }
#addUsersPage.is-edit-mode .au-status-seg { display: none; }
.au-status-readonly {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  color: var(--text-primary);
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
}
.au-status-readonly[hidden] { display: none; }
.au-status-readonly svg { flex-shrink: 0; }
.au-profile-field { align-self: start; }
.au-profile-field .au-label { margin-bottom: 4px; }
.au-profile-sync-note { margin-top: 4px; font-size: 13px; font-weight: 400; line-height: 18px; color: var(--text-secondary); }

.au-access-card { margin-top: 12px; }
.au-role-field { margin-top: 8px; }
/* Cap row to exactly one role-card column. The `.au-role-cards` grid
   below uses `gap: 24px` at desktop widths (see `#addUsersPage
   .au-role-cards`), so the column width is `(100% - 24px) / 2`. The
   row's max-width formula must match the same 24px gap to guarantee
   the row's right edge lands on the same x as the first card's right
   edge — otherwise the input + Add button feel 2px narrower than the
   card stacked below, which reads as a sub-pixel right-edge wobble
   between the two stacked rectangles. Left edges already share x=0 of
   the section body and are unaffected by this value. */
#auRolesCard .au-role-row {
  max-width: min(100%, calc((100% - 24px) / 2));
}
.au-role-row { margin-top: 0; display: flex; align-items: center; gap: 12px; flex-wrap: nowrap; }
.au-role-row .au-btn-add { flex-shrink: 0; }
/* Add User: Inactive status — cannot assign roles (EDL disabled treatment) */
#addUsersPage .au-role-row .edl-combo.is-au-roles-locked .edl-combo-input-wrap {
  pointer-events: none;
  opacity: 0.55;
  cursor: not-allowed;
}
#addUsersPage .au-role-row .au-btn-add:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.au-btn-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 32px;
  min-height: 32px;
  max-height: 32px;
  padding: 0 12px;
  border: 1px solid var(--brand-text);
  border-radius: 8px;
  background: var(--bg-surface);
  color: var(--brand-text);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.au-btn-add:hover:not(:disabled) { background: var(--brand-bg-soft); }
.au-btn-add:active:not(:disabled) { background: var(--brand-bg-selected); }
.au-btn-add:disabled { border-color: var(--border-input); color: var(--text-placeholder); cursor: not-allowed; background: var(--bg-surface); opacity: 1; }
.au-btn-add:focus-visible { outline: 2px solid var(--brand-focus-ring); outline-offset: 2px; }

/* Match Create Role `.cr-perms-content`: two-column grid when space allows, single column ≤1023px.
   align-items: start — each role card keeps its own height; expanding one must not stretch siblings.
   Add/Edit User (`#addUsersPage`) uses `.au-role-cards-row` + stretch grid (see after `.au-role-list-fallback li`).
   Create Role app cards use `#createRolePage .cr-perms-content` grid + stretch. */
.au-role-cards {
  margin-top: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px;
  align-items: start;
  align-content: start;
}
/* Retired on Add User (Figma 1023:22053 QA pass — see the HTML
   comment on `#auRoleCards`): the shared `.au-role-cards { display:
   grid }` rule above otherwise wins over the plain `[hidden]` UA
   style, so restate it explicitly at ID specificity. */
#addUsersPage #auRoleCards[hidden] { display: none; }
.au-role-cards.has-roles { margin-top: 24px; }
/* Role summary cards — natural height so expanded cards do not stretch their row mate. */
.au-role-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 176px;
  height: fit-content;
  max-height: none;
  align-self: start;
  justify-content: flex-start;
  border: 1px solid var(--border-default);
  border-radius: 12px;
  background: var(--bg-surface);
  overflow: hidden;
  transition: border-color 0.18s ease, box-shadow 0.22s ease;
  box-sizing: border-box;
}
.au-role-card:hover { border-color: #d6d9df; box-shadow: 0 2px 8px rgba(17, 24, 39, 0.06); }
.au-role-card-top { padding: 24px 24px 22px; flex: 0 1 auto; min-height: 0; }
.au-role-card .cr-app-title { min-width: 0; }
.au-role-card .cr-app-body { margin-top: 20px; min-width: 0; flex: 0 1 auto; }
.au-role-block { margin-top: 16px; }
.au-role-block:first-child { margin-top: 0; }
.au-role-section-text {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: var(--text-secondary);
}
.au-role-access-value {
  margin: 0;
}
.au-role-view-toggle {
  margin-top: 18px;
  align-self: flex-start;
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  min-width: 0;
  text-align: left;
  white-space: normal;
}
.au-role-toggle-label { min-width: 0; }
.au-role-toggle-arr {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1em;
  line-height: 1;
}

.au-role-expand {
  flex: 0 0 auto;
  border-top: 1px solid var(--border-subtle);
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height 220ms ease-in-out, opacity 180ms ease-in-out;
}
.au-role-card.expanded .au-role-expand {
  max-height: none;
  opacity: 1;
  overflow: visible;
}
.au-role-expand-inner { padding: 18px 24px 18px; }
/* Expand panel: mirror Create Role `.cr-access-summary-list` two-column layout per app. */
.au-role-app-section { margin-top: 20px; }
.au-role-expand-inner > .au-role-app-section:first-child { margin-top: 0; }
.au-role-expand-inner > .au-perm-card-list:first-child { margin-top: 0; }
.au-role-app-section > .cr-label { margin-bottom: 8px; }
/* Wrapper for Add/Edit User permission list: `display: contents` by default so
   layout is unchanged; #addUsersPage ≥1024px overrides to a flex-growing inner panel. */
.au-role-app-detail {
  display: contents;
}
.au-role-perm-summary-list .permission-values {
  color: var(--gray-95);
}
.au-role-list-fallback {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.au-role-list-fallback li {
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
}

/* ─── Add/Edit User (#addUsersPage) — Roles & Permissions layout ─── */
#addUsersPage .au-role-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  align-items: start;
  align-content: start;
}
#addUsersPage .au-role-cards-row {
  display: contents;
}
#addUsersPage .au-role-card {
  align-self: start;
  height: fit-content;
  min-height: unset;
}
#addUsersPage .au-role-card.expanded .au-role-expand {
  flex: 0 0 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#addUsersPage .au-role-card.expanded .au-role-expand-inner {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-height: 0;
}
#addUsersPage .au-role-card-top {
  flex: 0 0 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#addUsersPage .au-role-view-toggle {
  margin-top: 24px;
  position: static;
  align-self: center;
}

/* Add/Edit User — permission apps: DOM is
   .au-role-expand-inner > .au-perm-card-list > .au-perm-card-row >
     .au-perm-card-stack > .au-role-app-section.au-perm-card > (.cr-label + .au-role-app-detail > list) */
#addUsersPage .au-perm-card-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
#addUsersPage .au-perm-card-list .au-role-app-section {
  margin-top: 0;
}
#addUsersPage .au-perm-card-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
  align-items: start;
}
#addUsersPage .au-role-card .permission-row {
  grid-template-columns: 140px minmax(0, 1fr);
  column-gap: 12px;
}
#addUsersPage .au-role-card .permission-values {
  display: block;
  width: 100%;
  min-width: 0;
  white-space: normal;
  word-break: normal;
  overflow-wrap: normal;
}
#addUsersPage .au-perm-card-row > .au-perm-card-stack {
  min-width: 0;
  min-height: 0;
  height: auto;
  align-self: start;
  display: flex;
  flex-direction: column;
}
#addUsersPage .au-perm-card-row > .au-perm-card-stack > .au-perm-card {
  flex: 0 1 auto;
  min-width: 0;
  min-height: 0;
  height: auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

@media (min-width: 1024px) {
  #addUsersPage .au-perm-card-row {
    grid-template-columns: 1fr;
    gap: 20px;
    align-items: start;
  }
  #addUsersPage .au-perm-card-row > .au-perm-card-stack > .au-perm-card > .cr-label {
    flex-shrink: 0;
  }
  #addUsersPage .au-perm-card-row > .au-perm-card-stack > .au-perm-card > .au-role-app-detail {
    display: block;
    flex: 0 1 auto;
    min-height: 0;
    min-width: 0;
    width: 100%;
    box-sizing: border-box;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  #addUsersPage .au-perm-card-row > .au-perm-card-stack > .au-perm-card > .au-role-app-detail > .au-role-perm-summary-list {
    flex: 0 0 auto;
    min-height: 0;
    align-content: start;
  }
  #addUsersPage .au-perm-card-row > .au-perm-card-stack > .au-perm-card > .au-role-app-detail > .au-role-list-fallback {
    flex: 0 0 auto;
    min-height: 0;
    align-items: flex-start;
  }
}

@media (max-width: 1023px) {
  #addUsersPage .au-perm-card-row > .au-perm-card-stack,
  #addUsersPage .au-perm-card-row > .au-perm-card-stack > .au-perm-card {
    height: auto;
  }
}

/* ═══ RESPONSIVE LAYOUT BREAKPOINTS ═══
   Design anchor: 1440x1080 (desktop-ideal). */

/* 1200–1439: desktop structure retained, slightly tighter spacing */
@media (max-width: 1439px) {
  .page { padding: 0 40px; max-width: 1360px; }
  .cr-shell { max-width: 1080px; padding: 24px 40px 64px; }
  .au-shell { width: min(1048px, calc(100% - 80px)); }
  .tbar { padding: 8px 40px 8px 16px; }
}

/* 1024–1199: 2-column grids for forms/cards */
@media (max-width: 1199px) {
  .page { padding: 0 32px; max-width: 1200px; }
  .hdr { padding: 24px 0 28px; }
  .tabs-row { padding: 14px 16px 8px; }
  #usersPanel, #rolesPanel, #teamsPanel { padding-top: 10px; }
  .tbar { height: auto; min-height: 48px; padding: 8px 32px 8px 16px; }
  .search { width: 280px; }

  .cr-shell { max-width: 980px; padding: 20px 32px 56px; }
  .cr-header { flex-wrap: wrap; }
  .cr-header-actions { width: 100%; justify-content: flex-end; padding-top: 0; }
  .cr-card { padding: 16px 20px 20px; }
  #auBasicCard.cr-card.collapsed,
  #auRolesCard.cr-card.collapsed,
  #crBasicCard.cr-card.collapsed,
  #crFuncsCard.cr-card.collapsed { padding: 10px 20px; }
  .cr-input, .cr-dd { width: 100%; }
  .cr-app-row { align-items: flex-end; }
  .cr-app-row-field { flex: 1 1 auto; min-width: 0; }
  .cr-dd, .cr-dd-menu { width: 100%; }
  /* Pagination triggers stay compact; `.cr-dd { width:100% }` is for form rows. */
  .pgn-dd.cr-dd { width: auto; min-width: 56px; }

  .au-shell { width: min(1048px, calc(100% - 64px)); }
  .au-card { padding: 12px 20px 15px; }
  .au-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .au-role-cards { gap: 20px; }
  #addUsersPage .au-role-cards {
    gap: 20px;
  }
  #auRolesCard .au-role-row { max-width: min(100%, calc((100% - 20px) / 2)); }
}

/* 768–1023: prioritize vertical stability and readability */
@media (max-width: 1023px) {
  .page { padding: 0 24px; max-width: 100%; }
  .nav { padding-right: 12px; }
  .nav-mod { padding: 10px 12px 10px 16px; }
  .nav-a { padding: 0 8px; font-size: 14px; }
  .nav-logo-img { width: 128px; }

  .tabs-row nav { gap: 18px; }
  .tab-btn { font-size: 16px; }
  .card { margin-bottom: 24px; }

  .tbar { gap: 12px; flex-wrap: wrap; justify-content: space-between; padding: 8px 24px 8px 16px; margin-bottom: 12px; }
  #usersPanel .tbar { margin-bottom: 8px; }
  .tbar-l { flex: 1 1 100%; flex-wrap: wrap; gap: 12px; }
  .search { width: min(100%, 420px); }
  /* `.tbar-r` (the shared right-actions wrapper) is the flex item that
     actually needs pushing to the wrapped row's right edge — margin-left
     on the inner `.btn-ghost` alone has no effect once it's nested inside
     `.tbar-r`, since the wrapper only ever sizes to its own content. */
  .tbar-r,
  .tbar > .btn-ghost { margin-left: auto; }

  .tbl th, .tbl td { padding: 0 6px; }
  /* Proportional to base 48px row at this breakpoint. */
  .tbl td { height: 44px; }

  .cr-shell { max-width: 100%; padding: 16px 24px 48px; }
  .cr-title { font-size: 24px; line-height: 32px; }
  .cr-subtitle { line-height: 20px; }
  .cr-header-actions { justify-content: flex-start; flex-wrap: wrap; }
  .cr-card { padding: 14px 16px 16px; margin-bottom: 16px; }
  #auBasicCard.cr-card.collapsed,
  #auRolesCard.cr-card.collapsed,
  #crBasicCard.cr-card.collapsed,
  #crFuncsCard.cr-card.collapsed { padding: 10px 16px; }
  #createRolePage .cr-perms-content {
    grid-template-columns: 1fr;
  }
  .cr-app-section { flex: 0 0 auto; width: 100%; max-width: 100%; height: auto; }
  .au-role-cards { grid-template-columns: 1fr; gap: 16px; }
  #addUsersPage .au-role-cards {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .au-shell { width: min(1048px, calc(100% - 48px)); margin-bottom: 40px; }
  .au-header { flex-wrap: wrap; gap: 14px; }
  .au-header-actions { width: 100%; justify-content: flex-end; margin-top: 0; }
  .au-grid { grid-template-columns: 1fr; gap: 14px; }
  .au-status-seg { width: 100%; }
  .au-status-opt { flex: 1 1 0; min-width: 0; }
  /* Role cards single-column; Assign row spans card width but stays compact (no full-bleed stretch). */
  #auRolesCard .au-role-row { max-width: 100%; }
  .au-role-row { flex-wrap: nowrap; gap: 10px; }
  #addUsersPage .au-role-row > .au-role-dd-field {
    flex: 0 1 320px;
    max-width: min(320px, calc(100% - 88px));
  }
  .au-btn-add { min-width: 72px; }
  .au-role-cards.has-roles { margin-top: 16px; }
  .au-role-card { min-height: 176px; }
  #addUsersPage .au-role-card { min-height: 0; }
}

/* ═══ Users-tab narrow-width responsive cleanup (Frances 2026-06-08) ═══
   Brief: keep desktop layout unchanged; make the Users tab usable when
   the browser narrows. All rules below are scoped to #usersPanel so the
   Roles tab, Teams tab, Edit User, Edit Role, Edit Team, navigation,
   themes, and older versions are untouched.

   Sub-1100: the toolbar may wrap (Filter + segmented control + search
   stay together on row 1 and the search shrinks; Export + Add User drop
   to row 2 only once it reaches its floor — see `#usersPanel .tbar-l`
   below); row avatars hide; Last login truncates more.
   ≤900: Last login column collapses (matches the existing c-em / c-ct
   hide pattern, so #usersTable's fixed table-layout keeps header/body
   columns in alignment without restructuring the markup). */
@media (max-width: 1100px) {
  #usersPanel .tbar {
    flex-wrap: wrap;
    row-gap: 10px;
    height: auto;
    min-height: 48px;
    align-items: center;
  }
  /* Round 38 (2026-08-12 — Users search restored): back to a growing,
     shrinkable box now that this group contains a search field again.
     Round 24's `flex: 0 0 auto` (correct while Filter + the segmented
     control were the only, content-sized, occupants) would refuse to
     shrink below the group's natural width, forcing the restored search
     to overflow the row rather than narrow. `1 1 auto` + `min-width: 0`
     instead lets the search absorb the squeeze first (it is the only
     shrinkable sibling — see `.ads-search`'s own `flex: 0 1 clamp(...)`
     and its 120px floor), and only once that floor is reached does
     `.tbar-r` wrap to a clean second row (`.tbar` itself keeps
     `flex-wrap: wrap`, just above).
     This group is deliberately `nowrap`: flexbox breaks lines using each
     item's flex-BASIS, before any shrinking is applied, so a wrapping
     `.tbar-l` dropped the search onto its own second row the moment its
     ~41.667vw basis exceeded the space left beside Filter + the
     segmented control (~1100px and below) — even though shrinking it a
     few px would have kept one tidy row. Wrapping the right-hand action
     group instead is the documented order of degradation for this
     toolbar. Genuinely narrow screens still get a two-row layout from
     the ≤768px `.tbar-l { width: 100% }` rule further down. */
  #usersPanel .tbar-l {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: nowrap;
    align-items: center;
    gap: 12px;
  }
  /* Pin Export + Add User to the TOP of the wrapped toolbar so the
     group visually sits in Row 1 alongside Filter + segmented control
     (instead of vertically centering against the 2-line `.tbar-l` and
     floating between rows). */
  #usersPanel .tbar-r {
    align-self: flex-start;
    flex: 0 0 auto;
  }
  /* Row avatars/photos only — Edit User's .au-id-avatar (different
     selector) and the assigned-role chip avatar are untouched. */
  #usersPanel #tbody .name-avatar { display: none; }
  /* Reclaim the 40px avatar + 8px flex gap for the Name column. The
     32px left gutter on .name-cell still anchors the column edge. */
  #usersPanel #tbody .name-cell { padding-left: 16px; }

  /* Compact Name column (≤1100px, which fully covers Redline's numeric
     `1024` breakpoint): showing both the name and its email as two
     truncated lines in a narrow column is visual noise, so the email
     line is hidden here — presentationally only. The underlying user
     record, `.c-em` (the always-hidden export/data column), search,
     filter, export, and the Add/Edit User pages are all untouched; this
     is a pure `display: none` on the visible second line inside the
     Name cell. `.name-cell-text`'s existing `justify-content: center`
     then re-centers the single remaining name line for free inside the
     unchanged 64px row — no row-height or divider changes needed.
     `.name-link` already carries the nowrap/ellipsis/min-width:0 chain
     it needs at every width (see its base rule above), and the shared
     truncation-tooltip system (`getCellTruncationInfo` in app.js) is a
     generic `td` hover/focus handler that already special-cases
     `.name-link`, so the full name surfaces automatically via the same
     canonical ADS tooltip (`.edl-tooltip`) once the row is short enough
     to actually clip it — no page-specific tooltip logic was added. */
  #usersPanel #usersTable tbody .name-cell-email { display: none; }

  /* Last login: allow tighter truncation. Header already has nowrap;
     this makes the body cell match so long values ellipsis instead of
     pushing the table beyond .tbl-wrap. */
  #usersPanel #usersTable td.c-ll {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ≤900: Last login collapses entirely. This mirrors the c-em / c-ct
   hide pattern (visibility:hidden + zero width on col + cell padding/
   border zeroed) so #usersTable's fixed table-layout naturally rebases
   the remaining columns without the header/body alignment drifting. */
@media (max-width: 900px) {
  #usersPanel #usersColgroup col[data-u-col="ll"] { width: 0; }
  #usersPanel #usersTable th.c-ll,
  #usersPanel #usersTable td.c-ll {
    padding: 0 !important;
    border: 0 !important;
    width: 0 !important;
    max-width: 0 !important;
    overflow: hidden !important;
    visibility: hidden;
  }
  #usersPanel #usersTable th.c-ll > *,
  #usersPanel #usersTable td.c-ll > * { visibility: hidden; }
}

/* <768: single-column mobile layout with no clipping/overflow */
@media (max-width: 767px) {
  .page { padding: 0 16px; }
  .nav { height: 44px; }
  .nav-mod { gap: 4px; padding: 8px 8px 8px 12px; }
  .nav-logo-group { gap: 8px; }
  .nav-logo-img { width: 108px; height: 20px; }
  .nav-a { font-size: 13px; padding: 0 6px; }
  .nav-r-btn { padding: 0 8px; height: 44px; }
  .ads-nav-search { display: none; }

  .hdr { padding: 20px 0 24px; }
  .hdr h1 { font-size: 24px; line-height: 32px; }
  .hdr p { line-height: 20px; }
  .tabs-row { height: auto; padding: 12px 12px 8px; }
  .tabs-row nav { width: 100%; gap: 14px; flex-wrap: wrap; }
  .tab-btn { font-size: 15px; padding-bottom: 6px; }
  #usersPanel, #rolesPanel, #teamsPanel { padding-top: 8px; }

  .tbar { padding: 8px 12px; margin-bottom: 10px; }
  #usersPanel .tbar { margin-bottom: 6px; }
  #rolesPanel .tbar,
  #teamsPanel .tbar { padding-right: 12px; }
  .tbar-l { width: 100%; }
  /* Round 38 (2026-08-12): the ≤1100px rule above keeps Users' left
     group on one line on purpose, so the search shrinks instead of
     dropping to its own row. Below 768px that stops being enough — even
     at the search's minimum width, Filter + the (non-shrinking) 179px
     segmented control + search need more room than a phone-width row
     has, so the group would overflow the card rather than shrink.
     Wrapping is the correct last resort at these widths (each control
     stays fully visible and left-aligned to the same content inset,
     just on two lines) and this is where the toolbar already switches
     to a stacked layout via `.tbar-l { width: 100% }` above. */
  #usersPanel .tbar-l { flex-wrap: wrap; }
  .btn-std, .btn-ghost { height: 32px; }
  .search { width: 100%; }

  .pgn {
    flex-wrap: wrap;
    gap: 8px;
    height: auto;
    min-height: 40px;
    padding: 6px 12px;
  }
  .pgn-pages { order: 3; width: 100%; justify-content: flex-start; gap: 8px; }
  .pgn-jump { margin-left: 0; }

  .cr-shell { padding: 14px 16px 36px; }
  .au-back, .cr-back { margin-bottom: 10px; }
  .cr-title { font-size: 22px; line-height: 30px; }
  .cr-header { margin-bottom: 14px; }
  .cr-header-actions { width: 100%; gap: 8px; }
  .cr-btn-remove, #crCancel.btn-std, .cr-btn-save { padding-left: 12px; padding-right: 12px; }
  .cr-app-row { flex-wrap: wrap; }
  .cr-app-row-field { width: 100%; }
  .cr-dd, .cr-dd-menu { width: 100%; }
  .pgn-dd.cr-dd { width: auto; min-width: 56px; }
  .cr-btn-add { width: 100%; }
  #createRolePage .cr-perms-content {
    grid-template-columns: 1fr;
  }
  .cr-app-section { flex: 0 0 auto; width: 100%; max-width: 100%; height: auto; }

  .au-shell { width: calc(100% - 32px); margin: 8px auto 28px; }
  .au-title { font-size: 26px; line-height: 34px; }
  .au-subtitle { margin-top: 8px; }
  .au-card { margin-top: 16px; padding: 11px 12px 11px; }
  #addUsersPage .cr-section-title { font-size: 17px; }
  .au-header-actions { justify-content: flex-start; }
  #auRolesCard .au-role-row { align-items: center; flex-wrap: nowrap; }
  #auRolesCard .au-role-row > .au-role-dd-field {
    flex: 1 1 auto;
    min-width: 0;
    max-width: min(280px, calc(100% - 84px));
  }
  #auRolesCard .au-role-row .au-btn-add { width: auto; }
  .au-role-cards { grid-template-columns: 1fr; gap: 12px; }
  #addUsersPage .au-role-cards-row {
    grid-template-columns: 1fr;
  }
  #addUsersPage .au-role-cards,
  #addUsersPage .au-role-cards-row {
    gap: 12px;
  }
  .au-role-card-top { padding: 14px 14px 16px; }
  .au-role-expand-inner { padding: 14px 14px 16px; }
}

/* ═══ EDL Dark theme — targeted component overrides ═══
   Reach elements whose colors cannot be cleanly abstracted into a single
   semantic token (fixed whites on avatars, scrollbars). */

/* Required-asterisk tint */
[data-theme="dark"] .cr-req { color: #FF8AA0; }

[data-theme="dark"] .permission-label {
  color: var(--text-primary);
}
[data-theme="dark"] .permission-values {
  color: var(--text-primary);
}

/* Avatar backdrop in dark navy — matches raised surface so the white rim
   doesn't pop against the navy table surface. */
[data-theme="dark"] .name-avatar { background: #1E2B44; }

/* Segmented control dark-mode: tokens remap automatically via --brand-text
   and --bg-surface, so only the divider between segments needs explicit
   alignment with the dark border token. */
[data-theme="dark"] .seg-btn + .seg-btn { border-left-color: var(--brand-text); }
[data-theme="dark"] .seg-ctrl { border-color: var(--brand-text); }

/* Search input icon contrast on dark */
[data-theme="dark"] .search-ico { color: var(--text-muted); }

/* Scrollbars */
[data-theme="dark"] ::-webkit-scrollbar { width: 12px; height: 12px; }
[data-theme="dark"] ::-webkit-scrollbar-track { background: var(--bg-app); }
[data-theme="dark"] ::-webkit-scrollbar-thumb {
  background: #263654;
  border-radius: 6px;
  border: 2px solid var(--bg-app);
}
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #34466A; }
[data-theme="dark"] * { scrollbar-color: #263654 var(--bg-app); }

/* Combo dropdown menus: recede vs global 12px dark scrollbars */
[data-theme="dark"] .edl-combo-menu {
  scrollbar-color: rgba(158, 176, 189, 0.42) transparent;
}
[data-theme="dark"] .edl-combo-menu::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
[data-theme="dark"] .edl-combo-menu::-webkit-scrollbar-track {
  background: transparent;
}
[data-theme="dark"] .edl-combo-menu::-webkit-scrollbar-thumb {
  background: rgba(158, 176, 189, 0.42);
  border-radius: 999px;
  border: none;
}
[data-theme="dark"] .edl-combo-menu::-webkit-scrollbar-thumb:hover {
  background: var(--gray-50);
}

/* Native select popup menus in dark user agent */
[data-theme="dark"] select option { background: var(--bg-surface); color: var(--text-primary); }

/* ─────────────────────────────────────────────────────────────────────────
   TEMPORARY: Hide "Company Title / Role" column in the Users table.
   This is a visibility-only override. All underlying structure is preserved:
     • <col data-u-col="ct"> in #usersColgroup
     • <th class="c-ct"> header with sort handler
     • <td class="c-ct"> cell rendering in app.js
     • user.title data on every record
   Note: the "Company Title / Role" input has been removed from the
   filter drawer. The underlying `filters.title` field still exists
   but is no longer user-settable through the UI.
   To restore the column later, simply DELETE this block. Nothing else needs
   to change. The freed 17.28% width is reallocated to the Role column
   (22.08% → 39.36%) so multi-role rows show more inline content without
   truncation. Region column is intentionally NOT hidden and retains its
   original 7.20% width.

   IMPORTANT — do NOT use `display: none` on th.c-ct / td.c-ct. In a
   table-layout: fixed layout, removing a cell from the layout flow causes
   the <col>→cell width mapping for subsequent columns to shift, which
   zero-widths the Region column (last column) on some browsers.
   Instead we collapse the cells to zero width + hide their content via
   visibility, which keeps all cells in the layout flow so every <col>
   width is honored and Region renders at its declared 7.20%.
   ───────────────────────────────────────────────────────────────────────── */
#usersTable th.c-ct,
#usersTable td.c-ct { padding: 0 !important; border: 0 !important; width: 0 !important; max-width: 0 !important; overflow: hidden !important; }
#usersTable th.c-ct > *,
#usersTable td.c-ct { visibility: hidden; }
#usersColgroup col[data-u-col="ct"] { width: 0; }
/* ─── Hide Email column (c-em) — same zero-width technique as c-ct.
   The email now shows as secondary text inside the Name cell.
   Keeping the th/td/col in the DOM prevents col-width mapping shifts. ── */
#usersTable th.c-em,
#usersTable td.c-em { padding: 0 !important; border: 0 !important; width: 0 !important; max-width: 0 !important; overflow: hidden !important; visibility: hidden; }
#usersColgroup col[data-u-col="em"] { width: 0; }

/* ─── Column widths (all non-hidden visible columns) ───────────────────
   Round 25 (2026-08-11 — column rebalance): every visible column's REAL
   width is computed at runtime by `setupRightmostAlignment`'s Users
   branch in app.js, which implements the same min-width + proportional
   "fr" grow model as this CSS Grid track spec (Select | Name | Role |
   Status | Team | Last login | Region):
     40px | minmax(240px,1.2fr) | minmax(320px,2fr) | 92px |
     minmax(220px,1.4fr) | 170px | 96px
   The px values below are ONLY the pre-JS first-paint fallback (a
   representative snapshot at a common ~1200px table width) so nothing
   flashes at an obviously-wrong width before that script runs on
   DOMContentLoaded — see the "Users only" branch in app.js for the
   actual source of truth, including the horizontal-scroll fallback
   for viewports too narrow to fit every column's minimum.
   em and ct remain zero-width (hidden). */
#usersColgroup col[data-u-col="sel"] { width: 40px; }
#usersColgroup col[data-u-col="nm"] { width: 246px; }
#usersColgroup col[data-u-col="rl"] { width: 329px; }
#usersColgroup col[data-u-col="st"] { width: 92px; }
#usersColgroup col[data-u-col="tm"] { width: 227px; }
/* Last login/Region are fixed px (not proportional) — see app.js. */
#usersColgroup col[data-u-col="ll"] { width: 170px; }
#usersColgroup col[data-u-col="rg"] { width: 96px; }
/* `min-width: 0` lets the JS-driven inline `width` on #usersTable
   (set below MIN_TABLE_WIDTH's threshold) be the only thing forcing
   this table wider than its wrapper — see the horizontal-scroll
   fallback in app.js's Users alignment branch. */
#usersTable { min-width: 0; }
/* Team/Organization and Last login: content nudged slightly right via
   padding (boundary already shifted with the Status column above). */
#usersTable th.c-tm,
#usersTable td.c-tm { padding-left: 16px; }
#usersTable th.c-ll,
#usersTable td.c-ll { padding-left: 18px; white-space: nowrap; }

/* ─── Last login / Region spacing + readability ─────────────────────
   These two were previously crowded/merged: Region was sized to
   whatever width happened to align its left edge with the "+ Add
   User" CTA above (often quite narrow) and had `padding-left: 0`, so
   its text sat almost flush against Last login's.

   Fix: Region got a stable ~100px column (see the `data-u-col="rg"`
   fixed-px branch of `setupRightmostAlignment` in app.js, which is the
   source of truth at runtime — the width below is only the pre-JS
   fallback) with normal left padding re-added here, and Last login
   keeps its own fixed width (168px, same JS branch) sized to
   comfortably fit the shortened "Mon D, H:MM AM/PM" display format
   app.js renders into `.c-ll` (see `shortLastLogin()`), so the two
   columns' content no longer touch. Header cells get the same padding
   as their body cells so the "Region" label and its sort icon stay
   aligned with the column below at every width. Row height, other
   columns' widths, sort, tooltip truncation, search, filter, and
   pagination are untouched.

   Round 34 (2026-08-11 — toolbar/table horizontal-alignment pass):
   Region's WIDTH (not this padding — the 22px left inset inside the
   column is unchanged) is once again tied to "Add User"'s left edge
   at runtime, the same `targetRightPx` CTA-anchoring `align()` already
   uses for R&P's Create Date column below — see the Users branch in
   app.js. This makes the "Region" header/values' left edge (column
   start + this 22px padding) land exactly at "Add User"'s left edge,
   restoring the behavior the "no longer does" note below used to
   describe, now scoped specifically to this one requirement rather
   than the whole column-rebalance pass Round 25 was doing. */
#usersTable th.c-rg,
#usersTable td.c-rg { padding-left: 22px; }

/* ─── Rightmost column alignment (R&P only) ────────────────────────
   R&P's Create Date column locks its VISIBLE content start to the
   "+ Create Role" CTA's "+" icon x-coordinate above (Users' Region
   is anchored the same way again as of Round 34 — see the Users
   branch in app.js and the comment directly above).

   A pure-CSS solution can only approximate this because the CTA's
   left edge is `card_right − (56px rail + button_text_width)`, where
   `button_text_width` depends on font rendering and therefore varies
   between browsers/OSes. The column width, expressed as a % of the
   card, only matches that fixed-px anchor at one specific card width.
   So the precise alignment is set at runtime in JS
   (`setupRightmostAlignment` in app.js), which measures the button's
   bounding box and writes a pixel-exact width to the `<col>` element.
   The CSS width below is only the pre-JS fallback so the layout
   doesn't flash a wrong width on first paint.

   The JS then:
     1. Sets the rightmost `<col>` to exactly `tableRight − ctaLeft` px.
     2. Redistributes the other cols pro-rata so the table still fills
        the card (no horizontal scrollbar appears).
     3. Re-runs on window resize (the CTA's px-offset from the right
        is viewport-invariant, but this keeps the proportional
        redistribution honest).

   For the content to start AT the column's left edge (= CTA left
   edge) rather than 8px inside it, we zero `padding-left` on the
   rightmost cell. The `<tr>` border still draws edge-to-edge because
   the cell still spans to the table's right edge (no padding-right or
   right-align override here). Row height, typography, sort, tooltip
   truncation, search, filter, and pagination are untouched. */
#rpTable th.rp-date,
#rpTable td.rp-date { padding-left: 0; }

/* Micro-polish: nudge Created By content 4px to the left so the gap
   before Create Date feels a touch more comfortable. The base rule
   `.tbl th, .tbl td { padding: 0 8px; }` gives every cell an 8px
   left inset; reducing just this column's left inset to 4px shifts
   the "Created By" header label and every row's name value left by
   exactly 4px. Column width is untouched, so:
     • Create Date stays pinned to the "+ Create Role" CTA anchor
       (set at runtime by setupRightmostAlignment in app.js).
     • No other column moves or changes width.
     • Created By's content area gains 4px of breathing room, which
       actually helps longer names (e.g. "Timothy Lovejoy") fit
       without additional truncation.
   Padding-right stays at the default 8px so the right-side gap to
   the date column grows by the same 4px. No typography, row height,
   sort, resize, tooltip, search, filter, or pagination impact. */
#rpTable th.rp-by,
#rpTable td.rp-by { padding-left: 4px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview theme — isolated, additive, non-destructive.

   Purpose:
   A third theme preview that re-skins the app with an ADS-flavored token
   set while leaving EDL Light (:root) and EDL Dark ([data-theme="dark"])
   completely untouched. Activated only when <html data-theme="ads-preview">.

   Isolation contract:
     • No EDL palette variable (--gray-*, --indigo-*, etc.) is overwritten.
     • No EDL semantic token declared in :root is overwritten globally.
     • All re-points live inside the scoped [data-theme="ads-preview"] block
       below (or its targeted component overrides further down), so selector
       specificity applies the new values only under this attribute.
     • All component CSS above already consumes these semantic tokens via
       var(--…), so swapping the token values automatically re-skins the UI
       without touching any component rule.

   Token values:
   The ADS-facing palette below is scoped-local to this block (prefixed
   --ads-*). It is never referenced from outside this block, so naming can
   evolve without affecting anything else. Values approximate the Disney
   Ads Design System library: cooler neutrals for surfaces, Disney blue
   accent in place of EDL indigo, deeper ink for primary text, softer
   shadows, larger radii if/when components opt in to --radius-* tokens.
   ─────────────────────────────────────────────────────────────────────── */
[data-theme="ads-preview"] {
  color-scheme: light;

  /* Local ADS palette — scoped to this block, used only by the remaps below.
     Named `--ads-*` to make absolutely sure no EDL token is overwritten. */

  /* Neutral gray ramp — anchored to the Ads DS Gray hue
     (file 2048:18, "Gray 50–900"). The published values feel
     warmer / less blue than the prior cooler ink ramp; aligning
     here means every surface, border, and hairline that consumes
     an --ads-ink-* alias automatically picks up the Ads DS
     palette without rewriting consumers.
       --ads-ink-05  → Gray 50  #eceeee (page canvas, hover-soft)
       --ads-ink-10  → ~Gray 50 #eceeee (hover wash; same step,
                                          reserved for future)
       --ads-ink-15  → Gray 50  #eceeee (subtle hairlines)
       --ads-ink-20  → Gray 100 #51585b (deeper hairlines)
       --ads-ink-30  → Gray 100 #51585b
       --ads-ink-40  → Gray 100 #51585b
       --ads-ink-50  → Gray 100 #51585b
       --ads-ink-60  → Gray 200 #3b4347 (text/muted)
       --ads-ink-70  → Gray 200 #3b4347 (text/secondary)
       --ads-ink-80  → Gray 300 #30383c
       --ads-ink-95  → Gray 600 #1e2528 (primary text). */
  --ads-ink-95:       #1E2528;    /* primary text */
  --ads-ink-80:       #30383C;
  --ads-ink-70:       #3B4347;
  --ads-ink-60:       #3B4347;
  --ads-ink-50:       #51585B;
  --ads-ink-40:       #51585B;
  --ads-ink-30:       #51585B;
  --ads-ink-20:       #51585B;
  --ads-ink-15:       #ECEEEE;
  --ads-ink-10:       #ECEEEE;
  --ads-ink-05:       #ECEEEE;

  /* ADS Design System indigo ramp.
     Source of truth: the canonical Ads Design System Figma file
     (DJb3yM8aOQjIAbTQ9Cd8Mi/Ads-Design-System--5.13-, "Documentation /
     Color" node 2048:18). Step 300 (#4045C2) is the published brand
     anchor — used by color/surface/brand, color/text/brand,
     color/border/brand, color/border/active, color/border/focus,
     color/controls/primary/rest, and color/icons/brand/rest. Step 50
     (#E2E3F2) is the brand-wash used for selected rows, active nav
     fills, and other large-area brand affordances.
     Naming uses ADS step numbers (50–700) under scoped `--ads-indigo-*`
     so no EDL palette variable is ever overwritten. */
  --ads-indigo-50:    #E2E3F2;    /* surface/brand-wash, selected row */
  --ads-indigo-100:   #6567CE;    /* lighter accent */
  --ads-indigo-200:   #5458C9;    /* legacy/header (kept for compat) */
  --ads-indigo-300:   #4045C2;    /* ← BRAND anchor per ADS DS */
  --ads-indigo-400:   #3B3FBA;    /* brand hover */
  --ads-indigo-500:   #363AAB;    /* brand pressed */
  --ads-indigo-600:   #32349B;
  --ads-indigo-700:   #2D2F8C;

  /* Backward-compatible aliases — earlier ADS Preview refinements
     (buttons, cards, inputs, focus rings) still reference `--ads-violet-*`
     names. Re-point them to the new indigo step values so the rules
     keep working without being rewritten. Mapping uses the ADS step
     scale (50–700) so visual hierarchy is preserved:
       violet-05 / violet-10 → indigo-50 (brand-wash)
       violet-15 / violet-20 → indigo-100 (lighter accent)
       violet-30 / violet-40 → indigo-200 (mid)
       violet-50              → indigo-300 (brand)
       violet-60 / violet-70 → indigo-400 (hover)
       violet-80 / violet-90 → indigo-500 (pressed)
       violet-95              → indigo-700 (deepest). */
  --ads-violet-95:    var(--ads-indigo-700);
  --ads-violet-90:    var(--ads-indigo-500);
  --ads-violet-80:    var(--ads-indigo-500);
  --ads-violet-70:    var(--ads-indigo-400);
  --ads-violet-60:    var(--ads-indigo-400);
  --ads-violet-50:    var(--ads-indigo-300);
  --ads-violet-40:    var(--ads-indigo-200);
  --ads-violet-30:    var(--ads-indigo-200);
  --ads-violet-20:    var(--ads-indigo-100);
  --ads-violet-15:    var(--ads-indigo-100);
  --ads-violet-10:    var(--ads-indigo-50);
  --ads-violet-05:    var(--ads-indigo-50);

  /* Semantic greens / reds — Ads DS hue ramps (file 2048:18).
     Per the published library, Red 300 (#AF434E) is the destructive
     anchor and Green 300 (#568E6D) is the success anchor. The 400-step
     of each hue serves as the field-validation text colour
     (red-400 #993B44, green-400 #4C7D57). */
  --ads-red-50:       #F8E0E2;
  --ads-red-300:      #AF434E;    /* destructive surface */
  --ads-red-400:      #993B44;    /* validation/error text */
  --ads-green-50:     #E0EDE5;
  --ads-green-300:    #568E6D;    /* success surface */
  --ads-green-400:    #4C7D57;    /* validation/success text */

  /* Local radius ramp — scoped to ADS Preview.
     Source of truth: the canonical Ads DS Figma library — Form, Input,
     Dropdown, Card and Field components all publish `radius = 6px`
     (e.g. card/size/radius, dropdown/size/default/radius,
     form-layout/size/radius, input/size/default/radius). The pill
     value 100px comes from the Search component (search/size/radius).
     Cards use the same 6px as form controls per the Card spec — we
     keep a 12px `lg` slot reserved for modal/sheet surfaces. */
  --ads-radius-xs:    2px;    /* reserved */
  --ads-radius-sm:    6px;    /* ADS radius — buttons, inputs, menus, cards */
  --ads-radius-md:    6px;    /* alias; same as sm for ADS DS */
  --ads-radius-lg:    12px;   /* modals, sheets */
  --ads-radius-pill:  100px;  /* search, chips */
  --ads-radius-full:  999px;  /* alias */

  /* ADS component border — Figma `color/border/default` for control
     surfaces is `rgba(15,18,20,0.2)` (search, dropdown, input). The
     "bold" 0.5-alpha border is used for focus on neutral controls.
     Both are scoped here so component rules can consume them. */
  --ads-border-component: rgba(15,18,20,0.2);
  --ads-border-bold:      rgba(15,18,20,0.5);
  --ads-surface-recessed: rgba(15,18,20,0.05);

  /* ADS ghost / placeholder text — Figma `search/state/rest/text` is
     `#51585b` (Gray 100); we keep `--ads-text-ghost` as a slightly
     softer fallback for legacy refs but most consumers now point at
     `--text-placeholder` below which reads `#51585b`. */
  --ads-text-ghost:   #51585B;

  /* ─── Remap EDL semantic tokens to ADS values (scoped override only) ─── */
  /* Surfaces */
  --bg-app:            var(--ads-ink-05);
  --bg-surface:        #FFFFFF;
  --bg-surface-raised: #FFFFFF;
  --bg-hover:          var(--ads-ink-10);
  --bg-hover-soft:     var(--ads-ink-05);

  /* Two-region V4 detail-page shell (Add/Edit User, Create/Edit Role —
     Figma node 1023:22021, Dev Mode-inspected). Figma's page canvas
     ("Frame 5" 1:22021's *parent* frame) fills at Gray 10 (`--gray-10`
     #EFF3F5, exact match — verified via the Figma plugin API, not
     eyeballed from the screenshot). The main-content strip is that same
     canvas with an additional `color/black/opacity/5` wash on top
     (Figma variable `color/black/opacity/5`, rgba(15,18,20,0.05)) —
     already codified in this file as `--ads-surface-recessed`. We
     reproduce the exact two-layer structure (canvas + translucent
     overlay) rather than pre-flattening to a single hex, so it stays
     correct if either token's value changes upstream. Cards remain
     `--bg-surface` (#FFFFFF, opaque) on top of both regions. */
  --page-header-surface-bg: var(--gray-10);
  --page-main-surface-bg:   var(--ads-surface-recessed);

  /* Nav — anchored to the canonical Ads DS Navigation component
     (file DJb3yM8aOQjIAbTQ9Cd8Mi, node 796:78 "Navigation / Top Bar").
     The bar surface token is `navigation/topbar/background = #4045C2`,
     i.e. Indigo 300 — the same brand anchor used for surface/brand,
     text/brand, and focus rings. We previously rendered the bar at
     #5458C9 (Indigo 200, sourced from an earlier Global Header file);
     this update aligns the bar with the published Ads DS brand.
     Active tab is conveyed by a 2px white underline + bold white text;
     inactive items use Open Sans Regular at full white. */
  --ads-surface-brand: #4045C2;
  --nav-bg:            var(--ads-surface-brand);
  --nav-link:          #FFFFFF;
  --nav-link-active:   #FFFFFF;
  --nav-divider:       rgba(255,255,255,0.22);

  /* Text — anchored to Ads DS Gray ramp (Figma file 2048:18):
       text/primary   → Gray 600 #1E2528
       text/secondary → Gray 200 #3B4347
       text/muted     → Gray 100 #51585B
     The placeholder/ghost slot reuses Gray 100 #51585B per the
     Search component spec (search/state/rest/text). */
  --text-primary:      #1E2528;
  --text-secondary:    #3B4347;
  --text-muted:        #51585B;
  --text-placeholder:  var(--ads-text-ghost);
  --text-on-brand:     #FFFFFF;

  /* Borders — anchored to the Ads DS table & control specs.
     `table/border/divider = rgba(15,18,20,0.1)` (row dividers),
     `table/border/header = rgba(15,18,20,0.2)` (header underline),
     control borders use `rgba(15,18,20,0.2)`. We keep `--border-input`
     as a dedicated alias so the form-control rules consume the
     component border explicitly. */
  --border-subtle:     rgba(15,18,20,0.1);
  --border-default:    rgba(15,18,20,0.2);
  --border-input:      var(--ads-border-component);

  /* Brand / interactive — anchored to the Ads DS indigo ramp.
     Brand sits at Indigo 300 (#4045C2). Hover steps down one
     step (Indigo 400 #3B3FBA) and pressed steps to Indigo 500
     (#363AAB), preserving the published library's interaction
     gradient. Brand-wash is Indigo 50 (#E2E3F2) — the published
     `surface/brand-wash` token used for selected table rows and
     active nav fills. */
  --ads-brand-hover:   var(--ads-indigo-400);  /* #3B3FBA */
  --ads-brand-pressed: var(--ads-indigo-500);  /* #363AAB */
  --brand:             var(--ads-indigo-300);
  --brand-hover:       var(--ads-brand-hover);
  --brand-text:        var(--ads-indigo-300);
  --brand-text-hover:  var(--ads-brand-hover);
  --brand-bg-soft:     var(--ads-indigo-50);
  --brand-bg-selected: var(--ads-indigo-50);
  --brand-focus-ring:  var(--ads-indigo-300);
  --brand-disabled-bg: rgba(15,18,20,0.05);
  --brand-disabled-fg: rgba(15,18,20,0.3);

  /* Shadows — Ads DS Card and elevation tokens
     (file 1995:21 "Card", elevation/30). The system publishes a
     single shadow colour `color/shadow/default = rgba(15,18,20,0.3)`
     at three elevation depths:
       low    = 0 1px 4px
       medium = 0 4px 12px      (used by dropdown-menu / popover)
       high   = 0 8px 24px + 0 1px 2px
     We map the EDL semantic-shadow tokens onto those depths so
     menus and popovers inherit the right elevation, and reserve the
     drawer slot at the EDL diffusion since the Ads Sheet component
     ships its own elevation. */
  --shadow-menu:   0 4px 12px rgba(15,18,20,0.3);                  /* elevation/30 */
  --shadow-pop:    0 8px 24px rgba(15,18,20,0.3), 0 1px 2px rgba(15,18,20,0.3); /* elevation/high */
  --shadow-tip:    0 1px 4px rgba(15,18,20,0.3);                   /* elevation/low */
  --shadow-drawer: 4px 0 24px rgba(15,18,20,0.18);
  --overlay-scrim: rgba(15,18,20,0.4);
}

/* ─── ADS Preview — targeted component overrides ───
   Mirrors the pattern used for EDL Dark at the top of this file. Only
   scoped under [data-theme="ads-preview"]; no effect on other themes. */

/* Required-asterisk tint — handled centrally in the T6 Field Label
   block below using the Ads DS Field Label required marker token
   (Red 400, #993B44). This stub remains as a comment marker. */

/* User-row avatar backdrop on the lighter ADS canvas. EDL leaves this as
   plain white; under ADS we lift it with a soft violet tint so the portrait
   reads against white rows. Uses the locally-scoped violet-10 alias so no
   shared EDL token is touched. (This targets the table-cell avatar chip,
   not the nav avatar, and not the protected profile dropdown.) */
[data-theme="ads-preview"] .name-avatar { background: var(--ads-violet-10); }

/* Search input icon contrast on ADS light surface */
[data-theme="ads-preview"] .search-ico { color: var(--text-muted); }

/* Scrollbars tuned to the ADS palette */
[data-theme="ads-preview"] ::-webkit-scrollbar { width: 12px; height: 12px; }
[data-theme="ads-preview"] ::-webkit-scrollbar-track { background: var(--bg-app); }
[data-theme="ads-preview"] ::-webkit-scrollbar-thumb {
  background: #C3CFDB;
  border-radius: 6px;
  border: 2px solid var(--bg-app);
}
[data-theme="ads-preview"] ::-webkit-scrollbar-thumb:hover { background: #A5B4C2; }
[data-theme="ads-preview"] * { scrollbar-color: #C3CFDB var(--bg-app); }

/* Combo menus: subtle Gray 40 thumb (overrides global ADS scrollbar weight) */
[data-theme="ads-preview"] .edl-combo-menu {
  scrollbar-color: rgba(158, 176, 189, 0.78) transparent;
}
[data-theme="ads-preview"] .edl-combo-menu::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
[data-theme="ads-preview"] .edl-combo-menu::-webkit-scrollbar-track {
  background: transparent;
}
[data-theme="ads-preview"] .edl-combo-menu::-webkit-scrollbar-thumb {
  background: rgba(158, 176, 189, 0.78);
  border-radius: 999px;
  border: none;
}
[data-theme="ads-preview"] .edl-combo-menu::-webkit-scrollbar-thumb:hover {
  background: var(--gray-50);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview — component shape / state refinements.
   These overrides ONLY fire under [data-theme="ads-preview"] and never
   reach EDL Light or EDL Dark. They target the specific properties that
   cannot be expressed via semantic-token swaps alone: radius, elevation,
   focus ring, and interaction states (hover / pressed / disabled).
   Anatomy, layout, spacing structure, heights, and interactions are
   intentionally untouched so the product still matches what's shipping.
   ═══════════════════════════════════════════════════════════════════════════*/

/* ─── 1. Global focus ring ───
   The EDL rule `:focus-visible { outline: 2px solid var(--indigo-50); }`
   hard-codes EDL's indigo and would otherwise leak into ADS Preview.
   Scope a replacement that uses the ADS violet focus token. */
[data-theme="ads-preview"] :focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
[data-theme="ads-preview"] select:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 0;
}

/* ─── 2. Card / panel surfaces ───
   Anchored to the Ads DS Card component (node 1995:21). Card pins
   `card/size/radius = 6px` and three elevation depths:
     low    = 0 1px 4px  rgba(15,18,20,0.3)
     medium = 0 4px 12px rgba(15,18,20,0.3)
     high   = 0 8px 24px rgba(15,18,20,0.3) + 0 1px 2px rgba(15,18,20,0.3)
   We adopt `low` as the default for `.card` (page-level toolbar panels
   on the User Mgmt page) so the panel reads as a real elevated surface
   rather than the EDL 1px ring. Cards on the Create Role page step up
   to `medium` so the larger surface lifts off more confidently. */
[data-theme="ads-preview"] .card {
  border-radius: var(--ads-radius-md);
  box-shadow: 0 1px 4px rgba(15,18,20,0.3);
  border: none;
}

/* ─── 3. Buttons ───
   Radius 8 → 6px, and add explicit hover / pressed / disabled treatments.
   All properties kept to the theme scope — heights/padding unchanged so
   toolbar rhythm and CTA alignment stay pixel-identical to EDL. */

/* Primary (filled brand) — used by Apply, Add Users, Create Role, etc. */
[data-theme="ads-preview"] .flt-btn-apply,
[data-theme="ads-preview"] .btn-primary,
[data-theme="ads-preview"] button.btn-primary {
  border-radius: var(--ads-radius-sm);
  background: var(--brand);
  color: var(--text-on-brand);
}
[data-theme="ads-preview"] .flt-btn-apply:hover,
[data-theme="ads-preview"] .btn-primary:hover {
  background: var(--brand-hover);
}
[data-theme="ads-preview"] .flt-btn-apply:active,
[data-theme="ads-preview"] .btn-primary:active {
  background: var(--ads-brand-pressed);
}
[data-theme="ads-preview"] .flt-btn-apply:disabled,
[data-theme="ads-preview"] .btn-primary:disabled {
  background: var(--brand-disabled-bg);
  color: var(--brand-disabled-fg);
  cursor: not-allowed;
}

/* Secondary (outline brand) — used by Cancel, + Add Users, + Create Role. */
[data-theme="ads-preview"] .btn-std,
[data-theme="ads-preview"] .flt-btn-cancel {
  border-radius: var(--ads-radius-sm);
  border-color: var(--brand-text);
}
[data-theme="ads-preview"] .btn-std:hover,
[data-theme="ads-preview"] .flt-btn-cancel:hover {
  background: var(--brand-bg-soft);
}
[data-theme="ads-preview"] .btn-std:active,
[data-theme="ads-preview"] .flt-btn-cancel:active {
  background: var(--brand-bg-selected);
}

/* Tertiary / ghost — used by Reset, close, chevrons. */
[data-theme="ads-preview"] .btn-ghost,
[data-theme="ads-preview"] .flt-btn-reset {
  border-radius: var(--ads-radius-sm);
}
[data-theme="ads-preview"] .btn-ghost:hover,
[data-theme="ads-preview"] .flt-btn-reset:hover {
  color: var(--brand-text-hover);
}

/* ─── 4. Inputs / search / dropdowns ───
   Anchored to the Ads DS:
     • Search component (node 37:16) = `search/size/radius = 100px`
       (full pill). Border `rgba(15,18,20,0.2)` at rest, `0.5` at focus.
     • Dropdown / Input components = `radius = 6px`.
   The toolbar search field is the Search component; combo inputs,
   filter inputs, the pagination dropdown and Create Role inputs all
   use the Dropdown/Input 6px radius. When the search/combo is open
   we keep the top corners pill/rounded and the dropdown menu picks
   up the matching radius on its own. */
[data-theme="ads-preview"] .search input {
  border-radius: var(--ads-radius-pill);
}
[data-theme="ads-preview"] .flt-input,
[data-theme="ads-preview"] .edl-combo-input,
[data-theme="ads-preview"] .flt-select,
[data-theme="ads-preview"] .pgn-dd .cr-dd-trigger {
  border-radius: var(--ads-radius-sm);
}
[data-theme="ads-preview"] .search.open input {
  border-radius: 18px 18px 0 0;
}
[data-theme="ads-preview"] .edl-combo.open .edl-combo-input {
  border-radius: var(--ads-radius-sm) var(--ads-radius-sm) 0 0;
}
[data-theme="ads-preview"] .search-dropdown {
  border-radius: 0 0 18px 18px;
}
[data-theme="ads-preview"] .edl-combo-menu {
  border-radius: 0 0 var(--ads-radius-sm) var(--ads-radius-sm);
}

/* Input focus — Ads DS pattern.
   The Dropdown / Input / Combo components use a brand-border focus
   with a soft brand-wash halo. The Search component uses a different
   focus pattern per `search/border/bold = rgba(15,18,20,0.5)` (darker
   neutral, not brand) — Search lives in toolbar contexts where a
   brand ring would compete with adjacent brand CTAs.
   We layer both correctly: inputs/combos/select keep the brand ring;
   search adopts the bold-border pattern. */
[data-theme="ads-preview"] .flt-input:focus,
[data-theme="ads-preview"] .edl-combo-input:focus,
[data-theme="ads-preview"] .flt-select:focus,
[data-theme="ads-preview"] .pgn-dd.open .cr-dd-trigger,
[data-theme="ads-preview"] .pgn-dd .cr-dd-trigger:focus-visible {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-bg-soft);
}
[data-theme="ads-preview"] .search input:focus {
  border-color: var(--ads-border-bold);
  box-shadow: none;
}

/* ─── 5. Menus / popovers / user menu ───
   PROTECTED ZONE: the avatar/profile dropdown menu and anything inside or
   under it is frozen by product decision. Any ADS-Preview refinements to
   .user-menu-pop / .user-menu-sub / .user-menu-row / .user-menu-sub-item /
   .user-menu-hdr / .user-menu-name / .user-menu-sep are intentionally
   absent here. The popup inherits EDL Light shape/shadow/density; only
   the tokens it consumes (--bg-surface, --text-primary, --border-subtle,
   --shadow-menu, --brand-text, --bg-hover) flip to ADS values via the
   semantic-token remap above. That is the extent of ADS Preview's effect
   on this surface and it must not grow. */

/* ─── 6. Tables — Ads DS Data Table treatment ───
   Anchored to the Ads DS Table Row component (node 1727:13223). Spec:
     • header text  : `table/header/text = #51585b`, 13 / 18 Regular
                      (NOT uppercase; the Ads DS header is a label, not
                      a caps utility — this is the single biggest
                      divergence from earlier Pass-3 styling)
     • header pad   : 10y / 12x
     • row body     : 14 / 20 Regular, primary ink
     • cell pad     : 12y / 12x
     • row divider  : `table/border/divider = rgba(15,18,20,0.1)`
     • header rule  : `table/border/header  = rgba(15,18,20,0.2)`
     • row hover    : `table/row/state/hover/background = rgba(15,18,20,0.05)`
     • row selected : `table/row/state/selected/background = #E2E3F2`
                      (Indigo 50, the published brand-wash)
   We avoid changing column widths, resize handles, or sort glyphs so
   the column-resize behaviour and CTA alignment stay pixel-identical
   to EDL Light. */
[data-theme="ads-preview"] .tbl th {
  font-weight: 400;
  color: var(--text-muted);
}
[data-theme="ads-preview"] .tbl th[data-sort]:hover,
[data-theme="ads-preview"] .tbl th[data-rp-sort]:hover,
[data-theme="ads-preview"] .tbl th[data-tm-sort]:hover {
  background: var(--ads-surface-recessed);
  color: var(--text-primary);
}
[data-theme="ads-preview"] .tbl tbody tr {
  border-bottom-color: var(--border-subtle);
  transition: background-color 0.12s ease;
}
[data-theme="ads-preview"] .tbl tbody tr:hover {
  background: var(--ads-surface-recessed);
}
[data-theme="ads-preview"] .tbl tbody tr.is-selected,
[data-theme="ads-preview"] .tbl tbody tr[aria-selected="true"] {
  background: var(--brand-bg-selected);
}

/* ─── 7. Pagination footer ───
   ADS data tables separate the pagination footer from the body with a
   hairline divider. EDL uses a transparent bar on the card surface. */
[data-theme="ads-preview"] .pgn {
  border-top: 1px solid var(--border-subtle);
}

/* ─── 8. Combo-box selected row — stronger ADS tint ───
   EDL uses --brand-bg-soft (05-level) for the selected row which reads
   washed-out under ADS's cooler surface. ADS Dropdown Menu marks the
   selected row with --brand-bg-selected (10-level indigo) for a clearly
   visible state. Weight change already present in EDL base rule. */
[data-theme="ads-preview"] .edl-combo-item.selected {
  background: var(--brand-bg-selected);
  color: var(--brand-text);
}
[data-theme="ads-preview"] .edl-combo-menu--iam-roles .edl-combo-item.selected {
  background: var(--brand-bg-selected);
  color: var(--brand-text);
}

/* ─── 9. Search dropdown / combo-box menu — ADS elevation ───
   EDL renders these as a 1px violet ring + flat pop-shadow. ADS Dropdown
   surface reads as a layered drop shadow with a hairline, so the menu
   floats off the input rather than feeling welded to it. Replace the
   boxed ring with a stacked shadow + radius already handled (section 4
   converts the bottom corners to radius/sm). */
[data-theme="ads-preview"] .search-dropdown,
[data-theme="ads-preview"] .edl-combo-menu {
  border-color: var(--border-subtle);
  border-top-color: var(--border-subtle);
  box-shadow: var(--shadow-menu);
}

/* ─── 10. Tab underline ───
   `.tab-btn.on::after` already consumes var(--brand), so it flips to ADS
   violet automatically. No scoped override required. */

/* ─── 10b. Tooltip — Ads DS Tooltip ───
   Anchored to the canonical Ads DS Tooltip (node 73:234):
     • background: `tooltip/background = #21292d` (Gray 500)
     • radius:     `tooltip/size/container/radius = 6px`
     • padding:    16x / 6y (small), 16x / 16y (large)
     • label:      Open Sans SemiBold 12 / 18 white
     • tip arrow:  8×4 (small) / 12×6 (large)
   The existing `.edl-tooltip` ships at Gray 80 + 8px radius which is
   close but not exact. Scoped overrides bring it to spec without
   touching EDL Light / Dark. Padding stays anatomically unchanged so
   the JS positioning code (caret offsets) keeps working. */
[data-theme="ads-preview"] .edl-tooltip {
  background: #21292D;
  border-radius: var(--ads-radius-md);
  padding: 6px 16px;
  box-shadow: 0 1px 4px rgba(15,18,20,0.3);
}
[data-theme="ads-preview"] .edl-tooltip::after {
  border-top-color: #21292D;
}
[data-theme="ads-preview"] .edl-tooltip.below::after {
  border-bottom-color: #21292D;
}
[data-theme="ads-preview"] .edl-tooltip-line {
  font-family: var(--ff);
  font-size: 12px;
  font-weight: 600;
  line-height: 18px;
}
[data-theme="ads-preview"] .edl-status-tooltip {
  background: #21292D;
  border-radius: var(--ads-radius-md);
  font-family: var(--ff);
  font-size: 12px;
  font-weight: 600;
  line-height: 18px;
  padding: 6px 16px;
  box-shadow: 0 1px 4px rgba(15,18,20,0.3);
}
[data-theme="ads-preview"] .edl-status-tooltip::after {
  background: #21292D;
}

/* ─── 11. Filter drawer — ADS Modal/Drawer surface ───
   EDL uses heavier 700 weight on the drawer title and 8px radius on the
   icon-button close affordance. ADS Modal / Side Panel uses 600/-0.1
   tracking on the title (matches the T24 Alt pattern) and a 6px radius
   on icon buttons (matches our `radius/sm`). Field gap stays at 16 so
   layout rhythm inside the drawer is unchanged. */
[data-theme="ads-preview"] .flt-title {
  font-weight: 600;
  letter-spacing: -0.1px;
}
[data-theme="ads-preview"] .flt-close {
  border-radius: var(--ads-radius-sm);
}

/* ─── 12. Cards on the Create Role page ───
   Anchored to the Ads DS Card component (node 1995:21). Use the
   `card/size/radius = 6px` from the spec (one consistent card radius
   across the system) and step up to the `medium` elevation so the
   page-level cards lift off the surface more confidently than the
   toolbar panel `.card`. The Figma Card publishes 6px radius for
   every elevation variant, so EDL's earlier 12px figure is replaced
   here. Card-on-card density on Create Role is unchanged. */
/* Edit User containers (Basic Information, Roles & Permissions) — Ads DS elevation low.
   Spec: Figma node 1995:18 — 0px 1px 4px 0px rgba(15,18,20,0.3) on a 6px radius white card.
   Matches the .card override above so all primary content cards share one elevation. */
[data-theme="ads-preview"] .cr-card {
  border-radius: var(--ads-radius-md);
  box-shadow: 0 1px 4px rgba(15,18,20,0.3);
  border-color: transparent;
}

/* ─── 13. Create Role inputs / textarea ───
   These are the EDL text-field pair on the Create Role page. Align their
   shape and focus behavior to the ADS Text Field used everywhere else in
   ADS Preview: 6px radius, and the same 2-layer ring + border focus we
   apply to the filter-drawer inputs. Height and width are untouched so
   the form grid stays identical. */
[data-theme="ads-preview"] .cr-input,
[data-theme="ads-preview"] .cr-textarea {
  border-radius: var(--ads-radius-sm);
}
[data-theme="ads-preview"] .cr-input:focus,
[data-theme="ads-preview"] .cr-textarea:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-bg-soft);
}

/* ─── 14. Create Role / Modal primary buttons ───
   `.cr-btn-save` and `.cr-btn-danger-solid` are the two EDL button
   variants that sit outside the `.btn-primary` / `.flt-btn-apply` class
   group and therefore don't receive the button overrides in section 3.
   Re-apply the ADS Button anatomy (6px radius + explicit :active) to
   both so every ADS-Preview CTA reads the same way. Background/height
   stay token-driven. */
[data-theme="ads-preview"] .cr-btn-save,
[data-theme="ads-preview"] .au-btn-save,
[data-theme="ads-preview"] .cr-btn-danger-solid {
  border-radius: var(--ads-radius-sm);
}
[data-theme="ads-preview"] .cr-btn-save:active:not(:disabled),
[data-theme="ads-preview"] .au-btn-save:active:not(:disabled),
[data-theme="ads-preview"] .cr-btn-danger-solid:active {
  background: var(--ads-brand-pressed);
}

/* ─── 15. Confirm / destructive modal surface ───
   `.cr-confirm-dialog` ships with a heavy 0-24-px drop shadow that reads
   as a legacy-EDL modal. ADS Modal uses a softer stacked elevation and
   the brand backdrop scrim. Scope a replacement that matches the ADS
   Card pattern above so filter-drawer, card, and modal share one
   elevation language. Radius is already 12px so no change there. */
[data-theme="ads-preview"] .cr-confirm-backdrop {
  background: var(--overlay-scrim);
}
[data-theme="ads-preview"] .cr-confirm-dialog {
  border-radius: var(--ads-radius-lg);
  box-shadow: var(--shadow-pop);
}

/* ─── 16. Role overflow chip ("+N role") ───
   EDL renders `.role-extra` as a plain underlined link. ADS's equivalent
   overflow affordance in Data Table is a small, inline, neutral chip
   that uses the softer brand tint, not a text link. We keep the anchor
   markup and line-height so the row height stays pixel-identical, but
   under ADS Preview repaint it as a compact inline pill — radius/999,
   soft violet fill, brand text. Hover drops the underline in favor of a
   stronger fill, which is how ADS chips signal interactivity. */
/* `+N role` overflow indicator — Ads DS Chip / Small / Indigo treatment.
   The role-extra anchor is a non-dismissible indicator chip, not a
   filter. We adopt the Ads Chip small-pill anatomy (100px radius,
   SemiBold 12/18 label, 4y/8x padding) and a soft brand-wash fill
   so the affordance reads as "show more brand items" rather than as
   plain link text. */
[data-theme="ads-preview"] .role-extra {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--ads-radius-pill);
  background: var(--brand-bg-soft);
  color: var(--brand-text);
  font-weight: 600;
  font-size: 12px;
  line-height: 18px;
  vertical-align: baseline;
  transition: background-color 0.12s ease, color 0.12s ease;
}
[data-theme="ads-preview"] .role-extra:hover {
  background: var(--brand-bg-selected);
  text-decoration: none;
}

/* ─── 17. Section / page title typography ───
   The product's three H1-class labels — `.cr-title` on the Create Role
   page, `.flt-title` on the filter drawer, and the Users/Roles page
   headings rendered as `.tab-btn.on` — all inherit EDL's 28/32 display
   weight. The ADS "heading/xl" pattern for page titles uses a slightly
   tighter tracking (-0.2px) at 28/36 with weight 600. We've already
   set `.flt-title` to 600/-0.1px in section 12; cascade the same rule
   to `.cr-title` so both page-level titles share a single typographic
   voice under ADS Preview. Size / family / line-height are preserved
   so wrap points and page grid are identical to EDL. */
[data-theme="ads-preview"] .cr-title {
  font-weight: 600;
  letter-spacing: -0.2px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview — Global Navigation Bar rebuild.

   Phase 1 of the "use EDL as scaffold, replace with ADS components" strategy.
   The EDL .nav markup is treated as layout scaffolding; the rules below
   restyle its parts to match the anatomy of the ADS Global Navigation Bar
   component (Figma library id 043d32be…, node 1037:59810).

   All selectors are prefixed with [data-theme="ads-preview"], so nothing
   below affects EDL Light or EDL Dark. Reference: structure audit above
   in the commit message / response — reused: HTML, flex skeleton, dropdown
   JS, sticky/z-index, 48px bar height. Replaced: link anatomy (inner pill),
   active state (submodule chip), hover / pressed / focus, icon hitboxes,
   avatar ring, divider tone.
   ═══════════════════════════════════════════════════════════════════════════*/

/* ──────────────────────────────────────────────────────────────────────
   ADS-Preview-only elements injected into the nav markup.
   These are hidden by default so EDL Light and EDL Dark are unaffected;
   they only become visible under [data-theme="ads-preview"]. */
.ads-nav-search { display: none; }

/* ─── Bar container ───
   Figma Global Header (node 6426:54055) pins the bar at 48px with
   `spacing-07 = 32px` horizontal padding on BOTH sides. EDL's base rule
   already sets height:48px, so we only need to re-override the padding
   (EDL's is `padding-right: 28px`, left indent lives inside `.nav-mod`).
   Result: ADS Preview ends up with the same 48px height as EDL Light —
   no vertical layout shift, no `.cr-page` offset needed, no scroll
   jump when switching themes. */
[data-theme="ads-preview"] .nav {
  height: 48px;
  padding: 0 32px;
}

/* ─── Tool module (logo + optional wordmark + divider) ───
   Figma anatomy (node I6426:54055;6335:25784 "Tool"):
     • `spacing-03 = 8px` gap between logo glyph and wordmark
     • Tool module sits against the bar's left padding (no extra indent)
     • Divider is a 1px × 32px vertical rule, centered between Tool and
       the Primary Nav Tabs row
     • `spacing-06 = 24px` gap from divider to the first nav tab
   EDL buries the logo behind 48px of internal padding and hugs the
   divider; ADS reads more like a thin 1px rule floating in whitespace.
   We zero out `.nav-mod`'s padding (the bar itself now supplies the
   32px), tighten `.nav-logo-group`'s gap to 8px, and keep the divider
   visible with the exact 1×32 proportions. */
[data-theme="ads-preview"] .nav-mod {
  padding: 0;
  gap: 24px;           /* spacing-06 between Tool and Primary Nav Tabs */
  align-items: center;
  height: 100%;
}
[data-theme="ads-preview"] .nav-logo-group {
  gap: 8px;            /* spacing-03 between logo glyph and divider */
  padding-right: 0;
  height: 100%;
  align-items: center;
}
/* Divider removed per Ads DS top bar (Figma 796:78): brand sits flush
   against the spacer with no vertical rule. Hidden only in ADS Preview;
   EDL Light/Dark keep the legacy rule. */
[data-theme="ads-preview"] .nav-divider {
  display: none;
}

/* ─── Bar layout: brand · spacer · centered nav · spacer · utilities ───
   Per Ads DS Top Bar (Figma 796:78): three groups separated by two
   flex-grow spacers so the nav cluster sits in the geometric center of
   the bar and the right-side utilities pin to the right edge.
   We achieve this by overriding the base `.nav-c { margin-right: auto }`
   (which only claims slack on the right for EDL) with `margin: 0 auto`
   so slack distributes evenly on BOTH sides of the cluster. */
[data-theme="ads-preview"] .nav-c {
  margin-left: auto;
  margin-right: auto;
  gap: 4px;              /* spacing-02 between tabs per Figma 795:45 */
}

/* ─── Primary Nav Item — ADS inner-pill anatomy ───
   Figma "Global header items" (node I6426:54055;6335:25815/16/17/18/19)
   is a nested two-layer block:
     • Outer: full bar height, `px-spacing-03 = 8px`, `py-spacing-02 = 4px`,
       `radius-md = 3px`, TRANSPARENT background — an invisible hit target.
     • Inner ("label + icon"): `px-spacing-04 = 12px`, `py-spacing-02 = 4px`,
       `radius-999 = 999px` (full pill), `gap-spacing-02 = 4px`, carrying
       the visible fill when active/hovered.
   Our EDL markup is a single `<a class="nav-a">` node. We collapse the
   Figma two-layer anatomy onto that one element by letting the element
   BE the inner pill and using horizontal margin to produce the outer
   8px gutter. The pill vertically centers at 28px tall inside the 48px
   bar (line-height 20 + py 4×2 = 28).
   Typography per `body/md/medium`:
     • Open Sans SemiBold (weight 500), size 14, line-height 20, tracking 0.
   Rest state is FULL white — Figma does not dim inactive items on the
   brand bar; active is conveyed by the white pill instead. */
[data-theme="ads-preview"] .nav-a {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;       /* spacing-04 horizontal */
  margin: 0 8px;         /* spacing-03 each side → 16px gap between pills */
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: 0;
  color: var(--nav-link);
  background: transparent;
  border-radius: 999px;
  gap: 4px;              /* spacing-02 between label and chevron */
  align-self: center;
  transition: background-color 0.12s ease, color 0.12s ease;
}
/* Hover (non-active): light white-alpha wash. The brand bar is already
   a mid-tone indigo, so a darker overlay reads muddy; a subtle white
   lift matches the ADS state matrix for on-brand surfaces. */
[data-theme="ads-preview"] .nav-a:hover {
  background: rgba(255,255,255,0.14);
  color: var(--nav-link-active);
}
[data-theme="ads-preview"] .nav-a:active {
  background: rgba(255,255,255,0.22);
}

/* Active primary nav item — Ads DS Top Bar Tab.
   Anchored to the canonical Ads DS Navigation / Top Bar (node 796:78):
   the active tab is NOT a white pill — it is full-white SemiBold text
   over the brand bar with a 2px white underline rendered as a tight
   bottom rule. Inactive items use Open Sans Regular at full white.
   This is the single biggest visual change vs the prior pass which
   sourced from the older Global Header file. */
[data-theme="ads-preview"] .nav-a.on {
  background: transparent;
  color: var(--nav-link-active);
  font-weight: 600;
  letter-spacing: 0;
  position: relative;
}
[data-theme="ads-preview"] .nav-a.on::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -8px;            /* aligns underline to the bar's lower edge */
  height: 2px;
  background: #FFFFFF;
  border-radius: 1px;
}
[data-theme="ads-preview"] .nav-a.on:hover {
  background: rgba(255,255,255,0.10);
  color: var(--nav-link-active);
}

/* Chevron — 16×16 per Figma icon frame (node I6426:54055;6335:25817;6350:40158).
   Use pure currentColor so the chevron matches the label's text color
   (inherits brand `#5458C9` on the active pill, white on rest). */
[data-theme="ads-preview"] .nav-chev {
  width: 16px;
  height: 16px;
  opacity: 1;
}

/* Focus ring on links: solid white at 2px so it reads on the brand bar;
   the default ADS violet ring would vanish into the surface. */
[data-theme="ads-preview"] .nav-a:focus-visible,
[data-theme="ads-preview"] .nav-r-btn:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* ─── Bar flow: keep EDL's `space-between`, tune child gaps ───
   Verification source: Figma frame `6335:25782` (Global Header assembled
   example, 1440 viewport) — ABSOLUTE coordinates extracted via
   `get_metadata`:
     • Nav cluster  : x=32,  w=721 (ends at 753)
     • Account      : x=801, w=607 (ends at 1408)
     • Right padding: 1440 − 1408 = 32
     • Gap Nav↔Acct : 801 − 753 = 48
   EDL's default `.nav { justify-content: space-between }` already yields
   an exact 48 px gap at 1440 (1440 − 32 − 32 − 721 − 607 = 48) and lets
   that gap grow naturally on wider viewports. No layout override needed;
   the earlier `flex-start + gap-48 + flex-grow` rewrite was a
   self-invented interpretation that diverged from the verified frame. */
[data-theme="ads-preview"] .nav-r {
  gap: 16px;             /* utilities/gap per Ads DS Top Bar (Figma 795:56) */
  padding-right: 0;
  height: 100%;
  align-items: center;
}

/* Ads DS-only utility icons (bell, three-dot) — render as 20×20 in white per
   Ads DS Top Bar (Figma 795:57 / 795:59). EDL Light/Dark keep their legacy
   `<img src="nav/bell.svg">` bell and have no three-dot icon, so these
   selectors are gated on `[data-theme="ads-preview"]` only.
   `currentColor` on the path lets one rule paint both icons. */
[data-theme="ads-preview"] .nav-r-btn .nav-ico {
  width: 20px;
  height: 20px;
  display: block;
  color: #FFFFFF;
  flex-shrink: 0;
}
[data-theme="ads-preview"] .nav-r-btn-dots {
  display: inline-flex;
}
/* Hide the legacy bell img in ADS Preview so the inline Ads SVG is the
   only glyph rendered inside the notification button. */
[data-theme="ads-preview"] .nav-bell-img {
  display: none;
}

/* Nav Icon container — Pass-6 right-cluster correction.
   Canonical reference is now the Ads DS Top Bar component itself
   (Figma node 795:40 → utilities cluster 795:56), where the icons sit
   as direct 20×20 children inside a 16px-gap row — there is no 48×48
   "Nav Icon container" wrapper in the published component. Our HTML
   needs button elements for hit area, so we keep a wrapper but pull
   it down to 40×40 so the hover/active background reads as a tight
   rounded square around the 20×20 icon instead of as a 48×48 block
   that visually competes with the icon itself. 6px radius matches
   every other ADS surface in this theme (dropdown menu, button,
   card). Avatar trigger gets a circular wrapper override below so
   its hover halo reads as a halo, not a square wash. */
[data-theme="ads-preview"] .nav-r-btn {
  width: 40px;
  height: 40px;
  padding: 0;
  margin: 0;
  border-radius: 6px;
  transition: background-color 0.15s ease;
}

/* Avatar trigger — wrapper hugs the round portrait so hover/focus
   reads as a circular halo, not a 6px rounded square behind a round
   image. The trigger is the *only* `.nav-r-btn` that holds a 32×32
   round image (the bell and three-dot buttons hold 20×20 glyphs);
   this is a one-button override, not a general pattern. */
[data-theme="ads-preview"] #userMenuTrigger.nav-r-btn {
  border-radius: 50%;
}

/* ADS search pill (injected DOM, visible only in ADS Preview).
   Verification source: Figma frame `6335:25782` → instance `6335:28633`
   ("Search bar") inside the Account cluster — absolute coords at 1440 vp:
     • x=0, y=8, width=345, height=32 (y=8 centers the 32 px pill in the
       48 px bar)
   Token values from the SearchBar component spec (node 5859:37219):
     • color/surface/overlay  = #FFFFFF               (fill)
     • color/border/default   = rgba(15,18,20,0.15)   (border — 15% alpha,
                                                       the header-context
                                                       value, NOT the 26%
                                                       of the standalone
                                                       search component)
     • radius/full            = 999px                 (full pill)
     • spacing-03 = 8px (icon gap)
     • spacing-04 = 12px (horizontal padding)
     • placeholder text colour `color/text/ghost = #BEC0C1`
   Non-functional (readonly, tabindex="-1") — this is a preview widget
   of the ADS search component. EDL themes never render it.

   Earlier implementation used `flex: 1 1 0; max-width: 400 px` as a
   "responsive ADS cap"; that was invented. The frame pins the search
   bar to a fixed 345 px width at the 1440 design viewport.

   For viewports narrower than 1440 (the IDE preview pane is ~1185 CSS
   px, typical laptop displays are 1366–1536) ADS has no published
   responsive rule, so we shrink stepwise: at 1440+ match the spec
   exactly (345 px); between 1280 and 1439 use 280 px so the Admin tab
   never overlaps; below 1280 use 200 px — still a usable search
   affordance. The nav layout stays `space-between` so the slack
   redistributes naturally. */
[data-theme="ads-preview"] .ads-nav-search {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  width: 200px;
  height: 32px;
  padding: 0 12px;
  background: #FFFFFF;
  border: 1px solid rgba(15,18,20,0.15);
  border-radius: 999px;
  margin: 0;
  color: #526374;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
@media (min-width: 1280px) {
  [data-theme="ads-preview"] .ads-nav-search { width: 280px; }
}
@media (min-width: 1440px) {
  [data-theme="ads-preview"] .ads-nav-search { width: 345px; }
}
[data-theme="ads-preview"] .ads-nav-search:hover {
  border-color: rgba(15,18,20,0.28);
}
[data-theme="ads-preview"] .ads-nav-search:focus-within {
  border-color: var(--ads-border-bold);
  box-shadow: none;
}
[data-theme="ads-preview"] .ads-nav-search-ico {
  width: 16px;
  height: 16px;
  color: var(--text-muted);  /* Ads DS search/state/rest/text = #51585b */
  flex-shrink: 0;
}
[data-theme="ads-preview"] .ads-nav-search-inp {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;         /* Ads DS search body = 14/20 Regular */
  line-height: 20px;
  color: var(--text-primary);
  padding: 0;
  cursor: text;
}
[data-theme="ads-preview"] .ads-nav-search-inp::placeholder {
  color: var(--text-muted);  /* Ads DS search/state/rest/text = #51585B */
  font-weight: 400;
}

/* Icon-only nav items — ADS uses a subtle white-alpha lift on the brand
   bar rather than the black overlay we tried earlier (that reads EDL). */
[data-theme="ads-preview"] .nav-r-btn:hover {
  background: rgba(255,255,255,0.14);
}
[data-theme="ads-preview"] .nav-r-btn:active {
  background: rgba(255,255,255,0.22);
}

/* Avatar — Pass-6 right-cluster correction.
   The Ads DS Top Bar component (Figma node 795:61, "avatar") publishes
   the profile image at 32×32 round. EDL Light/Dark continue to use the
   base 24×24 (no override leaks across themes), so the cross-theme
   no-recolour/no-replace rule from the prior May 18 nav-correction
   still holds — the only ADS-scoped change is to grow the portrait to
   the published ADS size. `box-shadow: none` keeps the bare portrait
   on the brand bar without inheriting an EDL focus ring or border. */
[data-theme="ads-preview"] .nav-avatar-img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  box-shadow: none;
}

/* (Removed) The previous `.nav-r-btn img { filter: ... }` rule was added to
   normalise the EDL bell PNG to white on the brand bar. In ADS Preview the
   inline Ads bell SVG is now the only bell glyph (the legacy <img> is
   hidden via `.nav-bell-img { display:none }`), and the avatar must not be
   recolored, so no per-img filter is required. */

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview — Pass-2 QA corrections (scoped).
   Identified by the self-audit loop after the Phase-1 nav rebuild:
     • Focus rings on several EDL components still hard-code `var(--indigo-*)`
       as an outline color, which bypasses the semantic-token remap and
       leaves EDL indigo bleeding into ADS Preview. Re-scope each one to
       `var(--brand-focus-ring)` (ADS `color/surface/brand` = #5458C9) so
       focus behaves as a single unified ADS token everywhere.
     • Several display-scale labels (page-level tab title, Create-Role
       section titles, permission-group subtitles) still ship at EDL's
       800 weight — an ADS heading at this size sits at 600/semibold with
       a small tracking adjustment. The saturated brand fill on the
       Create-Role section title also reads as "EDL indigo with ADS
       background" rather than as an ADS section header. Neutralise the
       color (keep the chevron in brand for the interactive affordance)
       and drop the weight to 600.
     • The Create-Role application dropdown (`.cr-dd-*`) and native
       checkboxes (`.cr-check`, `.cr-perm-check`) are still at EDL's
       8 px / 2 px corner scale. ADS form primitives sit at radius/sm
       (3 px) consistently. Pin both to `--ads-radius-sm` and layer the
       same focus "ring + border" pattern used by every other ADS-Preview
       form control.

   PROTECTED ZONE: none of these selectors match the avatar/profile
   dropdown menu (`.user-menu-*`). Those rules remain untouched. */

/* ─── Focus rings ───
   EDL hard-codes `var(--indigo-50)` / `var(--indigo-70)` on these
   selectors. The global `[data-theme="ads-preview"] :focus-visible`
   override has lower specificity than the per-component rules below,
   so we have to restate each one. */
[data-theme="ads-preview"] .rp-role-link:focus-visible,
[data-theme="ads-preview"] .rp-func-text:focus-visible,
[data-theme="ads-preview"] button.rp-func-link:focus-visible,
[data-theme="ads-preview"] .cr-section-header[data-cr-toggle]:focus-visible,
[data-theme="ads-preview"] .cr-section-header[data-au-toggle]:focus-visible,
[data-theme="ads-preview"] .cr-app-section-head:focus-visible,
[data-theme="ads-preview"] .cr-app-remove:focus-visible,
[data-theme="ads-preview"] .cr-customize-link:focus-visible,
[data-theme="ads-preview"] .cr-module-head:focus-visible {
  outline-color: var(--brand-focus-ring);
}
[data-theme="ads-preview"] .cr-check:focus-visible,
[data-theme="ads-preview"] .cr-perm-check:focus-visible {
  outline-color: var(--brand-focus-ring);
}

/* ─── Display typography neutralisation ───
   Drop EDL's 800-weight display on page-level tabs and Create-Role
   section/permission-group headers. ADS headings at 16–18 px sit at
   weight 600 (`heading/sm-semibold`). Also stop painting the Create
   Role section title in saturated brand: ADS uses neutral ink there,
   with the chevron (kept in `--brand-text`, already the case) carrying
   the interactive affordance. Size/line-height are preserved so grid
   wrap points are identical to EDL. */
/* Tab weight handled by the Ads DS Primary Tab rules in section
   P4-1 below (Regular rest, SemiBold active). */
[data-theme="ads-preview"] .cr-section-title {
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.1px;
}
[data-theme="ads-preview"] .cr-perm-group-title {
  font-weight: 600;
  letter-spacing: -0.1px;
}

/* ─── P5b. Checkbox — full ADS Checkbox component alignment ─────────────────
   Anchored to the canonical Ads DS Checkbox (Figma file DJb3yM8aOQjIAbTQ9Cd8Mi,
   node 20:5 / 71:62) and to the table-cell + row-header-cell embedded
   instances (nodes 1728:13164 leading-checkbox, 1730:13277 leading-checkbox).
   Published spec:
     • Box      : 16×16, 1.5px solid rgba(15,18,20,0.2), radius 2px,
                  fill white (rest state)
     • Frame    : 20×20 alignment slot around the box (not a visual element)
     • Padding  : 4px outer wrapper, ~24×24 total click target
     • Checked  : box-fill flips to brand (Indigo 300 = #4045C2),
                  white check glyph drawn at center
     • Indeterminate : same brand fill, single horizontal white bar
     • Disabled : opacity 0.5, no pointer events
     • Tokens   : --checkbox/size/box-radius=2px,
                  --checkbox/box-border=rgba(15,18,20,0.2),
                  --checkbox/box-fill=white,
                  --checkbox/size/padding=4px

   Earlier passes left two violations of this spec:
     1. `.cr-check` / `.cr-perm-check` had `border-radius: var(--ads-radius-sm)`
        (6px). The dropdown/button radius is 6px; the canonical checkbox
        radius is 2px. The two are separate tokens in Figma; we were
        conflating them.
     2. `.rp-check` (the role-assignment / permission-management table
        checkbox) shipped as a raw browser-native input with only
        `accent-color: var(--brand)`. Under ADS Preview that paints the
        platform's gradient checkbox (the macOS/WebKit native look),
        which is the visual that read as "too large" and "floating"
        against the 14/20 row content. The 18×18 width override that
        was supposed to be a hot-fix only amplified the size mismatch
        without addressing the rendering path.

   This block converts all three table+form checkboxes (`.rp-check` for
   tables, `.cr-check` / `.cr-perm-check` for Create-Role / Create-
   Permission-Capability forms) to a single shared `appearance:none`
   pipeline that paints the Figma 16×16 / 1.5px / 2-radius / white
   anatomy with brand fill on checked, brand fill + white bar on
   indeterminate, and an opacity-0.5 disabled state. EDL Light + EDL
   Dark continue to use the base `.cr-check` / `.cr-perm-check` rules
   (16×16 / 2px radius / EDL-indigo fill / EDL focus ring) and the
   base `.rp-check { 16×16 + accent-color }` rule — none of which is
   touched by the selectors below. */
[data-theme="ads-preview"] .rp-check,
[data-theme="ads-preview"] .cr-check,
[data-theme="ads-preview"] .cr-perm-check,
[data-theme="ads-preview"] .pc-page .pc-chk {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 16px;
  height: 16px;
  margin: 0;
  padding: 0;
  border: 1.5px solid var(--ads-border-component);
  border-radius: 2px;
  background: #FFFFFF;
  cursor: pointer;
  flex-shrink: 0;
  position: relative;
  vertical-align: middle;        /* aligns the inline-block control to the
                                    text baseline center inside a 48px row */
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

[data-theme="ads-preview"] .rp-check:hover:not(:checked):not(:indeterminate):not(:disabled),
[data-theme="ads-preview"] .cr-check:hover:not(:checked):not(:indeterminate):not(:disabled),
[data-theme="ads-preview"] .cr-perm-check:hover:not(:checked):not(:indeterminate):not(:disabled),
[data-theme="ads-preview"] .pc-page .pc-chk:hover:not(:checked):not(:indeterminate):not(:disabled) {
  border-color: var(--ads-border-bold);
}

[data-theme="ads-preview"] .rp-check:focus-visible,
[data-theme="ads-preview"] .cr-check:focus-visible,
[data-theme="ads-preview"] .cr-perm-check:focus-visible,
[data-theme="ads-preview"] .pc-page .pc-chk:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}

[data-theme="ads-preview"] .rp-check:checked,
[data-theme="ads-preview"] .cr-check:checked,
[data-theme="ads-preview"] .cr-perm-check:checked,
[data-theme="ads-preview"] .pc-page .pc-chk:checked,
[data-theme="ads-preview"] .rp-check:indeterminate,
[data-theme="ads-preview"] .cr-check:indeterminate,
[data-theme="ads-preview"] .cr-perm-check:indeterminate,
[data-theme="ads-preview"] .pc-page .pc-chk:indeterminate {
  background: var(--brand);
  border-color: var(--brand);
}

/* Checkmark glyph — the SVG is sized to fill the 16×16 box at viewBox
   16 16 with the check anchored from (3.5, 8.2) → (6.6, 11.3) → (12.5,
   5.2). The path matches the EDL base check so the two themes are
   silhouette-identical; only the surrounding box color differs. */
[data-theme="ads-preview"] .rp-check:checked::after,
[data-theme="ads-preview"] .cr-check:checked::after,
[data-theme="ads-preview"] .cr-perm-check:checked::after,
[data-theme="ads-preview"] .pc-page .pc-chk:checked::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'><path d='M3.5 8.2 L6.6 11.3 L12.5 5.2' stroke='%23ffffff' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
}

/* Indeterminate — single 8×1.5 white bar, centered. Reuses the brand
   fill above. Used by `rpSelectAll` / `pmSelectAll` when some-but-not-
   all rows are selected (see app.js: `selAll.indeterminate = on > 0
   && on < total`). In IAM these flags are mutually exclusive
   (`checked = on === total`, `indeterminate = on > 0 && on < total`),
   but we explicitly null `background-image` and `bottom` here so that
   any hypothetical "checked AND indeterminate" state still paints
   only the bar — defensive against future code that toggles both. */
[data-theme="ads-preview"] .rp-check:indeterminate::after,
[data-theme="ads-preview"] .cr-check:indeterminate::after,
[data-theme="ads-preview"] .cr-perm-check:indeterminate::after,
[data-theme="ads-preview"] .pc-page .pc-chk:indeterminate::after {
  content: '';
  position: absolute;
  left: 2.5px;
  right: 2.5px;
  top: 50%;
  bottom: auto;
  height: 1.5px;
  background-color: #FFFFFF;
  background-image: none;
  transform: translateY(-50%);
  border-radius: 1px;
  pointer-events: none;
}

[data-theme="ads-preview"] .rp-check:disabled,
[data-theme="ads-preview"] .cr-check:disabled,
[data-theme="ads-preview"] .cr-perm-check:disabled,
[data-theme="ads-preview"] .pc-page .pc-chk:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Pixel-perfect vertical centering for the leading-checkbox column.
   Inline-block inputs with `vertical-align: middle` align to the cell's
   text line-box mid, not to the cell's geometric center — for a 48px
   body row with a 21px line-box the input lands ~1.75px below center,
   producing the "floating" feel reported in QA. Collapsing the cell's
   line-height to 0 removes the line-box, so `vertical-align: middle`
   computes against the cell's actual height and the checkbox sits on
   the row's geometric centerline. Scoped to ADS Preview so EDL Light
   / EDL Dark retain their existing rendering. The Figma equivalent is
   the Flex `items-center` on the row, which centers geometrically. */
[data-theme="ads-preview"] .tbl th.rp-sel,
[data-theme="ads-preview"] .tbl td.rp-sel,
[data-theme="ads-preview"] .tbl th.pm-sel,
[data-theme="ads-preview"] .tbl td.pm-sel {
  line-height: 0;
}

/* ─── P5c. Users list — leading select-all/row-checkbox column + Export
   toolbar action (Figma 770:17428) ───────────────────────────────────
   Checkbox cell reuses the same `.rp-sel`/`.pm-sel` line-height:0
   vertical-centering trick above (kept below). Horizontal position
   used to be `text-align: center` (this column's only content is the
   checkbox, so centering inside a fixed-width column was an easy way
   to keep every row's checkbox lined up) — Round 34 (2026-08-11,
   toolbar/table horizontal-alignment pass) replaces that with a fixed
   `padding-left` instead, because the checkbox needs to land at a
   predictable x-position rather than merely centered within whatever
   width this column happens to have.
   Round 38 (2026-08-12): the value used to arrive here as a
   `--users-sel-pad-left` custom property written from app.js, computed
   from the "Users" tab label's live x-coordinate. That anchor is gone
   (the toolbar takes its inset from `.tbar`'s own shared padding now,
   not from a tab label), so this column keeps the same 32px it has
   always effectively rendered at — declared here, in the table's own
   shared column rule, instead of being pushed in from a script.
   `align()` mirrors it as `SEL_COL_PAD_LEFT` purely to size the
   colgroup track; header and body cells are both positioned by THIS
   rule, so they can never drift apart.
   Round 39 (2026-08-12): that 32px turned out to BE the card's shared
   content edge all along — every row of the card now derives its inset
   from one `--iam-card-content-inset` property, and this column is
   re-pointed at it in the "ONE shared content inset" block at the end
   of this file. The literal below remains the value for the non-V4
   sheets that also match this selector. */
#usersTable th.c-sel,
#usersTable td.c-sel {
  padding: 0 0 0 32px;
  text-align: left;
  line-height: 0;
}
#usersTable .cr-perm-check.u-row-check,
#usersTable .cr-perm-check.u-select-all {
  margin: 0;
  vertical-align: middle;
}

/* Export + Add User — Figma "Frame 627874" measures a fixed 12px gap
   between the two buttons, as one self-contained right-hand group.
   `.tbar` keeps its base `justify-content: space-between` (two direct
   children: `.tbar-l` and `.tbar-r`), so the toolbar's free space is
   distributed between the two groups exactly like Figma, instead of
   one button's `margin-left: auto` absorbing it — that previous
   approach also double-counted `.tbar`'s own 16px flex `gap` between
   Export and Add User (16px gap + 12px margin = 28px, not the 12px
   Figma actually uses), which is why the pair looked too far apart. */
/* Shared right-actions group for ALL toolbars (Users/Roles/Teams) — a
   single flex row anchoring page-specific secondary actions (Export)
   alongside the primary creation CTA. Using one class (not a per-panel
   rule) guarantees Roles' Create Role and Teams' future primary action
   sit in the exact same right-hand slot/spacing contract as Add User. */
.tbar-r { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

/* Export button — ADS Button component, `ghost` variant, `default`
   size (Figma Dev Mode node 1003:17838). Every value measured on that
   node directly, not approximated from a screenshot:
     • 89×36 total (icon 16 + 4px gap + "Export" label + 12px/8px
       padding-x/y), 6px radius, transparent ("ghost") background.
     • Icon: 16×16 slot, vector inset to 12×12 inside it.
     • Label: Open Sans SemiBold 14px/20px.
     • Rest color (icon + label): `button/variant/ghost/text` #51585b
       — matches this codebase's existing `--iam-ads-text-muted`.
   Deliberately its OWN rule (not `.btn-std`/`.btn-ghost`, which carry
   brand-tinted rest/hover colors tuned for Filter/Add User) so this
   button owns its full ghost-button contract end to end and editing
   it cannot change any other consumer of those shared classes. */
#usersExportBtn.au-export-btn {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 36px;
  padding: 8px 12px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--iam-ads-text-muted, #51585b);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
#usersExportBtn.au-export-btn .au-export-ico {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
}
/* Hover / active (pressed) — ADS ghost buttons gain a neutral wash and
   darken toward the primary-text color; no border or shadow appears
   (kept visually flat, per the ghost variant contract). */
#usersExportBtn.au-export-btn:hover:not(:disabled) {
  background: rgba(15, 18, 20, 0.05);
  color: var(--iam-ads-text, #1e2528);
}
#usersExportBtn.au-export-btn:active:not(:disabled) {
  background: rgba(15, 18, 20, 0.08);
  color: var(--iam-ads-text, #1e2528);
}
#usersExportBtn.au-export-btn:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
/* Disabled — dim only the icon + label color. The button keeps its
   transparent background, border-less shape, 89×36 footprint and
   toolbar position exactly as in the enabled state, so it never
   shifts Add User and is never reduced to a faded rectangle. */
#usersExportBtn.au-export-btn:disabled {
  color: rgba(81, 88, 91, 0.45);
  cursor: not-allowed;
  background: transparent;
}

/* Prototype-only "preparing export" loading state (Select Users → Export
   to Excel simulation). `.is-loading` swaps the static icon for a
   spinning ring in the exact same 16×16 slot — the button's own
   footprint, position, and "Export" label never move, satisfying "no
   layout jump" / "don't move Export or Add User" even while busy. The
   button is also set `disabled` in JS during this state (prevents
   repeated clicks) — icon/label colors below intentionally repeat the
   normal `:disabled` treatment above rather than fading further, so it
   still reads as "busy", not "unavailable". */
#usersExportBtn.au-export-btn .au-export-spinner {
  display: none;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
}
#usersExportBtn.au-export-btn.is-loading {
  color: var(--iam-ads-text-muted, #51585b);
  cursor: default;
}
#usersExportBtn.au-export-btn.is-loading .au-export-ico { display: none; }
#usersExportBtn.au-export-btn.is-loading .au-export-spinner {
  display: block;
  animation: simExportSpin 0.8s linear infinite;
}
@keyframes simExportSpin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  #usersExportBtn.au-export-btn.is-loading .au-export-spinner { animation: none; }
}

/* ─── P5. Dropdown — full ADS Dropdown component alignment ─────────────────
   Anchored to the canonical Ads DS Dropdown component (Figma file
   DJb3yM8aOQjIAbTQ9Cd8Mi, node 36:56). The published spec is a
   FLOATING menu, not a welded popover — trigger and menu are distinct
   surfaces with a small gap and each has its own complete border /
   shadow / radius. The earlier Pass-1 patch only converted radius and
   added a brand focus ring; it kept the EDL "welded" pattern where
   the trigger's bottom corners flatten on Open and the menu inherits
   the trigger's bottom border. Two visual tells survived that pass:
     1. `.cr-dd.open .cr-dd-trigger` flattened its bottom corners,
        which only reads correctly when the menu is glued to the
        field. The ADS pattern keeps the trigger as a stable rounded
        rect through Open.
     2. `.cr-dd-menu.is-layered` inherits `border: 1px var(--brand-text)`
        from the EDL base rule (line ~1819). Under ADS Preview that
        paints the menu with a violet ring — wrong per the ADS
        Dropdown spec, which calls for the same neutral `color/border/
        default` token (`rgba(15,18,20,0.2)`) on every side.

   Spec we now match (Default size; --ads-radius-sm = 6px):
     Trigger
       • bg: white
       • border: 1px `--ads-border-component` on ALL sides (rest)
       • radius: 6px on all 4 corners (rest AND open)
       • padding: 0 12px horizontal (vertical driven by 32px height)
       • text: 14 / 20 Open Sans Regular (typography pass sets `--ff`)
       • chevron: 16×16 inherits 32px-height trigger (Compact density);
                  rotates 180° on Open via the base `.cr-dd.open
                  .cr-dd-chev` rule which we do not touch.
     Open / Focus
       • border-color: var(--brand)
       • halo: 3px var(--brand-bg-soft) (ADS focus pattern)
       • radius: still 6px on all corners (no welding to menu)
     Menu (Figma elevation/30 floating surface)
       • bg: white (inherits)
       • border: 1px `--ads-border-component` on ALL 4 sides
       • radius: 6px on all 4 corners
       • padding: 4px vertical
       • shadow: 0 4px 12px rgba(15,18,20,0.3) (elevation/30 token)
       • gap from trigger: ~4px visible separation
     Options
       • height: auto, min 36px (8y + 20 line + 8y)
       • padding: 8px / 12px
       • text: 14 / 20 primary ink
       • hover bg: var(--ads-surface-recessed)
       • selected bg: var(--brand-bg-selected) (preserved — Figma
         component snapshot does not depict a Selected option but the
         Ads DS Dropdown Menu node uses the same brand-wash for
         Selected, see the `.edl-combo-item.selected` override at
         section 8 which uses the identical token)

   Protection: `.user-menu-pop` / `.user-menu-sub` are NOT in this
   selector list — they are frozen by the section-5 PROTECTED ZONE
   rule. The Search component (`.search input` + `.search-dropdown`)
   and the Combobox (`.edl-combo-input` + `.edl-combo-menu`) follow
   the ADS Search anatomy (welded results panel under a pill input,
   per ADS Search component node 37:16) and are governed by sections
   4 and 9 above — they are intentionally NOT routed through this
   floating-dropdown pattern. */

/* Trigger — rest */
[data-theme="ads-preview"] .cr-dd-trigger {
  border-radius: var(--ads-radius-sm);
  padding: 0 12px;
  line-height: 20px;
  border-color: var(--ads-border-component);
}

/* Trigger — open / focus. Keep ALL 4 corners at 6px (no welding) so
   the trigger reads as a stable rounded rect; the menu floats below
   with its own complete border and shadow. */
[data-theme="ads-preview"] .cr-dd.open .cr-dd-trigger,
[data-theme="ads-preview"] .cr-dd-trigger:focus-visible {
  border-radius: var(--ads-radius-sm);
  border-color: var(--brand);
  border-bottom-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-bg-soft);
  outline: none;
}

/* Menu — both inline and portaled. The base `.cr-dd-menu.is-layered`
   rule (line ~1819) sets `border: 1px var(--brand-text)` plus
   `border-top: 1px var(--border-default)` to weld it to the trigger;
   we restate every side here with the neutral component token AND
   full 6px radius so the violet ring + bottom-only rounding both go
   away. The base `.cr-dd-menu` (non-portaled) has no border at all,
   so the same rules give it its first border under ADS Preview. */
[data-theme="ads-preview"] .cr-dd-menu,
[data-theme="ads-preview"] .cr-dd-menu.is-layered {
  border: 1px solid var(--ads-border-component);
  border-top: 1px solid var(--ads-border-component);
  border-radius: var(--ads-radius-sm);
  padding: 4px 0;
  box-shadow: 0 4px 12px rgba(15, 18, 20, 0.3);
}

/* Layered menu offset — `attachCrDdLayeredMenu` (app.js) sets
   `top: r.bottom - 1` so the menu visually overlaps the trigger's
   bottom border by 1px (the welded seam). Shift it 5px down so the
   gap reads ~4px per Figma, matching the inline-menu offset below. */
[data-theme="ads-preview"] .cr-dd-menu.is-layered {
  margin-top: 5px;
}

/* Non-layered menu — already at `top: calc(100% + 4px)`; keep that
   gap. (No override needed; rule preserved as a comment marker.) */

/* Options — ADS dropdown row density (14/20 with 8y/12x padding) */
[data-theme="ads-preview"] .cr-dd-option {
  height: auto;
  min-height: 36px;
  padding: 8px 12px;
  font-size: 14px;
  line-height: 20px;
}
[data-theme="ads-preview"] .cr-dd-option:hover:not(.is-disabled) {
  background: var(--ads-surface-recessed);
}
[data-theme="ads-preview"] .cr-dd-option.is-selected,
[data-theme="ads-preview"] .cr-dd-option.is-selected:hover {
  background: var(--brand-bg-selected);
  color: var(--text-primary);
}
[data-theme="ads-preview"] .cr-dd-option.is-disabled:hover {
  background: transparent;
}

/* Pagination dropdown — ADS Small size (13/18, 6y/10x). The trigger
   is already constrained to compact width by the base `.pgn-dd`
   rules; only the option density needs tightening here. NOTE: option
   rules are keyed off the menu IDs (not `.pgn-dd .cr-dd-option`)
   because `attachCrDdLayeredMenu` portals the menu to `document.body`
   when open, so the parent `.pgn-dd` ancestor selector no longer
   matches at the option level. */
[data-theme="ads-preview"] .pgn-dd .cr-dd-trigger {
  padding: 0 10px;
  font-size: 13px;
  line-height: 18px;
}
[data-theme="ads-preview"] #usersPageSizeMenu .cr-dd-option,
[data-theme="ads-preview"] #rpPageSizeMenu .cr-dd-option,
[data-theme="ads-preview"] #pmPageSizeMenu .cr-dd-option {
  min-height: 32px;
  padding: 6px 10px;
  font-size: 13px;
  line-height: 18px;
}

/* Combobox option — same ADS dropdown row density. The combo input
   stays welded per ADS Search anatomy (section 9), but the options
   themselves should match the floating-dropdown rhythm so the two
   menu families read consistently inside the same product. */
[data-theme="ads-preview"] .edl-combo-item {
  height: auto;
  min-height: 36px;
  padding: 8px 12px;
  font-size: 14px;
  line-height: 20px;
}
[data-theme="ads-preview"] .edl-combo-item:hover,
[data-theme="ads-preview"] .edl-combo-item.kb-highlight {
  background: var(--ads-surface-recessed);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview — Pass-3 TYPOGRAPHY system replacement.

   Why this block exists:
   The prior passes flipped colours, shapes, elevation, focus, and radius
   to ADS values but left the single biggest EDL tell in place — the
   Disney brand TYPEFACES. EDL's `--ff` resolves to `InspireTWDC`
   (a brand face licensed to Disney+ surfaces) and `.hdr h1` / `.cr-title`
   use `MultiplaneTWDC Display`, another Disney brand face. No amount of
   re-skinning can make a product look like ADS while those two fonts
   render every label on the page. ADS publishes its typography voice as
   Open Sans (body/* tokens in the Figma library reference "Open Sans
   SemiBold", "Open Sans Regular", etc., see node I6426:54055; 6335:25815
   ":root-level body/md/medium").

   Strategy:
   • Flip `--ff` to the Open Sans stack at THIS scope only. EDL Light and
     EDL Dark continue to resolve `--ff` from :root (InspireTWDC) — they
     are byte-identical. Any component that reads `var(--ff)` (body,
     profile dropdown, modals, form controls, etc.) automatically picks
     up Open Sans when the user switches to ADS Preview.
   • Override the two display-face selectors (`.hdr h1`, `.cr-title`) to
     also use `var(--ff)` so MultiplaneTWDC is never drawn under ADS
     Preview. Weight + tracking tuned to ADS heading/xl spec.
   • Add ink-agnostic antialiasing so Open Sans renders crisp on the
     light ADS canvas the way it does in the Figma mocks.
   • Refine role-level typography (page title/subtitle, table headers,
     field labels, chips, pagination, tabs) to match ADS voice: hierarchy
     via weight + tracking + colour, not via heavy 800 EDL weights.

   Protection:
   • No selector below targets `.user-menu-*`. The avatar/profile dropdown
     still receives the `--ff` token flip only (token-level change, the
     same pattern the dropdown already accepts for bg/text/border). Its
     anatomy, spacing, weights, sizes, and colours are otherwise untouched.
   • EDL Light (:root) and EDL Dark ([data-theme="dark"]) are unaffected:
     no token declared there is overwritten, and every selector below is
     prefixed with `[data-theme="ads-preview"]`.
   ═══════════════════════════════════════════════════════════════════════════*/

/* ─── T1. Body typeface override ───
   Single point of entry for the entire app's voice under ADS Preview.
   Keeps the same fallbacks as EDL's --ff so any environment that can't
   load Open Sans (offline dev, CSP blocks) still gets a clean sans. */
[data-theme="ads-preview"] {
  --ff: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
        Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Antialiasing — Open Sans is designed for subpixel AA but the Disney
   faces ship baked for aliased rendering. Switching fonts inside a
   single theme requires restating the smoothing on the ADS Preview
   body so labels, nav, and table text all hit the same renderer path. */
[data-theme="ads-preview"] body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern" 1, "liga" 1;
}

/* ─── T2. Display / page-level titles — Ads DS heading/xl ───
   Anchored to the canonical Ads DS Typography Scale (node 1308:40):
     • heading/xl = 30 / 36 / SemiBold (the published page-title slot)
   `.hdr h1` (User Management) and `.cr-title` (Create Role) are the
   product's page-level titles. Repoint to --ff (now Open Sans) and
   land at 30/36 SemiBold per the Ads DS spec. The earlier pass kept
   the EDL 28px size; that was the only published-typeface tell still
   bleeding through. Tracking stays slightly negative (-0.2) since the
   30px size on Open Sans benefits from a hair of tightening on a
   light canvas. Page grid still aligns because the line-height step
   (32 → 36) lands inside the section's flex padding budget. */
[data-theme="ads-preview"] .hdr h1,
[data-theme="ads-preview"] .cr-title {
  font-family: var(--ff);
  font-size: 30px;
  font-weight: 600;
  line-height: 36px;
  letter-spacing: -0.2px;
}

/* Page subtitle — EDL ships `.hdr p` at weight 500 (medium) in secondary
   ink. Reading against the bolder 600 ADS title, 500 feels competitive
   rather than supporting; ADS supporting copy sits at 400 (regular) and
   uses the muted-ink slot so the hierarchy reads title → subtitle →
   body from dark to light. */
[data-theme="ads-preview"] .hdr p {
  font-weight: 400;
  color: var(--text-muted);
}

/* ─── T3. Tabs — count removed ───
   The "(610 total)" inline count has been moved to the pagination footer
   as "Total users: 610" beside "Go to page". The `.tab-count` span no
   longer exists in the Users tab markup. Rules below are kept for
   compatibility with any other page that might still carry `.tab-count`. */

/* ─── T4. Nav typography ───
   The brand-bar nav link (`.nav-a`) already reads `body/md/medium`
   (14/500/20) from the Pass-1 rebuild and active is 14/700. With --ff
   flipping to Open Sans, the nav voice now matches the Figma Global
   Header by construction — no additional scoped rule needed. Documented
   here so the audit trail is complete. */

/* ─── T5. Table headers — Ads DS Data Table header ───
   Anchored to the Ads DS Table Header Cell (file 105:9): the header
   label is body/normal/sm at `text/secondary` ink — 13 / 18 Regular,
   colour `#51585b`. The canonical system does NOT use uppercase caps
   for table headers; the earlier Pass-3 caps treatment was an EDL
   convention. Drop the caps + tracking, restore Regular weight, and
   keep sort-hover lifting the label into primary ink for a clear
   interactive cue. Row / header height is driven by padding so this
   does not move any column. */
[data-theme="ads-preview"] .tbl th {
  font-size: 13px;
  font-weight: 400;
  line-height: 18px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted);
}
[data-theme="ads-preview"] .tbl th[data-sort]:hover,
[data-theme="ads-preview"] .tbl th[data-rp-sort]:hover,
[data-theme="ads-preview"] .tbl th[data-tm-sort]:hover {
  color: var(--text-primary);
}

/* ─── T6. Form field labels — Ads DS Field Label ───
   Anchored to the canonical Ads DS Field Label component
   (node 896:70). Spec:
     • `field-label/state/default/text = #1E2528` (Gray 600, primary)
     • Open Sans SemiBold (600)
     • size matrix: sm 12/16, md 14/18, lg 18/20
     • required marker `*` uses `#993B44` (Red 400)
   Both `.cr-label` (Create Role) and `.flt-label` (filter drawer)
   are page-level form labels rendering at 14px in EDL, so they map
   to the md slot. The earlier Pass-3 styling at 500/secondary was
   one weight light and one shade muted versus the published Ads DS
   spec. Margin-bottom / block display are preserved so the form
   grid is identical. */
[data-theme="ads-preview"] .cr-label,
[data-theme="ads-preview"] .flt-label {
  font-weight: 600;
  color: var(--text-primary);
}
[data-theme="ads-preview"] .cr-req {
  color: var(--ads-red-400);
}

/* Role-overflow chip (already styled as a pill in section 17) — match
   the same font-weight so both chip families share one label voice. */
[data-theme="ads-preview"] .role-extra {
  font-weight: 600;
}

/* "+1 role" mini-pill rendered in table cells */
[data-theme="ads-preview"] .role-extra,
[data-theme="ads-preview"] .role-more {
  letter-spacing: 0.1px;
}

/* ─── T8. Pagination footer labels ───
   `.pgn-lbl` currently paints at `12/primary`. The surrounding page
   area is light canvas and the utility role is supporting metadata;
   ADS treats footer utility labels as muted 12/500. Drop to muted ink
   and keep 12 so the Show/Page-of controls don't fight the table body. */
[data-theme="ads-preview"] .pgn-lbl {
  font-weight: 500;
  color: var(--text-muted);
}

/* ─── T9. Permission / access group titles inside Create Role ───
   `.cr-perm-group-title` was bumped to 600 in Pass 2. Cascade the same
   tracking (-0.1 px) so its voice matches `.cr-section-title` and the
   filter-drawer title. */
[data-theme="ads-preview"] .cr-perm-group-title {
  letter-spacing: -0.1px;
}

/* ─── T10. Button labels — tighten for Open Sans rendering ───
   Open Sans at 14 px on the ADS indigo brand fill benefits from a
   touch of positive tracking (0.1 px) to avoid letter-collision in
   short CTA labels ("Apply", "Save"). Weight stays 500. Applied to
   every primary / secondary / tertiary button variant so button voice
   is unified under ADS Preview. */
[data-theme="ads-preview"] .btn-primary,
[data-theme="ads-preview"] .btn-std,
[data-theme="ads-preview"] .btn-ghost,
[data-theme="ads-preview"] .flt-btn-apply,
[data-theme="ads-preview"] .flt-btn-cancel,
[data-theme="ads-preview"] .flt-btn-reset,
[data-theme="ads-preview"] .cr-btn-save,
[data-theme="ads-preview"] .cr-btn-danger-solid,
[data-theme="ads-preview"] #crCancel.btn-std,
[data-theme="ads-preview"] #crConfirmCancel.btn-std,
[data-theme="ads-preview"] #auInactiveConfirmCancel.btn-std,
[data-theme="ads-preview"] #auRemoveUserCancel.btn-std {
  font-family: var(--ff);
  letter-spacing: 0.1px;
}

/* ─── T11. Input / search / textarea / select text voice ───
   Redundant re-statements of `font-family: var(--ff)` for every form
   control that had its own explicit declaration in the EDL base (which
   pinned it to InspireTWDC). Without this, those selectors win on
   specificity and keep rendering the Disney brand body font even
   though the rest of the app has switched. */
[data-theme="ads-preview"] .search input,
[data-theme="ads-preview"] .flt-input,
[data-theme="ads-preview"] .flt-select,
[data-theme="ads-preview"] .edl-combo-input,
[data-theme="ads-preview"] .cr-input,
[data-theme="ads-preview"] .cr-textarea,
[data-theme="ads-preview"] .pgn-dd .cr-dd-trigger,
[data-theme="ads-preview"] input,
[data-theme="ads-preview"] select,
[data-theme="ads-preview"] textarea,
[data-theme="ads-preview"] button {
  font-family: var(--ff);
}

/* Placeholder weight — ADS placeholder is regular (not medium) so the
   ghost ink reads soft, not competitive with the typed value. */
[data-theme="ads-preview"] .search input::placeholder,
[data-theme="ads-preview"] .flt-input::placeholder,
[data-theme="ads-preview"] .edl-combo-input::placeholder,
[data-theme="ads-preview"] .cr-input::placeholder,
[data-theme="ads-preview"] .cr-textarea::placeholder {
  font-weight: 400;
  color: var(--text-placeholder);
}

/* ─── T12. Table cell primary text + role link ───
   Row text is 14/primary; role links paint `--brand-text`. Under Open
   Sans the role-link weight wants a nudge to 500 so the link reads as
   an affordance rather than just coloured body text. Underline already
   paints on hover. */
[data-theme="ads-preview"] .rp-role-link {
  font-weight: 500;
}

/* ─── T13. Empty-state text inside tables ───
   Keep the copy size but bump tracking so Open Sans doesn't read too
   tight when no rows are rendered. */
[data-theme="ads-preview"] .tbl td.empty-state {
  letter-spacing: 0.1px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview — Pass-4 PAGE-LEVEL visual alignment (User Management page).
   Scope: User tab + Roles & Permissions tab only. Page-level selectors
   (`.tabs-row`, `.tab-btn`, `.tbar .btn-ghost`, `.search-ico`, `.tbl td`,
   `.name-cell`, `.name-avatar`, `button.rp-func-count`, `.pg-n`) are only
   rendered on this page, so every rule below naturally confines itself
   to the two target tabs without affecting the Create Role page or the
   protected avatar dropdown.

   Strategy: the prior passes (P1 component shape, P2 states, P3 typography)
   already tokenised colour, shape, elevation, focus, and type. What still
   read as EDL were the four remaining anatomical tells that a design-
   system-level recolour cannot fix:
     1. Tab strip (too big, too bold, count competes with label).
     2. The primary page CTA rendered as a text link rather than a Button.
     3. Search magnifier pinned to the right of the input.
     4. Table rows at 64px with 48×48 avatars — marketing density, not
        ADS Data Table density.
     5. R&P function counts rendered as `(8)` inline text instead of a
        count pill — the hallmark of an EDL table.
     6. Pagination current-page marked by a 2px underline tick instead of
        a filled Button / Pagination chip.

   EDL Light + EDL Dark + the avatar dropdown are not referenced below.
   ═══════════════════════════════════════════════════════════════════════════*/

/* ─── P4-1. Tabs strip — Ads DS Primary Tab ───
   Anchored to the canonical Ads DS Primary Tab (node 57:56). Spec:
     • Default size: 18 / 24 Regular rest, 18 / 24 SemiBold active
     • State colors: rest `#51585B`, hover `#3B4347`, active `#4045C2`
     • Padding: 8y / 16x with a 3px-tall active underline at the bottom
   The earlier Pass-4 styling compressed tabs to 16/600 with negative
   tracking. The published Ads DS expects the larger 18px body so the
   tab strip still reads as page-level navigation rather than a section
   header. Strip height is driven by typography + padding so the row
   doesn't shift when toggling themes. Rest-state colour is handled by
   the `--text-muted` token. Active text colour is brand by token. */
[data-theme="ads-preview"] .tab-btn {
  font-size: 18px;
  font-weight: 400;
  line-height: 24px;
  letter-spacing: 0;
  padding-bottom: 8px;
  color: var(--text-muted);
}
[data-theme="ads-preview"] .tab-btn:hover {
  color: var(--text-secondary);
}
[data-theme="ads-preview"] .tab-btn.on {
  font-weight: 600;
  color: var(--brand-text);
}
[data-theme="ads-preview"] .tab-btn.on::after {
  height: 3px;
  bottom: -1px;
  border-radius: 2px 2px 0 0;
}

/* ─── P4-2. Tab count — removed from tab label ───
   The "(610 total)" count has been removed from the Users tab label and
   moved to the pagination footer. The `.tab-count` selector below is
   retained for forward-compatibility but no longer matches the IAM tab. */
[data-theme="ads-preview"] .tab-btn .tab-count {
  font-weight: 400;
  color: var(--text-muted);
  margin-left: 4px;
}
[data-theme="ads-preview"] .tab-btn.on .tab-count {
  color: var(--text-secondary);
}

/* ─── P4-3. Toolbar primary CTA — filled Button, not a text link ───
   "+ Add Users" / "+ Create Role" ship as `.btn-ghost` (transparent,
   brand-text, no chrome). Under EDL that matches the original visual
   contract. Under ADS the primary action on a Data Table toolbar is a
   filled Button (see ADS Button / Primary), so we promote the same
   anchor-style markup to a filled button while keeping the DOM, height
   and gap identical so the toolbar rhythm does not shift. Scoped via
   `.tbar .btn-ghost` so any other `.btn-ghost` use (none on this
   page today — but the Reset/Close affordances on filter panels use a
   different class already) is not swept up. */
[data-theme="ads-preview"] .tbar .btn-ghost {
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ads-radius-sm);
  background: var(--brand);
  color: var(--text-on-brand);
  font-weight: 500;
  letter-spacing: 0.1px;
  transition: background-color 0.15s ease;
}
[data-theme="ads-preview"] .tbar .btn-ghost:hover {
  background: var(--brand-hover);
  color: var(--text-on-brand);
}
[data-theme="ads-preview"] .tbar .btn-ghost:active {
  background: var(--ads-brand-pressed);
  color: var(--text-on-brand);
}
[data-theme="ads-preview"] .tbar .btn-ghost:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}

/* ─── P4-4. Search field — magnifier on the LEFT ───
   EDL anchors the magnifier on the right (`.search-ico { right: 10px }`)
   which was an EDL utility-input convention. ADS Search Field puts the
   icon on the leading edge, before the placeholder text. Flip the icon
   to `left: 12px` and swap the input padding so the placeholder starts
   to the right of the icon. The clear-X affordance stays on the right
   (already attached with `right: 8px`) so the trailing side reads as
   the action rail. */
[data-theme="ads-preview"] .search-ico {
  left: 12px;
  right: auto;
}
[data-theme="ads-preview"] .search input {
  padding: 0 32px 0 36px;
}

/* ─── P4-5. Data Table row density (User tab) ───
   Anchored to Figma 770:17443 (ADS Data Table reference).
   Frame geometry for the Name cell:
     • Cell width 296, avatar 40×40 anchored at cell-relative x=0
     • Text block "Frame 2134099142" starts at cell-relative x=56
       (Order Name frame x=48 + inner text-block x=8)
     • Visual gap avatar→text   = 56 − 40 = 16px
     • Avatar offset from row L = 32 (matches v2 base .name-cell pad-left)
   Text block internals:
     • Name (21 line-height, y=0)
     • Email (16 line-height, y=25) → 4px visual gap between them
     • Block total height 41px → fits 48px row with 3.5px top/bottom
   Row + avatar dimensions match Figma exactly: 48px row, 40px avatar
   (Ellipse 493). Earlier ADS-specific compaction (gap:12, pad:20) was
   tighter than this Figma node specifies, so we restore Figma values. */
[data-theme="ads-preview"] .tbl td {
  height: 48px;
}
[data-theme="ads-preview"] .name-cell {
  height: 48px;
  gap: 16px;
  padding: 0 0 0 32px;
}
[data-theme="ads-preview"] .name-cell-text {
  gap: 4px;
}
[data-theme="ads-preview"] .name-avatar {
  width: 40px;
  height: 40px;
}

/* ─── P4-6. R&P function semantic access links (ADS preview) ─── */
[data-theme="ads-preview"] .rp-func-app {
  color: var(--text-primary);
}
[data-theme="ads-preview"] button.rp-func-link .rp-func-access {
  color: var(--brand-text);
}
[data-theme="ads-preview"] button.rp-func-link:hover .rp-func-access {
  color: var(--brand-text-hover);
  text-decoration: underline;
}

/* ─── P4-7. Pagination current page — ADS Button-style pill ───
   EDL marks the active page with a 2px brand-coloured tick under the
   number. ADS Pagination marks current page with a filled chip that
   reads as a toggled Button. Preserve the 24×24 tap-target footprint
   so navigation keyboard-arrow behaviour and hover-hit regions stay
   unchanged; just repaint. Inactive numbers keep their hover tint. */
[data-theme="ads-preview"] .pg-n.on {
  background: var(--brand);
  color: var(--text-on-brand);
  border-radius: var(--ads-radius-sm);
  font-weight: 600;
}
[data-theme="ads-preview"] .pg-n.on::after {
  display: none;
}
[data-theme="ads-preview"] .pg-n:hover:not(.on) {
  background: var(--brand-bg-soft);
  color: var(--brand-text);
}

/* ─── P4-8. Table header height ───
   v2 base is already 32px (Figma Data Table / Example Row Header height).
   The earlier 44px override was written against 1.0's 48px base to
   reduce it. With v2 base at 32px the override is redundant; setting
   it explicitly to 32px makes the intent clear and ensures the header
   never drifts if the base ever changes. */
[data-theme="ads-preview"] .tbl th {
  height: 32px;
}

/* ─── P4-9. Role Assignment column proportions (Figma 770:19301) ───
   The Figma RA frame (1343 wide) lays out columns at:
     • Checkbox slot + leading gutter : 60px  (x=0  → x=60)
     • Role          : 216px           (x=60 → x=276)
     • Functions     : 752px           (x=276→ x=1028)
     • Created By    : 176px           (x=1028→x=1204)
     • Create Date   : 144px           (x=1204→x=1348)
   Re-expressed as percentages of the four content columns (1283px
   after the 60px lead), normalized to 100% so the colgroup adds up:
     Role 16.84  | Functions 58.61  | Created By 13.72  | Create Date 10.83
   We round to two decimals to absorb pixel rounding without drift.
   Scoped to [data-theme="ads-preview"] #rolesPanel so:
     • EDL Light/Dark in v2 keep their original proportions.
     • Theme 1.0 is unaffected (rule does not appear in public/).
     • Users tab is unaffected (no .rp-col selectors on Users table).
   alignRP() still pins the Create Date right edge to the Create Role
   CTA at runtime — these widths just set the proportional starting
   point so the table reads closer to Figma before/after JS snap.
   Spec: same data, better outfit. The Cursor RA content (Atlas Admin,
   Core Planning Admin, Operations Admin, Planner, Planning Specialist,
   Planning Manager, Campaign Planner, Ad Operations Specialist,
   Read-Only Viewer, ICM Admin, with real Functions/Created By/Create
   Date) is preserved — only column widths shift. */
[data-theme="ads-preview"] #rpColgroup col[data-rp-col="role"] { width: 16.84%; }
[data-theme="ads-preview"] #rpColgroup col[data-rp-col="func"] { width: 58.61%; }
[data-theme="ads-preview"] #rpColgroup col[data-rp-col="by"]   { width: 13.72%; }
[data-theme="ads-preview"] #rpColgroup col[data-rp-col="date"] { width: 10.83%; }

/* ─── P4-10. Role Assignment pagination row height (Figma 770:19612) ───
   Figma RA pagination band is 48px tall (frame 770:19612 h=48). The
   current v2 base renders at 40px — 8px short, which makes the band
   feel cramped relative to the 48px toolbar above it and the 48px
   data rows. Bumping the band to 48px restores the consistent vertical
   rhythm Figma calls for. Scoped to #rolesPanel so the Users tab
   pagination stays at its current value; if/when the Users tab calls
   for the same lift, that will be a separate intentional change. */
[data-theme="ads-preview"] #rolesPanel .pgn {
  min-height: 48px;
}

/* ─── P4-11. Role Assignment checkbox glyph size (Figma 770:19301) ───
   Superseded by Pass-5b "Checkbox — full ADS Checkbox component
   alignment" above. The earlier 18×18 figure came from the
   Figma 770:19301 product frame (which is a styled tile inside the
   IAM role-assignment design); the canonical ADS Checkbox component
   (node 20:5 / 71:62) pins the visible box at 16×16 with a 1.5px
   stroke (Pass-5b restates the full anatomy). The 44px column width
   in `.rp-tbl col.rp-col-sel` is unchanged — the 16×16 control sits
   centered in the same slot. */

/* ─── P4-12. Permission Management column proportions (Figma 770:20039) ───
   The PM Figma frame (1343 wide) lays out the 6 columns from x=0:
     • Checkbox slot + leading gutter : 60px  (x=0 → x=60)
     • Function Name : 320px           (x=60  → x=380)
     • Description   : 320px           (x=380 → x=700)
     • Type          : 180px           (x=700 → x=880, holds 1 chip)
     • Used in       : 180px           (x=880 → x=1060)
     • Last Updated  : 144px           (x=1060→ x=1204)
   Re-expressed as percentages of the 5 content columns (1144px after
   the 60px lead), normalized to 100%:
     Name 27.97 | Desc 27.97 | Type 15.73 | Used 15.73 | Date 12.59
   PM-only selectors (no theme scoping) so the proportions apply across
   EDL Light, EDL Dark, and ADS Preview — column widths are layout, not
   styling. Other panels (Users, Role assignment) are untouched because
   they use different colgroup IDs (#usersColgroup, #rpColgroup). */
#pmColgroup col[data-pm-col="name"] { width: 27.97%; }
#pmColgroup col[data-pm-col="desc"] { width: 27.97%; }
#pmColgroup col[data-pm-col="type"] { width: 15.73%; }
#pmColgroup col[data-pm-col="used"] { width: 15.73%; }
#pmColgroup col[data-pm-col="date"] { width: 12.59%; }

/* ─── P4-13. Permission Management pagination height (Figma 770:20352) ───
   PM Figma pagination band frame is 48px tall (Frame 770:20352 h=48),
   matching the RA pagination band. v2 base ships .pgn at 40px which
   reads cramped against the 48px row rhythm above. Bump to 48px,
   scoped to #permsPanel so other panels aren't pulled into PM's
   rhythm changes (RA's bump is in P4-10, also #rolesPanel-scoped). */
[data-theme="ads-preview"] #permsPanel .pgn {
  min-height: 48px;
}

/* ─── P4-14. Permission Management Type column chips (Figma 770:20039) ───
   The Figma Type column renders each value inside a chip (Cell Chip
   component). Per the design system the Type column only supports
   two variants:
     • Default — light neutral background, subtle border, brand-text.
                 Used for system-shipped permissions (majority of rows).
     • Custom  — brand-tint background, brand border, brand-text.
                 Used for customer-authored / re-scoped permissions.
   No other type chips exist on this surface.

   Chip dimensions (from Figma chip frame y=12 inside 48px cell):
     • height 24px, vertically centered (12px breathing top/bottom)
     • horizontal padding 10px (Figma text x=10 inside chip)
     • border-radius full pill (12px)
     • font 12px / 18px / 500 weight (Figma chip text spec)
     • 1px solid border (color follows variant)

   Scoped to .pm-tbl so chips only appear on the Permission Management
   table; RA and Users tables are not affected. Theme-agnostic on chip
   structure; tokens resolve to theme-appropriate colors per existing
   var() chains. */
.pm-chip {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: 12px;
  font-size: 12px;
  line-height: 18px;
  font-weight: 500;
  white-space: nowrap;
  border: 1px solid transparent;
  box-sizing: border-box;
}
/* Default — system-shipped permission. Near-white surface with a
   subtle border, brand text. Reads as "neutral / standard" so admins
   recognise it as the platform's baseline. */
.pm-chip--default {
  background: var(--bg-surface);
  color: var(--brand-text);
  border-color: var(--border-input);
}
/* Custom — customer-scoped or customer-authored. Light brand-purple
   wash (Indigo 05 / brand-bg-soft) with a brand border, brand text.
   Visually warmer than Default so the eye picks out the few Custom
   rows in a long catalog. */
.pm-chip--custom {
  background: var(--brand-bg-soft);
  color: var(--brand-text);
  border-color: var(--brand-bg-soft);
}

/* Base .tbl td already sets vertical-align: middle and the chip is
   inline-flex with align-items: center, so the chip centers naturally
   inside the 48px row without extra cell padding. The pm-type cell
   inherits cell padding from .tbl th, .tbl td { padding: 0 8px }. */

/* ─── P4-15. Permission Management metadata colors (Figma 770:20039) ───
   Used In and Last Updated columns are read as supporting metadata in
   the Figma node — neither black nor muted gray, but EDL Gray 95
   (#171C20). Gray 95 sits just below pure black, giving the metadata
   enough weight to be legible while remaining secondary to the
   Function Name link. Applied at the cell selector so chip-text inside
   pm-type is not affected; .pm-name keeps the brand-link color. */
.pm-tbl td.pm-used,
.pm-tbl td.pm-date {
  color: var(--gray-95);
}

/* ─── P4-16. Permission Capability detail page (Figma 788:4348) ───
   Opens when a user clicks a permission function name on the
   Permission Management tab. The page chrome (.cr-page shell, .cr-back,
   .cr-header, .cr-card, .cr-section-header) is fully reused from
   #createRolePage / #addUsersPage — only the body-level pieces unique
   to this page are introduced here under the .pc- prefix:

     • .pc-basic-grid — 3-column field grid (296/296/296 per Figma)
       with Description spanning two columns on the second row and a
       compact metadata cell (Status + Last Updated) in the third.
     • .pc-status — green check + "Active" pill-style metadata block.
     • .pc-meta-value — compact secondary-color label/value rendering.
     • .pc-options-toolbar — Default Access + Add permission + Add CTA
       row at the top of the Permission Options card.
     • .pc-grp-card — one collapsible group card per option group
       (Order, Media Plans, etc. in Figma; Roles, Users, Analytics etc.
       in our real data). Re-uses brand chevron + a trash-affordance
       Delete link on the right.
     • .pc-chk-row — flex row of checkboxes, 80px-wide slots so 8
       actions fit on a single row before wrapping.

   Scoped to .pc-page so nothing here leaks to other detail pages. */

.pc-page .pc-basic-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  column-gap: 24px;
  row-gap: 16px;
  padding-top: 4px;
}
.pc-page .pc-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.pc-page .pc-field .cr-input { width: 100%; }
.pc-page .pc-field-name    { grid-column: 1 / 2; grid-row: 1 / 2; }
.pc-page .pc-field-app     { grid-column: 2 / 3; grid-row: 1 / 2; }
.pc-page .pc-field-created { grid-column: 3 / 4; grid-row: 1 / 2; }
.pc-page .pc-field-desc    { grid-column: 1 / 3; grid-row: 2 / 3; }
.pc-page .pc-field-meta    { grid-column: 3 / 4; grid-row: 2 / 3; display: flex; flex-direction: row; gap: 32px; align-items: flex-start; }
.pc-page .pc-meta-cell     { display: flex; flex-direction: column; gap: 6px; min-width: 0; }

/* Status pill — green Check Circle + "Active". Matches the Figma
   compact metadata treatment (Status column on PM detail). */
.pc-page .pc-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 32px;            /* match cr-input height so meta row baselines align */
  padding: 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-primary);
}
.pc-page .pc-status-label { font-weight: 400; }
.pc-page .pc-meta-value {
  display: inline-flex;
  align-items: center;
  height: 32px;
  font-size: 14px;
  line-height: 20px;
  color: var(--gray-95);   /* matches the PM table Last Updated tone (P4-15) */
}

/* Permission Options card body */
.pc-page .pc-section-help {
  font-size: 14px;
  line-height: 20px;
  color: var(--text-secondary);
  margin: 0 0 16px 0;
}
/* Toolbar layout: two 283px field columns + a natural-width Add button
   slot. Using `max-content` for the button column instead of `auto`
   prevents the button from stretching across leftover row width — the
   button reads as a compact toolbar action sitting next to the
   dropdown, not a primary page CTA. */
.pc-page .pc-options-toolbar {
  display: grid;
  grid-template-columns: 283px 283px max-content;
  column-gap: 16px;
  align-items: end;
  margin-bottom: 24px;
}
/* The shared .cr-btn-add (used by Create Role) is natural-width
   already; this rule just nails it to the bottom of the toolbar grid
   row so it baseline-aligns with the dropdown triggers (32px tall). */
.pc-page .pc-options-toolbar .cr-btn-add {
  align-self: end;
  height: 32px;
  margin-bottom: 0;
}

/* Disabled-input styling for Created By + Default Access level. Native
   :disabled gets a clearly muted treatment (gray surface, secondary
   text) so the read-only metadata cannot be confused with an editable
   input. The native cursor and pointer-events: none ensure it doesn't
   participate as a click target either. Scoped to .pc-page so other
   inputs that may use :disabled in confirm dialogs etc. are unaffected. */
.pc-page .cr-input:disabled,
.pc-page input.pc-input-disabled {
  background: var(--gray-10, #F3F4F4);
  color: var(--text-secondary);
  border-color: var(--border-default);
  cursor: not-allowed;
  -webkit-text-fill-color: var(--text-secondary); /* Safari override */
  opacity: 1;                                     /* override UA dim */
}

/* The Choose Application + Add Permission Group dropdowns sit inside
   .pc-field — give them 100% width so they expand to the field column
   (283px) like other .cr-dd uses on Create Role. Default .cr-dd ships
   with width: 283px which already matches, but inside flex-column
   .pc-field we want it inherit the field's column width for safety. */
.pc-page .pc-dd { width: 100%; max-width: 283px; }
.pc-page .pc-dd .cr-dd-trigger { width: 100%; }

/* Group cards */
.pc-page .pc-groups { display: flex; flex-direction: column; gap: 16px; }
.pc-page .pc-grp-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: 12px;
  padding: 12px 24px 16px;
}
.pc-page .pc-grp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0 12px 0;
}
.pc-page .pc-grp-header-left {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--brand-text);
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
}
.pc-page .pc-grp-chev {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--brand-text);
  transition: transform 0.15s ease;
}
.pc-page .pc-grp-card.collapsed .pc-grp-chev { transform: rotate(-90deg); }
.pc-page .pc-grp-card.collapsed .pc-chk-row { display: none; }

.pc-page .pc-grp-delete {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  padding: 4px 0;
  color: var(--brand-text);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  cursor: pointer;
}
.pc-page .pc-grp-delete:hover { color: var(--brand-text-hover, var(--brand-text)); }
.pc-page .pc-grp-delete svg { flex-shrink: 0; }

.pc-page .pc-chk-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  padding-top: 4px;
}
.pc-page .pc-chk-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 80px;          /* Figma checkbox slot = 80px */
  font-size: 14px;
  line-height: 20px;
  color: var(--text-primary);
  cursor: pointer;
  user-select: none;
}
.pc-page .pc-chk {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--brand-text);
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ADS Preview — P6. Audit polish pass (May 22, 2026).
   Resolves a small set of "close but inconsistent" findings from a full
   ADS/Yeti component audit across the IAM v2 prototype. The audit walked
   the 12 component families called out in the design-system reference
   (Navbar, Table, Checkbox, Dropdown, Toggle, Buttons, Search, Filter,
   Tabs, Pagination, Chips, Tooltip) and confirmed that prior passes
   (Pass-3 Buttons, Pass-4 Inputs, Pass-5 Dropdown, Pass-5b Checkbox,
   Pass-6 Navbar, P4-1 Tabs, P4-7/10/13 Pagination, P4-14 Chips, 10b
   Tooltip, etc.) have already aligned the bulk of the surface area.
   This block addresses the three remaining Medium findings.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── P6-M1. Segmented control radius — `.seg-ctrl` (Internal/External) ──
   Base ships with `border-radius: 8px` (EDL Light convention). Every
   other ADS Preview form primitive — input, dropdown, button, filter,
   pagination pill — has been pinned to `--ads-radius-sm` (6px). Pin
   the segmented control container the same way so the toolbar reads
   as a single coherent radius family. EDL Light keeps its 8px. */
[data-theme="ads-preview"] .seg-ctrl {
  border-radius: var(--ads-radius-sm);
}

/* ─── P6-M2. Dialog cancel-button radii — ID-scoped `.btn-std` instances ──
   Pass-3 pins `[data-theme="ads-preview"] .btn-std { border-radius:
   var(--ads-radius-sm) }`, but several modal-footer Cancel buttons
   declare an ID-scoped 8px radius (e.g. `#crCancel.btn-std`,
   `#crConfirmCancel.btn-std`, …) that wins on specificity (1,1,0 vs
   0,2,0). The Cancel buttons in Create Role / Remove App / Inactive
   Confirm / Remove User / Delete Permission Group dialogs therefore
   still render at 8px while the rest of the form sits at 6px. Pin
   them explicitly under ADS Preview only; EDL Light keeps the 8px
   contract. The selectors mirror the ones already used in Pass-T10
   for typography unification so the responsibility list is in one
   place when a future Cancel button is added. */
[data-theme="ads-preview"] #crCancel.btn-std,
[data-theme="ads-preview"] #crConfirmCancel.btn-std,
[data-theme="ads-preview"] #crAppRemoveCancel.btn-std,
[data-theme="ads-preview"] #auInactiveConfirmCancel.btn-std,
[data-theme="ads-preview"] #auRemoveUserCancel.btn-std,
[data-theme="ads-preview"] #pcDeleteGroupCancel.btn-std {
  border-radius: var(--ads-radius-sm);
}

/* ─── P6-M3. Table header sort-icon gap ────────────────────────────────
   Base `.th-inner { gap: 4px }`. Canonical Ads DS Table Header Cell
   (Figma node 1728:13313) publishes `--table/size/header/gap = 6px`
   for the label-to-sort-icon spacing. The 2px difference is small
   but cumulative across an 8-column header row, and breaks the
   "every label rests on a 6px rhythm" pattern used by the body
   cells and pagination footer. Pin to 6px under ADS Preview only. */
[data-theme="ads-preview"] .th-inner {
  gap: 6px;
}

/* ─── P6-M6. Pagination — full ADS Pagination component ────────────────
   Canonical reference: Ads DS Pagination (Figma node 35:36). Spec:
     • Item size      : 36 × 36 (min-width 36, height 36)
     • Item padding   : 8px (centers the 16×16 chevron icon)
     • Item radius    : `8px` (literal; pagination is the only ADS form
                        family that uses 8px instead of the 6px radius-sm)
     • Item gap       : `--pagination/size/gap = 4px`
     • Rest bg        : `--pagination/page/rest/background = #FFFFFF`
     • Rest border    : `--pagination/page/rest/border = rgba(15,18,20,0.2)`
     • Rest text      : `--pagination/page/rest/text = #1E2528`, 14/normal
                        Open Sans Regular
     • Active bg      : `--pagination/page/active/background = #4045C2`
     • Active text    : `--pagination/page/active/text = #FFFFFF`
     • Active border  : `--pagination/page/active/border = rgba(15,18,20,0.5)`
     • Ellipsis       : same 36×36 slot, plain text, NO border, NO bg
     • Chevron prev/next: same 36×36 bordered button with 16×16 caret

   Current v2 base renders `.pg-n` at 24×24 / 12px / 2px radius and
   `.pg-nav` as a bare 16×16 icon with no chrome — both compress the
   pagination strip to a fraction of the ADS footprint, exactly the
   "too small" feedback raised in this pass. The earlier P4-7 covered
   the active-page color flip but left button geometry and the
   prev/next anatomy untouched. This block supplies the full ADS spec
   and supersedes P4-7's geometry while inheriting its concept.

   Row height: keep the band at 48px (already in place for RA + PM via
   P4-10/P4-13; lift Users panel here too so all three pagination rows
   share the same vertical rhythm with 36px buttons plus 6px breathing
   room top/bottom). EDL Light / Dark continue to render at 40px /
   24px buttons — they consume `--pgn-*` selectors that are untouched
   outside the `[data-theme="ads-preview"]` scope.

   Scope: every selector below is `[data-theme="ads-preview"]`-prefixed.
   No HTML, no JS, no Theme 1.0 changes — pure CSS lift of the existing
   `.pgn / .pg-nav / .pg-nums / .pg-n / .pg-dots` skeleton. Pagination
   page-size dropdown (`.pgn-dd`) and metadata labels (`.pgn-lbl`,
   `.pgn-show`) keep their existing ADS treatment. */

/* Row container — give the band enough vertical space for 36×36 buttons. */
[data-theme="ads-preview"] .pgn {
  min-height: 48px;
}
/* Page-numbers + nav-arrows cluster — uniform 4px gap per ADS spec.
   Base `.pgn-pages` uses 10px so the prev arrow sits further from the
   numbers; ADS treats all items as a single equal-gap row. */
[data-theme="ads-preview"] .pgn-pages {
  gap: 4px;
}

/* Prev / Next / First / Last arrow buttons — promote from bare 16×16
   icons to 36×36 bordered buttons with the 16×16 caret centered. The
   First/Last variants (»« glyphs) reuse the same chrome. */
[data-theme="ads-preview"] .pg-nav {
  width: 36px;
  height: 36px;
  padding: 8px;
  background: #FFFFFF;
  border: 1px solid rgba(15, 18, 20, 0.2);
  border-radius: 8px;
  color: var(--text-primary);
  box-sizing: border-box;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
[data-theme="ads-preview"] .pg-nav svg {
  width: 16px;
  height: 16px;
  display: block;
}
[data-theme="ads-preview"] .pg-nav:hover:not(.off) {
  background: var(--ads-surface-recessed);
  color: var(--text-primary);
  border-color: var(--ads-border-bold);
}
[data-theme="ads-preview"] .pg-nav:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
[data-theme="ads-preview"] .pg-nav.off {
  /* Base already sets opacity:0.4 + pointer-events:none; chrome stays the
     same shape, the reduced opacity carries the disabled signal. */
  background: #FFFFFF;
  color: var(--text-muted);
  border-color: rgba(15, 18, 20, 0.15);
}

/* Page-number buttons — 36×36, 14px Open Sans, 8px radius, white bg
   with neutral 1px border. The active state lifts the brand fill +
   white text + slightly darker brand-tinted border per ADS spec. */
[data-theme="ads-preview"] .pg-n {
  width: 36px;
  min-width: 36px;
  height: 36px;
  padding: 0 8px;
  background: #FFFFFF;
  border: 1px solid rgba(15, 18, 20, 0.2);
  border-radius: 8px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  color: var(--text-primary);
  box-sizing: border-box;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
[data-theme="ads-preview"] .pg-n:hover:not(.on) {
  background: var(--ads-surface-recessed);
  color: var(--text-primary);
  border-color: var(--ads-border-bold);
}
[data-theme="ads-preview"] .pg-n.on {
  background: var(--brand);
  color: var(--text-on-brand);
  border-color: rgba(15, 18, 20, 0.5);
  font-weight: 400;          /* ADS active text stays Regular — the
                                fill carries the emphasis, not weight */
  border-radius: 8px;        /* override P4-7's 6px to match canonical
                                Pagination spec exactly */
}
[data-theme="ads-preview"] .pg-n.on::after {
  display: none;             /* explicit kill of the EDL 2px tick mark */
}
[data-theme="ads-preview"] .pg-n:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}

/* Ellipsis — same 36×36 slot but no border, no background. Acts as a
   visual spacer that preserves the 4px gap rhythm without reading as
   an interactive button. */
[data-theme="ads-preview"] .pg-dots {
  width: 36px;
  min-width: 36px;
  height: 36px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  color: var(--text-primary);
  box-sizing: border-box;
}

/* ─── P6-M5. Combo-box selected row — ADS recessed gray, not brand ─────
   Canonical reference: Ads DS Dropdown / Select component (Figma node
   36:56, "dropdown-menu / option-2" highlight state). The published
   ADS Select paints the highlighted/selected option with the recessed
   surface token:
     • `--dropdown/surface/recessed = rgba(15,18,20,0.05)`
       (equivalent to our `--ads-surface-recessed`, already defined).
     • Text color stays neutral `--field-label/state/default/text = #1E2528`.
     • There is NO brand-color fill, border, or text tint on the row.

   Section 8 above paints `.edl-combo-item.selected` with
   `var(--brand-bg-selected)` + `var(--brand-text)` — that read as a
   full purple/lavender row, the exact mismatch raised by product. The
   Pass-5 hover override (`--ads-surface-recessed`) at line ~4326 is
   correct; the SELECTED state was the only family member still using
   the brand fill. Repoint both selected variants (default + IAM roles
   menu) to the recessed gray and drop the brand text tint.

   Checkmark behavior: kept as-is on the trailing edge of the selected
   row (per product UX — the checkmark is a useful "currently selected"
   affordance the ADS Figma reference omits but our IAM forms benefit
   from). Its color stays `--brand-text` so it reads as a subtle brand
   accent against the recessed gray, providing the selection signal
   without coloring the whole row.

   EDL Light / Dark continue to use the original brand-bg-soft tint
   (the base rules at lines 925-926); only `[data-theme="ads-preview"]`
   is touched here.                                                    */
[data-theme="ads-preview"] .edl-combo-item.selected,
[data-theme="ads-preview"] .edl-combo-menu--iam-roles .edl-combo-item.selected,
[data-theme="ads-preview"] .edl-combo-menu--add-user .edl-combo-item.selected {
  background: var(--ads-surface-recessed);
  color: var(--text-primary);
}
[data-theme="ads-preview"] .edl-combo-item.selected:hover,
[data-theme="ads-preview"] .edl-combo-item.selected.kb-highlight,
[data-theme="ads-preview"] .edl-combo-menu--iam-roles .edl-combo-item.selected:hover,
[data-theme="ads-preview"] .edl-combo-menu--iam-roles .edl-combo-item.selected.kb-highlight,
[data-theme="ads-preview"] .edl-combo-menu--add-user .edl-combo-item.selected:hover,
[data-theme="ads-preview"] .edl-combo-menu--add-user .edl-combo-item.selected.kb-highlight {
  background: var(--ads-surface-recessed);
  color: var(--text-primary);
}

/* ─── P6-M8. Role cards — equal height per row + bottom-centered toggle ──
   Role cards in `#addUsersPage` Roles & Permissions normally take their
   natural content height (the base rule sets `align-self: start;
   height: fit-content;`). When two cards in the same grid row have
   different description / access-level text wrap counts, the row's
   bottom edge ends up jagged and the "Show all permissions" toggle
   lands at different vertical positions across siblings. Per ADS,
   stacked cards in a row should share the same height and primary
   actions should pin to a consistent vertical position.

   Fix (ADS Preview only):
   • Override grid `align-items: start` → `stretch` so cards inherit
     the row's tallest natural height.
   • Override card `align-self: start; height: fit-content;` →
     `align-self: stretch; height: auto;` so the card actually stretches.
   • Promote `.au-role-card-top` and `.cr-app-body` to flex columns
     with `flex: 1 1 auto` so the inner stack fills the card.
   • Pin `.au-role-view-toggle` to the bottom-center via
     `margin-top: auto; align-self: center` — pushes the toggle past
     description / access-level content to the bottom of the card body
     and centers it on the card's horizontal axis.

   The expand panel (`.au-role-expand`) is a sibling of
   `.au-role-card-top` in the card column; its collapsed `max-height: 0`
   keeps it out of the layout when not active, so the bottom of
   `.au-role-card-top` coincides with the bottom of the card chrome at
   rest — the toggle pin lands on the inner chrome edge.

   Scope: ADS Preview + `#addUsersPage` only. EDL Light / Dark and
   other surfaces using `.au-role-card` keep the existing natural-height
   behavior. The Planner card (lone card on row 2) is unaffected because
   it has no row mate to stretch against. The Remove action stays in
   `.cr-app-section-head` (the first child of `.au-role-card-top`) and
   continues to render flush to the top-right, untouched by this rule. */
[data-theme="ads-preview"] #addUsersPage .au-role-cards {
  align-items: stretch;
  align-content: stretch;
}
[data-theme="ads-preview"] #addUsersPage .au-role-card {
  align-self: stretch;
  height: auto;
}
[data-theme="ads-preview"] #addUsersPage .au-role-card-top {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
[data-theme="ads-preview"] #addUsersPage .au-role-card-top > .cr-app-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
[data-theme="ads-preview"] #addUsersPage .au-role-card .au-role-view-toggle {
  margin-top: auto;
  align-self: center;
}

/* ─── P6-M7. Combo-box selected row — remove trailing checkmark ────────
   Canonical reference: Ads DS Dropdown / Select (Figma node 36:56). The
   ADS Select option states (Rest / Hover / Selected) do NOT render a
   trailing checkmark glyph on the selected row — selection is conveyed
   entirely by the recessed-gray row fill set in P6-M5. The leading
   left-aligned label is the only mark inside the row.

   This supersedes the "checkmark kept as-is" decision in P6-M5's
   header comment. Earlier product UX argued for keeping the brand-blue
   tick as a "currently selected" affordance, but the canonical ADS
   Select component does not include it, and product reviewed the open
   menu against the Figma reference and asked to drop the glyph so the
   selected row matches ADS 1:1.

   Implementation: the base SVG (`.edl-combo-check`, app.js line 2907)
   is still emitted in the DOM — we hide it via CSS rather than touching
   the JS so EDL Light / Dark keep the existing affordance. `display:none`
   removes the icon from the flex layout entirely; because the row uses
   `justify-content: space-between` with only the label remaining, the
   label stays left-aligned at the existing 16px padding (no shift).

   Scope: ADS Preview only; all combo menu variants (default, IAM roles,
   add-user). Selecting an option still updates the hidden field and
   visible input — only the in-menu glyph is suppressed.            */
[data-theme="ads-preview"] .edl-combo-item.selected .edl-combo-check,
[data-theme="ads-preview"] .edl-combo-menu--iam-roles .edl-combo-item.selected .edl-combo-check,
[data-theme="ads-preview"] .edl-combo-menu--add-user .edl-combo-item.selected .edl-combo-check {
  display: none;
}

/* ─── P6-M4. Timezone combo focus — neutralise the brand halo ──────────
   Pass-4 above applies the canonical ADS Dropdown/Input focus pattern
   to every `.edl-combo-input:focus` (brand border + 3px soft halo).
   On the Add-User form the Timezone field sits inline with adjacent
   plain inputs (Display Name, Email) that have no equivalent focus
   ring, so the brand halo reads as a heavy double-border anomaly
   relative to its neighbours. Per product feedback, neutralise the
   ring on this one field only — keep the resting neutral border on
   focus AND while the menu is open. The activation affordance is
   carried by the menu opening itself (the combo opens on focus/click
   and on Enter/Space from keyboard), so keyboard a11y remains intact:
   tab traversal, arrow-key option navigation, Esc-to-close, and
   screen-reader announcement of the trigger and listbox are all
   unchanged. Scoped strictly to `#auTimezoneCombo` so the rest of the
   combo family (Region, Team, application pickers, page-size, etc.)
   keep the ADS focus pattern; EDL Light is untouched. */
[data-theme="ads-preview"] #auTimezoneCombo .edl-combo-input:focus,
[data-theme="ads-preview"] #auTimezoneCombo .edl-combo-input:focus-visible,
[data-theme="ads-preview"] #auTimezoneCombo.open .edl-combo-input {
  border-color: var(--border-input);
  box-shadow: none;
  outline: none;
}

/* ════════════════════════════════════════════════════════════════════
   V3 ONLY · Edit User page (Figma node 847:16112 / 847:16172)
   ────────────────────────────────────────────────────────────────────
   Layout rewrite (FigmaSpec):
     • Basic Information card hosts ONE horizontal row (.au-edit-row)
       holding three 296-px columns:
         col 1 = identity block (72-px avatar + name + email + active
                 check-circle), Figma node 847:16173.
         col 2 = Preferred name (top) + Team (bottom),     Figma 847:16186.
         col 3 = Region        (top) + Timezone (bottom),  Figma 847:16189.
       Column gap = 39 px, row gap inside cols 2/3 = 24 px.
     • Add-mode .au-grid is untouched; edit-mode neutralizes its grid
       layout and places the four real form fields into cols 2 and 3
       via direct flex children with explicit width: 296px.
     • Identity block uses the EDL neutral placeholder by default to
       match Figma 847:16174; photo path is opt-in per user record.

   All selectors are scoped to `#addUsersPage.is-edit-mode` so Add
   mode is byte-identical to the V2 fork.
   ════════════════════════════════════════════════════════════════════ */

/* Hide all edit-only DOM in Add mode. The `hidden` attribute on the
   elements handles initial paint; once .is-edit-mode toggles, JS
   clears `hidden`. The CSS rule below is belt-and-suspenders. */
#addUsersPage:not(.is-edit-mode) .au-edit-only { display: none !important; }
/* Mirror rule for Add-mode-only DOM — hide it in Edit mode so the
   Access section reads as "Assigned Role + effective access table"
   instead of also showing the Add-mode role-cards stack
   (Frances QA 2026-06-07, Edit User v3 / Figma 788:4348). */
#addUsersPage.is-edit-mode .au-add-only { display: none !important; }

/* ─── Access / Role and Permission section — shared helper sentence ──
   Same EDL rhythm as the Edit Team Members helper (margin: 0 0 16px;
   14/20 secondary text). Add User's "Role and Permission" card (Figma
   1023:22053) still carries this sentence and keeps this base rule
   completely unchanged. */
#addUsersPage #auRolesCard .au-access-helper {
  /* Figma 1003:20186 "Frame 2134099791": ~8px between the chevron/title
     baseline and this description (was 0, i.e. text touching the
     title row directly). */
  margin: 8px 0 16px;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--text-secondary, #526374);
}
/* Edit User's "Access" card (final-QA pass, 2026-08-11 round 2) drops
   this sentence entirely — scoped to `.is-edit-mode` only, so Add
   User's "Role and Permission" card above is completely untouched.
   `display: none` (not `visibility: hidden` / zero-opacity / an
   off-screen or visually-hidden treatment) removes the paragraph from
   rendered layout, reserved spacing, AND the accessibility tree in one
   step — nothing below it needs a compensating margin change, because
   an element with no box also has no margin box. */
#addUsersPage.is-edit-mode #auRolesCard .au-access-helper {
  display: none;
}

/* Effective-access table layout. Reuses the EDL table rhythm
   (header 32px, body 48px, 1px Gray-20 dividers, 14/21 body text).
   3 columns: Application 28% / Access Level 16% / Summary auto.
   Read-only — no row hover or click.

   Un-scoped from `.is-edit-mode` (Figma 1023:22053 "Role and
   Permission"): Add User's populated state uses this exact same
   table, not the older `.au-role-cards` stack (which is now retired
   — see `#auRoleCards[hidden]` below). `renderAuCombinedEffectiveAccess`
   already ran on every Add-mode role add/remove before this pass; only
   the *visible* target was wrong. */
#addUsersPage #auRolesCard .au-eff-wrap {
  margin-top: 16px;
}
/* Round 22 (2026-08-11 — Access card refinement): Edit mode only,
   widen the role-controls -> table gap from 16px to 24px per brief
   ("approximately 24px of space between the role controls and the
   access table") so the table reads as its own block rather than
   crowding the "Update access" row above it. Add mode is unaffected
   (still 16px) — its role controls have a different shape (helper
   text + single-select combo + Add button) and were not in scope. */
#addUsersPage.is-edit-mode #auRolesCard .au-eff-wrap {
  margin-top: 24px;
}
#addUsersPage #auRolesCard .au-eff-tbl {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}
#addUsersPage #auRolesCard .au-eff-tbl thead th {
  height: 32px;
  text-align: left;
  vertical-align: middle;
  font-size: 12px;
  font-weight: 400;
  line-height: 18px;
  color: var(--text-secondary, #526374);
  padding: 0 8px;
  border-bottom: 1px solid var(--border-default, #D4DEE3);
  white-space: nowrap;
}
#addUsersPage #auRolesCard .au-eff-tbl thead th:first-child {
  padding-left: 0;
}
#addUsersPage #auRolesCard .au-eff-tbl thead th:last-child {
  padding-right: 0;
}
/* 3-column Access table (Frances UX 2026-06-08 round 3): Application,
   Access Level, Effective access. The 3rd column carries a read-only
   single-line "Resource: Actions; … ; +N more" summary (no chips, no
   pills, no interactive affordance). The Application and Access
   Level columns are tightened from rounds 1/2 (28%/18% → 22%/14%) to
   give the summary column the most room — round-3 brief calls out
   "do not leave excessive empty space on the right" and the single-
   line format benefits directly from a wider summary column. */
#addUsersPage #auRolesCard .au-eff-tbl thead th.au-eff-th-app     { width: 22%; }
#addUsersPage #auRolesCard .au-eff-tbl thead th.au-eff-th-level   { width: 14%; }
#addUsersPage #auRolesCard .au-eff-tbl thead th.au-eff-th-summary { width: auto; }
/* Round 22 (2026-08-11 — Access card refinement): Edit mode only,
   rebalance the two content-bound columns slightly — Access Level's
   values ("Full Access"/"View Access"/"No Access") never need 14% of
   a ~1000px card (that reads as a wide gap before Effective access
   starts), while Application occasionally wraps a long name
   ("Identity and Access Management") onto 2 lines.    Shifting 2% from
   Level to Application tightens that gap and gives the wrapping name
   a bit more room. All 3 columns stay % of the card (set on both the
   `<col data-aueff-col>` elements and these `<th>` rules together),
   so header <-> body edges stay pixel-identical, just shifted. Add
   mode keeps the original 22/14 split — unchanged/out of scope. */
#addUsersPage.is-edit-mode #auRolesCard .au-eff-tbl thead th.au-eff-th-app   { width: 24%; }
#addUsersPage.is-edit-mode #auRolesCard .au-eff-tbl thead th.au-eff-th-level { width: 12%; }

#addUsersPage #auRolesCard .au-eff-tbl tbody td {
  /* Vertical padding rather than fixed height so the cell can
     grow when chips wrap onto a second visual line under the app
     name. The earlier 44px fixed-height clipped chips at narrow
     widths. */
  padding: 12px 8px;
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary, #171C20);
  border-bottom: 1px solid var(--border-default, #D4DEE3);
  vertical-align: middle;
}
#addUsersPage #auRolesCard .au-eff-tbl tbody td:first-child {
  padding-left: 0;
}
#addUsersPage #auRolesCard .au-eff-tbl tbody td:last-child {
  padding-right: 0;
}
#addUsersPage #auRolesCard .au-eff-tbl tbody tr:last-child td {
  border-bottom: 0;
}

/* Application cell — single line, plain table text (chips moved out
   to the new dedicated "Effective access" column on 2026-06-08). */
#addUsersPage #auRolesCard .au-eff-app {
  font-weight: 400;
  color: var(--text-primary, #171C20);
}
#addUsersPage #auRolesCard .au-eff-app-name {
  /* Brief 2026-06-08 round 4: weight reduced 500 → 400 so the
     Application cell reads as table body content, not a heading. */
  font-weight: 400;
  color: var(--text-primary, #171C20);
  line-height: 21px;
}

/* Access-level label — plain table text. Round 4 dropped weight
   500 → 400 per brief ("Do not make Access Level bold. Access Level
   should read like table body content, not a headline."). Class
   name still reads "...-pill" for backward compatibility, but no
   pill chrome — no border, no chip background, no bold. */
#addUsersPage #auRolesCard .au-eff-level-pill {
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary, #171C20);
}
#addUsersPage #auRolesCard .au-eff-level-pill--no-access {
  color: var(--text-muted, #6A8095);
}

/* ─── Effective access — single-line read-only resource/action
   summary (Frances UX 2026-06-08 round 3). Replaces the previous
   stacked block. Format:
       Orders: Read, Create, Update; Media Plans: Read; +2 more
   Plain table text, semicolon separators, NO chips/pills/links/dots.
   JS (auEffApplyOverflow) measures the cell after render and trims
   tail groups until the visible string fits on a single line; the
   counter `+N more` then carries a native title tooltip listing only
   the HIDDEN groups (one per line). */
#addUsersPage #auRolesCard .au-eff-tbl tbody td.au-eff-app,
#addUsersPage #auRolesCard .au-eff-tbl tbody td.au-eff-level,
#addUsersPage #auRolesCard .au-eff-tbl tbody td.au-eff-summary-cell {
  /* Single-line summary → vertical-center the level and app name
     against the summary text again (rounds 1/2 used top because the
     summary wrapped). */
  vertical-align: middle;
}
#addUsersPage #auRolesCard .au-eff-summary-cell {
  color: var(--text-primary, #171C20);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  /* Hide horizontal overflow at the cell boundary; the measure pass
     should keep the inner span within the cell width, but this is a
     defensive guard against a single uncollapsed pixel pushing the
     row width. */
  overflow: hidden;
}
#addUsersPage #auRolesCard .au-eff-summary {
  display: inline-block;
  max-width: 100%;
  white-space: nowrap;
  color: var(--text-primary, #171C20);
  vertical-align: middle;
}
#addUsersPage #auRolesCard .au-eff-summary-group {
  /* Keep "Resource: Actions" together as one shaped unit so the
     measure pass can drop whole groups, never mid-group breaks. */
  white-space: nowrap;
}
#addUsersPage #auRolesCard .au-eff-summary-res {
  /* Round 4: weight dropped 500 → 400 per brief — the Access table
     body should read uniformly at 14/21/400. Resource and action
     text now share the same weight; the colon plus formatting carry
     the visual structure. */
  font-weight: 400;
  color: var(--text-primary, #171C20);
}
#addUsersPage #auRolesCard .au-eff-summary-acts {
  /* Brief: "normal table body text color"; resource label leads via
     a slightly heavier weight but the action verbs sit in the
     standard primary text color so they never read as a link. */
  font-weight: 400;
  color: var(--text-primary, #171C20);
}
#addUsersPage #auRolesCard .au-eff-summary-sep {
  /* Semicolon separator. Same color as body text — it reads as
     punctuation, not as content. */
  color: var(--text-primary, #171C20);
  font-weight: 400;
}
/* "+N more" — Indigo 70 per brief, no underline, no chip background,
   no border. Cursor is `help` because the native title tooltip is
   only revealed on hover; this is the only acceptable affordance
   exception per brief ("default unless tooltip implementation
   requires hover behavior"). Padded with a leading space rather than
   margin so it follows the semicolon-and-space cadence of the rest
   of the summary. */
#addUsersPage #auRolesCard .au-eff-summary-more {
  display: inline;
  margin-left: 8px;
  padding: 0;
  background: transparent;
  border: 0;
  color: #3611C8;
  font-weight: 400;
  font-size: 14px;
  line-height: 21px;
  text-decoration: none;
  cursor: help;
  white-space: nowrap;
}
#addUsersPage #auRolesCard .au-eff-summary--none {
  color: var(--text-muted, #6A8095);
  font-style: italic;
}

/* Round 6 (2026-06-09): the Access table participates in the shared
   column-resize helper, so its <th> cells need `position: relative`
   for the `.col-resize-handle` (anchored at `right:-1px`).
   Round 8 (2026-06-09): `overflow-x: auto` was painting a phantom
   bottom scrollbar even when the content fit (sub-pixel
   `table-layout: fixed` rounding caused `scrollWidth = clientWidth + 1`,
   which trips the auto scrollbar). Switching to `overflow-x: hidden`
   suppresses that bar; the Access table is only 3 columns wide and
   has comfortable min-width floors per <col>, so legitimate overflow
   is not a concern here. Page-level overflow is also prevented. */
#addUsersPage #auRolesCard .au-eff-tbl thead th {
  position: relative;
}
#addUsersPage #auRolesCard .au-eff-wrap {
  overflow-x: hidden;
}

/* Round 5 (2026-06-09): summary cell now renders compact counts —
   "Orders (3); Media Plans (1); …" — instead of verbose "Resource:
   Actions" strings. The count sits in its own `.au-eff-summary-count`
   span so we can tone it down without affecting the resource label. */
#addUsersPage #auRolesCard .au-eff-summary-count {
  color: var(--text-secondary, #526374);
  font-weight: 400;
}

/* ─── Edit User: Assigned Role field width (Edit mode only) ─────────
   Round 5 (2026-06-09): the assigned-role dropdown previously
   stretched to (card-width − 24px)/2 to align with the Add-mode
   role-card grid. In Edit mode there's no card grid below, so the
   wide dropdown reads as overweight. Cap the row to a role-selector
   width (~380px) and let the dropdown fill that. Add-mode is
   unaffected because the rule is class-gated on `.is-edit-mode`. */
/* Round 18 (2026-06-09): Edit User Assigned Role row now hosts the
   dropdown AND the EDL "Add" button on the same line (the button used
   to be Add-mode only). The combo keeps a stable ~380px width per
   brief §2 ("dropdown width around 360–420px"); the row total grows
   to fit the button + 8px gap. Without this cap relaxation the row
   would still clamp at 380px and the button would wrap to a second
   line on common viewports. */
/* Round 22 (2026-08-11 — Access card refinement, Figma node 7722:252):
   Edit User's "Access" heading and the "Assigned Role" label sat only
   12px apart total (the shared `.cr-section-header` 4px bottom padding
   plus `.au-field`'s base 8px `margin-top`), which read as cramped —
   Add mode doesn't have this problem because its helper paragraph
   (`.au-access-helper`) fills that space; Edit mode hides that
   paragraph entirely, so the label sat right under the heading with
   almost no breathing room. Bumping this field's own top margin to
   20px (+ the header's existing 4px padding = 24px total, matching
   the brief's 20-24px target) fixes Edit mode only — Add mode keeps
   its original 8px rhythm below the visible helper text. */
#addUsersPage.is-edit-mode #auRolesCard .au-role-field {
  margin-top: 20px;
}
#addUsersPage.is-edit-mode #auRolesCard .au-role-row {
  max-width: 480px;
  gap: 8px;
}
#addUsersPage.is-edit-mode #auRolesCard .au-role-row > .au-role-dd-field {
  flex: 0 0 380px;
  min-width: 0;
  max-width: 380px;
}
#addUsersPage.is-edit-mode #auRolesCard .au-role-row > .au-btn-add {
  flex: 0 0 auto;
  /* Round 21 (2026-06-09): the "Update access" button sits next to
     the EDL multi-select trigger (40px tall), so the button height
     matches the trigger per brief §6 ("Button height matches
     dropdown height"). The global `.au-btn-add` stays 32px so Add
     User's row (which sits next to a 40px combo but is sized for
     the historical Add-mode rhythm) is untouched. */
  height: 40px;
  min-height: 40px;
  max-height: 40px;
}
/* Round 18 (2026-06-09): assigned-role chips list (edit-mode only).
   Sits directly below the role row with 12px vertical rhythm so it
   reads as the "currently assigned" cluster paired with the picker.
   Each chip mirrors EDL chip styling (soft brand background, 1px
   border) and exposes a small `×` remove control. Chips stay
   read-only-looking (no underline, no link blue) — the only
   interactive affordance inside the chip is the remove button.

   Round 21 (2026-06-09): the chip list is hidden permanently — the
   new EDL-style multi-select dropdown manages selection state inside
   the closed trigger, so the external chip cluster is visually
   redundant. The container stays in the DOM only so existing app.js
   references stay safe; nothing renders into it. The other rules
   below remain dormant. */
#auAssignedRolesList {
  display: none !important;
}
#auAssignedRolesList[hidden] { display: none; }
.au-assigned-role-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 4px 0 10px;
  background: var(--brand-bg-soft);
  border: 1px solid var(--brand-text-soft, var(--brand-bg-selected));
  border-radius: 14px;
  color: var(--brand-text);
  font-family: var(--ff);
  font-size: 13px;
  font-weight: 500;
  line-height: 18px;
  white-space: nowrap;
  cursor: default;
}
.au-assigned-role-chip-label { cursor: default; }
.au-assigned-role-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-left: 2px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 50%;
  color: var(--brand-text);
  cursor: pointer;
  transition: background-color 0.12s ease;
}
.au-assigned-role-chip-remove:hover { background: var(--brand-bg-selected); }
.au-assigned-role-chip-remove:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 1px;
}
.au-assigned-role-chip-remove svg { display: block; width: 12px; height: 12px; }

/* ─── Edit User: assigned-role multi-select dropdown (Round 21) ─────
   EDL "checkbox dropdown" pattern (Figma EDL Component Library node
   13065:14610). Implemented WITHOUT the search input per the brief —
   the role list is short and search adds unnecessary complexity. The
   trigger height/border/radius/typography deliberately mirror the
   existing `.edl-combo-input` so the dropdown sits flush in the
   `.au-role-row` next to the `.au-btn-add` ("Update access") and
   matches the 40px field rhythm used elsewhere in Add/Edit User.

   Visible in Edit mode only. Add mode keeps the single-select EDL
   combo (`#auRoleCombo` with `.au-add-only`). */
#addUsersPage .au-role-multi {
  position: relative;
  display: none;          /* shown by `.is-edit-mode` rule below */
  width: 100%;
}
#addUsersPage.is-edit-mode .au-role-multi { display: block; }

#addUsersPage .au-role-multi-trigger {
  appearance: none;
  box-sizing: border-box;
  width: 100%;
  height: 40px;
  margin: 0;
  padding: 0 36px 0 16px;
  border: 1px solid var(--input-border);
  border-radius: 8px;
  background: var(--bg-surface);
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 40px;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  position: relative;
  display: inline-flex;
  align-items: center;
  outline: none;
  transition: border-color 0.15s ease, border-radius 0.1s ease;
}
#addUsersPage .au-role-multi-trigger:hover { border-color: var(--text-muted); }
#addUsersPage .au-role-multi-trigger:focus-visible {
  border-color: var(--brand-text);
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 1px;
}
#addUsersPage .au-role-multi.is-open .au-role-multi-trigger {
  border-color: var(--brand-text);
  border-radius: 8px 8px 0 0;
  border-bottom-color: var(--border-default);
}
#addUsersPage .au-role-multi-value {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Empty / placeholder state — matches `.edl-combo-input::placeholder`. */
#addUsersPage .au-role-multi-value.is-placeholder {
  color: var(--text-placeholder);
  font-weight: 400;
}
#addUsersPage .au-role-multi-chev {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-placeholder);
  transition: transform 0.2s ease;
  pointer-events: none;
}
#addUsersPage .au-role-multi.is-open .au-role-multi-chev {
  transform: translateY(-50%) rotate(180deg);
}
/* Disabled state (parity with `.edl-combo.is-au-roles-locked`). */
#addUsersPage .au-role-multi.is-disabled .au-role-multi-trigger {
  background: var(--bg-readonly, #f6f8fa);
  color: var(--text-placeholder);
  cursor: not-allowed;
  pointer-events: none;
}

/* Menu — positioned via JS (`fixed`) so it can overflow card edges.
   Same shell as `.edl-combo-menu`: brand border, no top border (the
   trigger's bottom border doubles as the menu's top border), soft
   shadow, no transitions. Scrollbar styled to match the rest of EDL. */
.au-role-multi-menu {
  position: fixed;
  background: var(--bg-surface);
  border: 1px solid var(--brand-text);
  border-top: 1px solid var(--border-default);
  border-radius: 0 0 8px 8px;
  box-shadow: var(--shadow-pop);
  z-index: 9998;
  padding: 6px 0;
  max-height: min(50vh, 360px);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(158, 176, 189, 0.8) transparent;
}
.au-role-multi-menu[hidden] { display: none; }
.au-role-multi-menu::-webkit-scrollbar { width: 6px; height: 6px; }
.au-role-multi-menu::-webkit-scrollbar-track { background: transparent; }
.au-role-multi-menu::-webkit-scrollbar-thumb {
  background: rgba(158, 176, 189, 0.8);
  border-radius: 999px;
  border: none;
}
.au-role-multi-menu::-webkit-scrollbar-thumb:hover { background: var(--gray-50); }

/* Each option row — EDL checkbox dropdown spacing (Figma 13065:14610
   item rows). Checkbox sits 16px from the menu's left edge and the
   label follows with a 12px gap. Row height ~40px matches the EDL
   `--add-user` density used by the role combo in Add mode. */
.au-role-multi-option {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 40px;
  padding: 0 16px;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.1s ease;
}
.au-role-multi-option:hover,
.au-role-multi-option.kb-highlight {
  background: var(--bg-hover-soft);
}
.au-role-multi-option.is-selected {
  background: var(--brand-bg-soft);
  font-weight: 500;
}
.au-role-multi-option.is-selected:hover,
.au-role-multi-option.is-selected.kb-highlight {
  background: var(--brand-bg-selected);
}
.au-role-multi-option:focus-visible {
  outline: 2px solid var(--brand-text);
  outline-offset: -2px;
}

/* Checkbox visual — sits in front of the native input which is
   `position: absolute; opacity: 0` for hit-test only. Indigo 70 fill
   when selected (matches Figma EDL Palette/Indigo/70 #3611C8), white
   tick. Gray 30 border (matches EDL Palette/Gray/30 #B8C7D0) when
   not selected. */
.au-role-multi-option-cb {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
  width: 16px;
  height: 16px;
}
.au-role-multi-option-cb input[type="checkbox"] {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.au-role-multi-option-cb-visual {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: 1px solid var(--gray-30, #B8C7D0);
  border-radius: 2px;
  background: var(--bg-surface);
  color: #fff;
  transition: background-color 0.1s ease, border-color 0.1s ease;
}
.au-role-multi-option-cb-visual svg {
  width: 12px;
  height: 12px;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 0.1s ease, transform 0.1s ease;
}
.au-role-multi-option.is-selected .au-role-multi-option-cb-visual {
  background: var(--brand-text);
  border-color: var(--brand-text);
}
.au-role-multi-option.is-selected .au-role-multi-option-cb-visual svg {
  opacity: 1;
  transform: scale(1);
}
.au-role-multi-option-cb input[type="checkbox"]:focus-visible + .au-role-multi-option-cb-visual {
  box-shadow: 0 0 0 2px var(--brand-focus-ring);
  border-color: var(--brand-text);
}
.au-role-multi-option-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ─── Edit User: "View access breakdown" trigger ────────────────────
   Round 22 (2026-08-11 — Access card refinement, Figma node 7722:252):
   moved off the *ghost* Button reference (node 7722:259, no border —
   see the round-2 history below) onto the *tertiary* Button variant
   the brief actually links to, because ghost's transparent-at-rest,
   border-less shell reads as plain text until the pointer is right on
   top of it ("clear interactive state" was the explicit ask). Tertiary
   keeps every dimension/color token round 2 already verified —
   36px height (8px/12px padding-y/x — 8+20+8=36), 6px radius, Open
   Sans SemiBold 14px/20px, text `button/variant/tertiary/text`
   #51585b, hover/active/focus backgrounds `rgba(15,18,20,0.05)` /
   `rgba(15,18,20,0.1)` / `rgba(15,18,20,0.05)` — identical to ghost's,
   confirmed directly against Figma's hover/active/focus/disabled
   instances (nodes 17:281/17:290/17:299/17:308) — and adds tertiary's
   one distinguishing property: a 1px `rgba(15,18,20,0.5)` border at
   rest/hover/active/focus, fading to `rgba(15,18,20,0.05)` on
   disabled (`button/variant/tertiary/disabled/border`), so the button
   now reads as a real outlined control at rest, not just SemiBold
   text.

   Icon: round 3 (2026-08-11) added a trailing chevron-right icon here
   per the then-current Figma "Type=text+icon" tertiary instance (see
   git history for that rationale). Round 26 (2026-08-11, later the
   same day) removed it again per an updated spec calling for a
   text-only label — `justify-content: center` below now centers the
   single remaining `<span>` label for free, no extra CSS needed.

   History (round 2, 2026-08-11): rebuilt from the unrelated *compact*
   26px ghost contract shared with "Remove Role"/"Remove application"
   (`.cr-btn-remove` and friends) plus a `margin-left: -8px` hack that
   faked flush text alignment; both were removed in favor of this
   button's own full box model and real ADS padding, with its
   container `.au-eff-actions` starting at the table's own left edge
   so the button's outer box — not just its label glyphs — aligns
   with the table's content boundary. */
#addUsersPage #auRolesCard .au-eff-actions {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  margin-top: 12px;
}
/* Round 31 (2026-08-11) — Add User parity pass: "View access
   breakdown" is hidden (not just visually empty) whenever no role is
   assigned yet (`assignedRoles.length === 0`), toggled via the
   `hidden` attribute in app.js (`refreshAuEffActionsVisibility`).
   Needs its own `[hidden]` override because `.au-eff-actions` above
   already sets `display: flex` at equal specificity — the extra
   attribute selector here breaks that tie so the element actually
   leaves the flow (no reserved height/margin) instead of rendering as
   an empty flex row. */
#addUsersPage #auRolesCard .au-eff-actions[hidden] {
  display: none;
}
/* Round 22: widen the controls-are-connected-to-the-table gap from
   12px to 22px per brief ("approximately 20-24px of spacing above the
   View access breakdown control so it does not feel attached to the
   final table row"). Round 31 (2026-08-11) — un-scoped from
   `.is-edit-mode`: Add User's "Role and Permission" card uses this
   exact same shared markup, and the Add User parity spec calls for
   "exactly the same spacing as Edit User" once a role is assigned, so
   Add mode now gets the same 22px instead of the previous 12px. */
#addUsersPage #auRolesCard .au-eff-actions {
  margin-top: 22px;
}
#addUsersPage #auRolesCard .au-eff-view-breakdown {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 36px;
  padding: 8px 12px;
  border: 1px solid rgba(15, 18, 20, 0.5);
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  white-space: nowrap;
  color: var(--iam-ads-text-muted, #51585b);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
#addUsersPage #auRolesCard .au-eff-view-breakdown:hover:not(:disabled) {
  background: rgba(15, 18, 20, 0.05);
  color: var(--iam-ads-text, #1e2528);
}
#addUsersPage #auRolesCard .au-eff-view-breakdown:active:not(:disabled) {
  background: rgba(15, 18, 20, 0.1);
  color: var(--iam-ads-text, #1e2528);
}
#addUsersPage #auRolesCard .au-eff-view-breakdown:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
#addUsersPage #auRolesCard .au-eff-view-breakdown:disabled {
  color: rgba(81, 88, 91, 0.45);
  background: transparent;
  border-color: rgba(15, 18, 20, 0.05);
  cursor: not-allowed;
}

/* ─── Edit User: Effective access breakdown modal — content ─────────
   Canonical ADS Modal (Ads Design System, node 38:2): rebuilt on the
   shared `.cr-confirm-dialog--modal` shell (header / divider / body /
   divider / footer) already used by Revoke access, instead of a
   bespoke chrome. Sizing (`.au-eff-breakdown-dialog`) is defined
   further down, alongside the other `.cr-confirm-dialog` width
   overrides, so it wins the cascade the same way `.au-adduser-dialog`
   and `.tm-add-dialog` already do. */
.au-eff-breakdown-subtitle {
  margin: 0;
}

/* Assigned-role summary — a compact inline label + value pair (not a
   full field row), separated from the per-application breakdown by
   the standard ADS hairline divider plus the body region's existing
   12px gap, so it reads as identity metadata sitting above the
   detailed list rather than another data row. */
.au-eff-modal-role {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
}
.au-eff-modal-role-label {
  font-family: var(--ff);
  font-size: 13px;
  font-weight: 400;
  line-height: 18px;
  color: var(--iam-ads-text-secondary, #3B4347);
}
.au-eff-modal-role-value {
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  color: var(--iam-ads-text, #1E2528);
}
.au-eff-modal-divider {
  flex: 0 0 auto;
  height: 1px;
  background: var(--iam-ads-divider, rgba(15, 18, 20, 0.10));
}
.au-eff-modal-scroll {
  display: flex;
  flex-direction: column;
}

/* Per-application groups — consistent two-column grid (function name
   / effective permission) shared across every application so values
   start on the same vertical axis modal-wide. Groups are separated by
   hairline dividers and vertical rhythm alone (no per-row borders or
   card containers) to keep the modal light. */
.au-eff-modal-section {
  padding: 12px 0;
  border-bottom: 1px solid var(--iam-ads-divider, rgba(15, 18, 20, 0.10));
}
.au-eff-modal-section:first-child { padding-top: 0; }
.au-eff-modal-section:last-child  { padding-bottom: 0; border-bottom: 0; }
.au-eff-modal-app {
  margin: 0 0 8px 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  color: var(--iam-ads-text, #1E2528);
}
.au-eff-modal-list {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.au-eff-modal-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  column-gap: 16px;
  align-items: baseline;
}
.au-eff-modal-res {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--iam-ads-text, #1E2528);
  word-break: break-word;
}
.au-eff-modal-acts {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--iam-ads-text-secondary, #3B4347);
  word-break: break-word;
}
.au-eff-modal-empty {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--iam-ads-text-muted, #51585B);
  font-style: italic;
}
@media (max-width: 520px) {
  .au-eff-modal-row {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* ─── Basic Information edit row (Figma 847:16172) ──────────────────
   Single horizontal row: identity col + 2 field cols. Aligned items
   center per Figma, gap 39 px. The three children are explicitly
   sized to 296 px so the row matches the Figma frame at the canonical
   1048-px card width. Wraps on narrower viewports. */
#addUsersPage .au-edit-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 39px;
  padding: 16px 0 8px 0;
  min-width: 0;
}
/* Explicit `[hidden]` override — without this, the `display: flex`
   rule above (author stylesheet) wins the cascade over the UA
   default `[hidden] { display: none }` (same class of bug already
   hit and fixed for the Add User modal's dropdown/spinner). Add
   mode's "no employee selected" empty state now relies purely on
   this attribute (no `.au-edit-only` class anymore), so it must
   actually hide. */
#addUsersPage .au-edit-row[hidden] { display: none; }

/* ─── Identity column (Figma 1003:20186 → "Frame 2134099562") ──────
   64 px avatar (re-measured against the task's authoritative node;
   the previous 72px came from an older reference, 847:16173) + 16 px
   gap + name/email stack. Total column width = 296 px (Figma). */
#addUsersPage .au-id-block {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Fills whatever the identity grid column gives it (a
     `minmax(240px, 296px)` range — see `.au-section-body` below)
     instead of hard-coding 296px. A rigid width here would make the
     block wider than its own column on narrower cards, which is how
     the name and email came to sit on top of the Preferred name
     field: an over-wide block has no width left for the text to
     ellipsis against. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
  /* The identity block is non-interactive (no role, no tabindex). Kill
     any inherited outline/border/box-shadow so the block never paints
     a stray blue selection/focus rectangle around the avatar + name +
     email cluster (Frances QA, 2026-05-29). Real interactive
     descendants (none today) would still receive their own
     :focus-visible treatment via their own selectors. */
  outline: none;
  border: 0;
  box-shadow: none;
}
#addUsersPage .au-id-block:focus,
#addUsersPage .au-id-block:focus-visible,
#addUsersPage .au-id-block:focus-within,
#addUsersPage .au-edit-row:focus,
#addUsersPage .au-edit-row:focus-visible,
#addUsersPage .au-id-avatar,
#addUsersPage .au-id-avatar:focus,
#addUsersPage .au-id-avatar:focus-visible,
#addUsersPage .au-id-avatar-svg:focus,
#addUsersPage .au-id-avatar-img:focus {
  outline: none !important;
  box-shadow: none !important;
}
#addUsersPage .au-id-avatar {
  flex: 0 0 64px;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  /* Figma 847:16174 placeholder carries its own white circle + indigo
     stroke, so the container has no background of its own. Photo path
     (`.au-id-avatar-img`) layers fully against the circular crop via
     `overflow: hidden` above. */
  background: transparent;
}
#addUsersPage .au-id-avatar--external {
  /* External users render the same blue initials chip the External
     Users table uses (`.avatar-initials`, 40 px). Edit User scales
     it up to the 72 px identity circle below via
     `.au-id-avatar-initials`. The container background stays
     transparent — the chip paints the visible blue disc itself, so
     this matches the table's chip exactly at every DPI. */
  background: transparent;
}
/* External Edit User initials chip — same shape, color, and font
   stack as the table chip (`.avatar-initials`, defined globally),
   but scaled up to the 64 px identity circle and bumped to a
   readable size at that scale. Inherits `background:
   rgb(78,136,210)`, `color: #FFFFFF`, `border-radius: 50%`,
   `font-weight: 700`, `letter-spacing: 0.5px` from the global
   `.avatar-initials` rule, so the table chip and Edit User chip
   are visually 1:1 (Frances QA, 2026-05-29). */
#addUsersPage .au-id-avatar .au-id-avatar-initials {
  width: 64px;
  height: 64px;
  font-size: 24px;
  line-height: 1;
}
#addUsersPage .au-id-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  /* Photo clarity (Frances QA 2026-05-29):
     Source assets are 1536x1024 PNGs being painted into the 64-px
     identity circle (~24x downscale). `image-rendering: auto` lets
     Chrome/Safari use their default bicubic-style downscale, which
     is correct for photographs. The previous
     `-webkit-optimize-contrast` hint is intended for line art /
     screenshots and made photo edges look blocky at this ratio.
     Matches the Users-table avatar rendering path. */
  image-rendering: auto;
}
/* Figma 847:16174 placeholder SVG — rendered inline at native 64x64
   (Figma 1003:20186's own avatar box is 64px, superseding the older
   72px reference) so vector strokes stay sharp at every DPI.
   `display: block` kills the inline baseline gap,
   `shape-rendering: geometricPrecision` keeps the indigo outline
   circle smooth. */
#addUsersPage .au-id-avatar-svg {
  display: block;
  width: 64px;
  height: 64px;
  shape-rendering: geometricPrecision;
}
/* Legacy 40-px line-art icon (no longer rendered in V3 edit mode) —
   kept for any add-mode fallback that might still emit the old SVG. */
#addUsersPage .au-id-avatar-icon {
  width: 40px;
  height: 40px;
}
#addUsersPage .au-id-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  flex: 1 1 auto;
}
#addUsersPage .au-id-name {
  /* Figma 847:16182 — Medium 18/21, EDL Gray 95. */
  font-size: 18px;
  font-weight: 500;
  line-height: 21px;
  color: var(--text-primary, #171C20);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#addUsersPage .au-id-email-row {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}
#addUsersPage .au-id-email {
  /* Figma 847:16184 — Roman 14/21, EDL Gray 95 (not muted). */
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--text-primary, #171C20);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
#addUsersPage .au-id-status {
  /* Figma 847:16185 — 16 × 16 check-circle, EDL Green 70 #056C07. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 16px;
}

/* ─── Field columns (Figma 847:16186 + 847:16189) ──────────────────
   Add-mode `.au-grid` uses display:flex with .au-field-* order
   classes. In edit mode we hide every Add-mode-only field (Name,
   First/Last name, Email, Status, Profile picture) so only Preferred
   name / Team / Region / Timezone remain, then collapse `.au-grid`
   into a transparent flex shell that lets the four fields participate
   in the parent `.au-edit-row` flex layout via `display: contents`.
   Each field then gets a fixed 296-px width to land on the Figma
   3-col grid. */
#addUsersPage .au-field-edit-only { display: none !important; } /* the read-only "Name" row */
#addUsersPage .au-field-email     { display: none !important; }
#addUsersPage .au-field-status    { display: none !important; }
#addUsersPage .au-profile-field   { display: none !important; }
#addUsersPage .au-grid {
  /* `display: contents` lifts the four remaining .au-field children
     into the .au-edit-row sibling-context above. The .au-grid box
     itself is invisible. We pair this with `order` so the fields
     reflow under the identity block on wrap. */
  display: contents;
}
/* Each field becomes a flex item inside .au-edit-row's flex line.
   Two 296-px columns × two rows are achieved via order + width. */
/* Edit-mode 3-col CSS Grid layout — scoped to the Basic Information
   card only. The Permission Options card (#auPermsCard) keeps its
   own layout untouched.

   Re-measured against the task's authoritative node (1003:20186 →
   "Frame 2134099567" / "Frame 2134099794"): the identity column is a
   fixed 296px, but the two field columns are NOT a matching fixed
   296px each — Figma sizes them as an equal flexible split
   (`flex: 1 0 0`) of a shared 661px-wide right-hand group, so they
   grow to fill whatever width remains up to the card's true
   inner-right guide (father than the previous fixed 296px, which
   left the right column ~32px short of that guide — a violation of
   the "right edge must align with the inner-right guide" requirement).
   `minmax(0, 1fr)` reproduces that flexible-fill behavior while
   keeping the identity column's own 296px fixed per Figma. */
#addUsersPage #auBasicCard .au-section-body {
  /* ONE column-gap token for both gaps in the row, so the space
     between the identity column and Preferred name/Team is always
     identical to the space between Preferred name/Team and
     Region/Timezone. Every breakpoint below re-points this single
     property rather than setting left/right spacing per column. */
  --au-basic-col-gap: 39px;
  /* Identity column: a range, not a fixed track. 296px is the Figma
     width and stays the maximum; 240px is the floor below which the
     avatar + a useful amount of name text no longer fit, at which
     point the responsive stages further down move the identity block
     onto its own row instead of squeezing it. */
  --au-basic-identity-col: minmax(240px, 296px);
  display: grid;
  grid-template-columns: var(--au-basic-identity-col) minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: var(--au-basic-col-gap);
  row-gap: 24px;
  padding-top: 8px;
  align-items: center;
  min-width: 0;
}
#addUsersPage #auBasicCard .au-section-body > .au-edit-row {
  grid-column: 1;
  /* Identity column spans BOTH grid rows so the avatar + name + email
     group is vertically centered against the full card height — not
     stuck in row 1 at the top of the card (Frances QA 2026-06-01).
     The form fields on the right still occupy two distinct rows
     (Preferred name + Region on row 1, Team + Timezone on row 2); the
     identity simply spans across them and `align-items: center` (set
     on the grid container above) handles the vertical centering. */
  grid-row: 1 / -1;
  align-self: center;
  padding: 0;
  gap: 0;
  /* Track the identity column's own width (see `.au-id-block`). */
  width: 100%;
  max-width: 100%;
  min-width: 0;
}
/* `.au-grid` is the legacy Add-mode wrapper around the form fields.
   In edit mode we collapse its box (display:contents) so its four
   real field children participate directly in the section-body grid
   tracks defined above. */
#addUsersPage #auBasicCard .au-section-body > .au-grid {
  display: contents;
}
#addUsersPage #auBasicCard .au-field-preferred { grid-column: 2; grid-row: 1; order: 0; }
#addUsersPage #auBasicCard .au-field-region    { grid-column: 3; grid-row: 1; order: 0; }
#addUsersPage #auBasicCard .au-field-team      { grid-column: 2; grid-row: 2; order: 0; }
#addUsersPage #auBasicCard .au-field-timezone  { grid-column: 3; grid-row: 2; order: 0; }
#addUsersPage #auBasicCard .au-grid > .au-field {
  min-width: 0;
  margin: 0;
  width: auto;
  /* The two fields sharing a row must share a top edge. They're the
     same height at normal text sizes, so the grid's `align-items:
     center` looks identical — but under browser zoom or a larger base
     font a longer label ("Preferred name" vs "Region") wraps to a
     second line, and centering then floats the shorter field down out
     of line with its partner. Aligning to the row start keeps the pair
     level however tall either one grows. The identity block opts back
     into centering above, since it spans both rows. */
  align-self: start;
}

/* ─── Responsive stages ────────────────────────────────────────────
   Three usable columns for as long as the card can hold them, then a
   two-column form with the identity on its own row, then a single
   column. Each stage keeps ONE shared column-gap, so the two gaps in
   any row stay equal to each other. Thresholds come from the width the
   two form fields end up with: the card's content box is roughly
   `viewport - 193px`, so at 900px the fields are still ~200px wide in
   the 3-column layout, and at 600px they are still ~200px wide in the
   2-column layout. Below each of those they'd be too cramped to use.

   These stages are deliberately NOT scoped to `.is-edit-mode`: Add
   User and Edit User render the same markup, so they reflow the same
   way (Edit User being the reference for this card's layout). */

/* Medium: tighten the flexible widths and the gap before wrapping. */
@media (max-width: 1199px) {
  #addUsersPage #auBasicCard .au-section-body {
    --au-basic-col-gap: 24px;
    row-gap: 16px;
  }
}

/* Identity moves to its own row; the two form columns sit beneath it
   and keep the same shared gap between them. */
@media (max-width: 900px) {
  #addUsersPage #auBasicCard .au-section-body {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto;
  }
  #addUsersPage #auBasicCard .au-section-body > .au-edit-row {
    grid-column: 1 / -1;
    grid-row: 1;
  }
  #addUsersPage #auBasicCard .au-field-preferred { grid-column: 1; grid-row: 2; }
  #addUsersPage #auBasicCard .au-field-region    { grid-column: 2; grid-row: 2; }
  #addUsersPage #auBasicCard .au-field-team      { grid-column: 1; grid-row: 3; }
  #addUsersPage #auBasicCard .au-field-timezone  { grid-column: 2; grid-row: 3; }
}

/* Narrow: one column. The two form columns stack in pair order —
   Preferred name + Team, then Region + Timezone — so the groupings that
   read as columns at wider sizes stay together here instead of
   interleaving into the markup's Preferred/Region/Timezone/Team order. */
@media (max-width: 600px) {
  #addUsersPage #auBasicCard .au-section-body {
    --au-basic-col-gap: 0px;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
  }
  #addUsersPage #auBasicCard .au-section-body > .au-edit-row,
  #addUsersPage #auBasicCard .au-field-preferred,
  #addUsersPage #auBasicCard .au-field-region,
  #addUsersPage #auBasicCard .au-field-team,
  #addUsersPage #auBasicCard .au-field-timezone {
    grid-column: 1;
    grid-row: auto;
    width: 100%;
    max-width: 100%;
    min-width: 0;
  }
  #addUsersPage #auBasicCard .au-section-body > .au-edit-row { order: 1; }
  #addUsersPage #auBasicCard .au-field-preferred { order: 2; }
  #addUsersPage #auBasicCard .au-field-team      { order: 3; }
  #addUsersPage #auBasicCard .au-field-region    { order: 4; }
  #addUsersPage #auBasicCard .au-field-timezone  { order: 5; }
}

/* Figma top-right action cluster is just Cancel + Save Permission.
   The Remove User link (an existing V2 utility) is hidden in V3 edit
   mode to match the Figma 1:1. The flow itself is preserved — Remove
   User can be re-surfaced from a future moremenu or page-level
   actions area in a follow-up. */
#addUsersPage.is-edit-mode #auRemoveUser { display: none !important; }

/* ─── Section titles in V3 Edit mode (Figma 847:16112) ─────────────
   Both "Basic Information" and "Permission Options" use the indigo
   brand (#3611C8) section title color in the Figma — distinct from
   the dark-text section titles V2 / Add mode use. Scoped to Edit
   mode so Add User and earlier versions are untouched. */
#addUsersPage.is-edit-mode #auBasicCard .cr-section-title,
#addUsersPage.is-edit-mode #auPermsCard .cr-section-title {
  color: var(--brand, #3611C8);
  font-weight: 700;
  font-size: 18px;
  line-height: 22px;
}
#addUsersPage.is-edit-mode #auBasicCard .cr-section-chev,
#addUsersPage.is-edit-mode #auPermsCard .cr-section-chev {
  color: var(--brand, #3611C8);
}

/* ─── Permission Options card (Figma 847:16138) ─────────────────────
   Single helper paragraph above the Assigned Applications field.
   Per Figma 847:16145 — 14 px Source Sans Pro Regular, leading 20,
   EDL Gray 95 (#171C20).

   Vertical rhythm (Figma 847:16139 / 847:16140 — Frances QA 2026-05-29):
   • header row .cr-section-header has padding 6/0/4 (~4px bottom)
   • helper margin-top 16px gives the 8px Figma gap PLUS recovers
     the ~12px breathing room the header's py-[16px] supplies in
     Figma but our compact .cr-section-header does not — net effect
     visually matches Figma's title→helper spacing
   • helper margin-bottom 16px keeps the Figma 16px gap to the
     Assigned Applications row */
#auPermsCard .au-perms-helper {
  margin: 16px 0 16px 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-primary, #171C20);
}
#auPermsCard .au-perms-app-field { margin-top: 0; margin-bottom: 24px; }

/* ─── Assigned Applications row width cap (Figma 847:16146) ────────
   The Figma frame shows a moderate-width dropdown with the Add
   button immediately to its right (16-px gap), not a full-width
   combo stretched across the section. Cap the row at one app-card
   column so the dropdown reads at the Figma proportion. Mirrors
   the cap already in place on `#auRolesCard .au-role-row`. */
#auPermsCard .au-perms-app-field .au-role-row {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: nowrap;
  max-width: min(100%, calc((100% - 24px) / 2));
}
#auPermsCard .au-perms-app-field .au-role-row > .au-role-dd-field {
  flex: 1 1 auto;
  min-width: 0;
}
#auPermsCard .au-perms-app-field .au-role-row > .au-btn-add {
  flex: 0 0 auto;
}

/* ─── Add button visual (Figma 847:16152) ──────────────────────────
   Figma shows the Add button in its standard *resting* (enabled)
   state. The functional `disabled` attribute is preserved (clicks
   are gated on a combo selection), but we suppress the dim
   appearance so the button doesn't read as broken at the
   page-loaded baseline. Cursor still flips to not-allowed when
   actually disabled, so the affordance is honest. */
#auPermsCard .au-perms-app-field .au-role-row > .au-btn-add:disabled {
  opacity: 1;
  cursor: not-allowed;
}

/* Two cards in a row, 24 px gap per Figma 847:16429. Wraps to a
   single column on narrow viewports. */
#auPermsCard .au-perms-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}
@media (max-width: 900px) {
  #auPermsCard .au-perms-cards { grid-template-columns: 1fr; }
}

/* Application card shell (Figma 847:16382 / 847:16327).
   border 1px #EDEEF0, radius 16, padding 24, gap 16 between blocks.
   `min-height: 344px` matches the Figma card height so Show all
   permissions bottom-anchors at the Figma position with comfortable
   space above the rows. */
#auPermsCard .au-perms-card {
  border: 1px solid #EDEEF0;
  border-radius: 16px;
  background: #FFFFFF;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
  min-height: 344px;
}

/* Card header (Figma 847:16385 — gap 8, items center, justify
   between). Title left, Remove right. */
#auPermsCard .au-perms-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
/* Card title — InspireTWDC Heavy 18/22, color #48494A (Figma 847:16388).
   Project ships "InspireTWDC" via @font-face; falls back to the system
   sans stack if the font fails to load. */
#auPermsCard .au-perms-card-title {
  margin: 0;
  font-family: 'InspireTWDC', 'Source Sans Pro', system-ui, -apple-system, sans-serif;
  font-size: 18px;
  font-weight: 700;
  line-height: 22px;
  color: #48494A;
}
/* Remove button — Figma 847:16389. 24-px trash icon + "Remove" link
   in EDL Indigo (#3611C8), 14 px Roman, gap 8. No background, no
   border. Treat as a destructive *link*, not a button surface. */
#auPermsCard .au-perms-card-remove {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  border: 0;
  padding: 4px 2px;
  border-radius: 4px;
  color: var(--brand, #3611C8);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  cursor: pointer;
  transition: opacity 0.12s ease;
}
#auPermsCard .au-perms-card-remove svg {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
}
#auPermsCard .au-perms-card-remove-label { line-height: 21px; }
#auPermsCard .au-perms-card-remove:hover { opacity: 0.85; }
#auPermsCard .au-perms-card-remove:focus-visible {
  outline: 2px solid var(--brand-focus-ring, #928AFF);
  outline-offset: 1px;
}

/* Card body — flex column with explicit gap so Access Level breathes
   off the rows list and Show all permissions sits comfortably below
   the rows (Figma 847:16382 — `gap-[16px]` between the header/access
   block and the rows block, then `gap-[64px]` between the rows and
   Show-all). The flex stack on `.au-perms-card` itself handles the
   header → body gap with `gap: 16px`. */
#auPermsCard .au-perms-card-body {
  display: flex;
  flex-direction: column;
  gap: 24px;
  flex: 1 1 auto;
  min-height: 0;
}

/* Access Level field inside an application card (Figma 847:16392).
   The dropdown itself reuses the shared EDL `.cr-dd / .cr-dd-trigger /
   .cr-dd-menu / .cr-dd-option` rules so the trigger, open-state
   chevron rotation, menu surface, and brand-selected option all
   inherit from the design-system component (no native <select>).
   These rules only handle the wrapping geometry so the EDL trigger
   stretches to the card's content width. */
#auPermsCard .au-perms-access-field { margin-bottom: 0; }
#auPermsCard .au-perms-access-wrap {
  position: relative;
  display: flex;
  align-items: stretch;
}
#auPermsCard .au-perms-access-dd { width: 100%; }
#auPermsCard .au-perms-access-trigger { width: 100%; }
#auPermsCard .au-perms-access-coverage { display: none; }

/* Read-only permission coverage rows (Figma 847:16394 — gap 16,
   label left bold + actions right bold, EDL Gray 95). */
#auPermsCard .au-perms-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
#auPermsCard .au-perms-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  font-size: 14px;
  line-height: 21px;
  color: var(--text-primary, #171C20);
  letter-spacing: -0.1px;
}
#auPermsCard .au-perms-row-label {
  font-weight: 700;
  color: var(--text-primary, #171C20);
}
/* Per Figma 847:16400/16406/16412 the action list is dark Heavy text,
   not muted. Aligned right to mirror Figma's two-column split. */
#auPermsCard .au-perms-row-actions {
  font-weight: 700;
  color: var(--text-primary, #171C20);
  text-align: right;
}

/* Show all permissions toggle (Figma 847:16413 — gap 4, center,
   indigo brand, 14 px Open Sans SemiBold, with feather Arrow-Down
   icon at 16 px). Bottom-anchored under the rows. */
#auPermsCard .au-perms-show-all {
  align-self: center;
  background: transparent;
  border: 0;
  padding: 8px 12px;
  margin-top: auto;
  color: var(--brand, #3611C8);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: 4px;
}
#auPermsCard .au-perms-show-all:hover { background: var(--brand-bg-soft, #E6E6FF); }
#auPermsCard .au-perms-show-all:focus-visible { outline: 2px solid var(--brand-focus-ring, #928AFF); outline-offset: 1px; }
#auPermsCard .au-perms-show-all-arr {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
}
#auPermsCard .au-perms-show-all-arr svg { width: 16px; height: 16px; }

/* Expanded read-only details — same row shape, light divider, no
   helper paragraph (Figma doesn't show one). */
#auPermsCard .au-perms-card-expand {
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px dashed var(--border-card, #E2E9EC);
}

/* Save Permission disabled tint in edit mode — leans on the existing
   `.au-btn-save:disabled` rule but tightens contrast so the Figma
   "muted indigo" look matches. */
#addUsersPage.is-edit-mode .au-btn-save:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ════════════════════════════════════════════════════════════════════
   V3 ONLY · Permission Catalog (Permissions tab)
   ────────────────────────────────────────────────────────────────────
   Read-only catalog of registered permission functions. Layout is
   anchored inside #permsPanel and intentionally re-uses the existing
   .tbar / .tbl / .pgn skeleton from R&P + Users so density, spacing,
   and pagination match the rest of V3.
   ════════════════════════════════════════════════════════════════════ */

/* No inner page title/subtitle on the Permissions tab (Frances QA
   2026-05-29). The toolbar is the first content row inside
   #permsPanel — matches Users/Roles layout exactly. Users/Roles
   gets a ~12px gap below the tabs row from the panel's natural
   margin; Permissions previously relied on the (now-removed)
   .pm-pagehead block for that breathing room, so we restore the
   same 12px gap directly on the panel here. Measured against the
   Users/Roles tabs→toolbar gap (12px). */
#permsPanel {
  padding-top: 12px;
}

/* Toolbar right-side action group rule retained for any future
   secondary action; currently no action sits in `.tbar-r` on the
   Permissions tab (Export CSV removed). */
#permsPanel .tbar-r {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Inline filter dropdown CSS (.pm-filter-dd) removed Frances QA
   2026-05-29 round 3 — the Permissions toolbar now uses the shared
   Filter button + left-side .flt-drawer pattern (see Users / Roles).
   No #permsPanel-scoped filter dropdown styles needed; the EDL combos
   inside #pmFltDrawer inherit the global .edl-combo treatment used
   by the Roles drawer. */

/* ─── Catalog table columns + rows ─────────────────────────────────
   Aligned to the Roles (#rpColgroup) table system (Frances QA
   2026-05-31). The previous fixed-px column widths + 16px in-cell
   horizontal padding made the table feel cramped:
     • all 7 columns hit their min content width simultaneously, so
       the table read as 7 narrow vertical strips,
     • the 16px inset on every cell stole content breathing room
       inside each column,
     • the first column gutter was only 16px vs Roles' 28px, so
       "Function key" sat closer to the card edge than Role does.

   This block now mirrors the Roles pattern exactly:
     • proportional % column widths (sum to 100%, table fills the
       card width like Roles does instead of staying at a 980px
       fixed footprint and crushing every column),
     • the base `.tbl th, .tbl td { padding: 0 8px }` is left alone
       — Roles uses the same 8px in-cell padding,
     • a 28px left gutter on the first column matches `.rp-role`'s
       28px gutter, so the Function key column starts on the same
       visual content edge as Role does.
   Result: row rhythm, dividers, toolbar, and pagination already
   inherit from `.tbl` + the shared `.tbar` / `.pgn` rules and
   match Roles 1:1 (verified). */
#permsPanel .pm-catalog-tbl col[data-pm-col="key"]      { width: 16%; }
#permsPanel .pm-catalog-tbl col[data-pm-col="name"]     { width: 17%; }
#permsPanel .pm-catalog-tbl col[data-pm-col="app"]      { width: 14%; }
#permsPanel .pm-catalog-tbl col[data-pm-col="resource"] { width: 13%; }
#permsPanel .pm-catalog-tbl col[data-pm-col="action"]   { width: 10%; }
#permsPanel .pm-catalog-tbl col[data-pm-col="used"]     { width: 14%; }
#permsPanel .pm-catalog-tbl col[data-pm-col="status"]   { width: 16%; }

/* 28px left gutter on the first column (Function key) matches the
   `.rp-role` gutter on Roles so the table's left content edge is
   shared across both tabs. Last column's right padding stays at
   the base `.tbl` 8px so the Status chip sits clean. */
#permsPanel .pm-catalog-tbl th.pm-key,
#permsPanel .pm-catalog-tbl td.pm-key { padding-left: 28px !important; }

/* Reset the legacy `.pm-tbl th.pm-name { padding-left: 28px }` rule
   (line ~1152) when `.pm-name` is used inside the Functions catalog,
   where it is the SECOND column — not the first. The legacy rule
   was authored for an older Permissions schema where `.pm-name` was
   the leading column; with `.pm-key` now leading, the second column
   should not also carry the 28px gutter or it ends up indented
   from its true cell edge and breaks Roles parity. */
#permsPanel .pm-catalog-tbl th.pm-name,
#permsPanel .pm-catalog-tbl td.pm-name { padding-left: 8px !important; }

/* Function key cell — EDL table body text styling. The markup is a
   <code> tag so the key still semantically marks itself as a stable
   identifier, but visually it follows the table-cell typography
   (same family, size, weight, and Gray 95 color as Display name or
   Application). No monospace, no code-block tint, no inline padding —
   reads like a normal table value (Frances QA 2026-05-29). */
#permsPanel .pm-catalog-tbl .pm-key-code {
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  color: var(--text-primary, #171C20);
  background: transparent;
  padding: 0;
  letter-spacing: 0;
}

/* Catalog rows are read-only — no cursor/hover treatment, no focus
   outline, no row-click affordance (drawer removed 2026-05-29). The
   shared `.tbl tbody tr` rule provides any baseline row styling. */

/* "Not assigned" treatment in the Used-in column — neutral muted text
   so it reads as a benign empty state, not an error. */
#permsPanel .pm-used-none {
  color: var(--text-muted, #6A8095);
  font-style: italic;
}

/* ─── Status chips (Permission Catalog) ──────────────────────────
   Status chip — color treatment swapped Frances QA 2026-05-29 (round 2)
   to match the EDL Component Library "Promoted" chip variant for the
   Active state. Source: Figma EDL Component Library node 4722-57865
   (Type=Default, Color=Promoted, Dark Mode=False, Interaction=Resting).

   Mapping:
     • Active   → color=Promoted — Figma node 4722-57865
                  bg     = white (sits on table-row surface)
                  border = EDL Indigo 20 (#B8B8FF)
                  text   = EDL Indigo 70 (#3611C8)
                  Same indigo token used by `.btn-std` and `.name-link`,
                  so Active reads as the system's primary brand state
                  rather than as a generic neutral pill.
     • Inactive → color=Demoted — Figma node 4722-57917
                  (the visual treatment Active used pre-2026-05-29 PM)
                  bg     = EDL Gray 15 (#E2E9EC)
                  border = EDL Gray 20 (#D4DEE3)
                  text   = EDL Gray 95 (#171C20)
                  Inactive is intentionally muted/neutral — NOT red/pink
                  and NOT error/destructive (per Frances brief).
   Typography: InspireTWDC Roman 12/18 (T10 token), 400 weight — matches
   the EDL chip body across all color variants. Height ~22 px, 10 px
   horizontal padding, pill radius — same geometry the chip used before. */
#permsPanel .pm-chip {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 400;
  line-height: 18px;
  border: 1px solid transparent;
  white-space: nowrap;
}
#permsPanel .pm-chip--active {
  background: var(--bg-surface, #FFFFFF);
  border-color: var(--indigo-20, #B8B8FF);
  color: var(--indigo-70, #3611C8);
}
#permsPanel .pm-chip--inactive {
  background: var(--gray-15, #E2E9EC);
  border-color: var(--gray-20, #D4DEE3);
  color: var(--text-primary, #171C20);
}

/* Permission Catalog drawer/flyout CSS removed Frances QA 2026-05-29
   along with the markup and JS. The Permissions tab is a read-only
   browse table only — no detail panel, no overlay, no slide-in. */

/* ═══════════════════════════════════════════════════════════════════
   TEAMS — list panel + Edit Team page (added 2026-05-29)
   ═══════════════════════════════════════════════════════════════════
   All rules below are scoped to #teamsPanel or #editTeamPage so they
   cannot leak into Users / Roles / Permissions / older versions. The
   panel re-uses the shared EDL primitives (`.tbar`, `.tbl`, `.search`,
   `.btn-std`, `.au-card`, `.au-input`) and only adds layout/spacing
   rules unique to Teams. No new design tokens, no new colors.
   ═══════════════════════════════════════════════════════════════════ */

/* Inner-page Teams title/subtitle CSS (.tm-pagehead, .tm-page-title,
   .tm-page-sub) was removed Frances QA 2026-05-29 round 4 along with
   its markup — the tab label "Teams" already names the sub-view, and
   no other tab carries an inner title block. The panel now relies on
   the shared `#usersPanel, #rolesPanel, #teamsPanel { padding-top: 12px }`
   rule (see top of file) so the toolbar sits flush under the tabs row,
   matching Users / Roles / Functions exactly. */

/* Teams table — aligned to the Roles (#rpColgroup) rhythm so both
   tabs feel like the same product surface (Frances QA 2026-05-31).
   • fixed table-layout + proportional percentages = Roles model
   • 28px left gutter on the first column = Roles `.rp-role` rule
   • Members/Created are left-aligned like Roles' right-side metadata
     ("Created By" / "Create Date"), not right-rail numeric.
   Percentages: Team 15 / Description 58 / Members 13 / Created 14
   match Roles' 15 / 58 / 13 / 14 exactly so column edges line up
   when scanning between tabs. */
#teamsPanel .tm-tbl { min-width: 0; table-layout: fixed; }

/* R58 — Teams intelligent column growth. `mem` (a 1-3 digit count)
   and `created` (a fixed-format date) are bounded/content-based, so
   they're pinned in px; `table-layout: fixed` then hands 100% of the
   remaining width to `name`/`desc` in their existing ~20/80 ratio —
   Description (the long free-text column) absorbs almost all of the
   growth as the table widens, Name gets a smaller, proportional
   share, and the two bounded columns never grow past their content's
   needs the way a flat percentage would have. */
#tmColgroup col[data-tm-col="name"]    { width: 20.00%; }
#tmColgroup col[data-tm-col="desc"]    { width: 80.00%; }
#tmColgroup col[data-tm-col="mem"]     { width: 100px; }
#tmColgroup col[data-tm-col="created"] { width: 130px; }

/* Roles uses `.rp-tbl th.rp-role, .rp-tbl td.rp-role { padding-left:
   28px !important }` to anchor the first column to the same left
   edge as the search input above. Apply the same 28px gutter to
   the Teams first column so both tables share the same left edge.
   Round 39 (2026-08-12): both of those now resolve from the card's
   shared `--iam-card-content-inset` instead (32px — see the "ONE shared
   content inset" block at the end of this file), which is what actually
   puts them on the same edge as the search input above and the tab
   labels above that. This 28px remains for the non-V4 sheets. */
#teamsPanel .tm-tbl th.tm-th-name,
#teamsPanel .tm-tbl td.tm-cell-name { padding-left: 28px !important; }

/* Team-name link — same visual treatment as Users `.name-link`
   (see #usersPanel rule above). The Users selector is scoped to
   #usersPanel so we redeclare the same EDL pattern here, scoped
   to #teamsPanel, rather than widening the original selector and
   risking a regression on Users. */
#teamsPanel .tm-tbl tbody .tm-name-link {
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  color: var(--brand-text);
  text-decoration: none;
  cursor: pointer;
}
#teamsPanel .tm-tbl tbody .tm-name-link:hover {
  color: var(--brand-text-hover);
  text-decoration: underline;
}
#teamsPanel .tm-tbl tbody .tm-name-link:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ── Edit Team page ──
   Reuses .au-shell / .au-back / .au-header / .au-card geometry from
   Edit User. The two cards (Team details + Members) inherit
   .au-card padding and rounded corners. Only the form-row layout
   and members-table polish are new. */

/* ─── Edit Team alignment grid (Frances QA 2026-05-31) ───
   Both cards on the Edit Team page share one internal content grid.
   `.au-card` already supplies the horizontal padding (24px each
   side); the section body MUST NOT add a second horizontal inset on
   top of it, or the form/table content drifts right of the section
   title. So the card body padding is vertical-only.

   The Name column of the members table is also pulled flush with
   the body left edge (overriding `.tbl td { padding: 0 8px }`) so
   the table's first column aligns with the card title and helper
   text. The same applies to the trailing column on the right — it
   uses `padding-right: 0` so the table's right edge lines up with
   the card's right content edge.

   Result: the title, helper text, form labels/inputs, table header
   "Name", and first-column cells all sit on the same content
   grid. */

/* Shared body wrapper used by BOTH the Team details and Members
   cards. Vertical breathing room only — horizontal alignment comes
   from `.au-card`. */
#editTeamPage .au-section-body {
  padding: 16px 0 8px;
}

/* Two-up form layout for Name + Description. Inherits the shared
   body padding above; only the grid columns/gap are local. */
#editTeamPage .tm-details-body {
  display: grid;
  /* Fill the card like Edit User fields on wide screens (Frances / HARPS family). */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 24px 24px;
}
#editTeamPage .tm-details-body .au-input {
  width: 100%;
  max-width: none;
}
#editTeamPage .tm-field-name { grid-column: 1 / 2; }
#editTeamPage .tm-field-desc { grid-column: 2 / 3; }
@media (max-width: 720px) {
  #editTeamPage .tm-details-body {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  #editTeamPage .tm-field-name,
  #editTeamPage .tm-field-desc { grid-column: 1 / -1; }
}

/* "Team details" / "Members" section-heading typography — Final-QA
   (Edit Team header alignment + heading-size correction), Figma node
   1003:21682 (ADS `heading/sm`, the same token already confirmed and
   applied to Edit User's "Basic information" / "Access" card headers):
     MultiplaneTWDC Display, 20px / 24px line-height, weight 500,
     0 letter-spacing, color gray/800 (#161c1e ≈ this codebase's
     --iam-ads-text). A prior round under-sized these to the 15px/22px
     Open Sans SemiBold scale used by ACCORDION triggers elsewhere
     (Create Role, Add/Edit User, Permission Capability); these two
     headings are the only `.cr-section-header` instances that are NOT
     accordion triggers (no `role="button"`, no chevron — see the HTML
     comment above each `<h2>`), so they get the heavier heading/sm
     display treatment instead, matching Edit User's own two non-
     generic card headers exactly. Also why they must not inherit the
     generic accordion rule's Indigo link-brand color/hover recolor:
     these are static headings, not links or buttons.
     `html[data-iam-version="v4"] #editTeamPage` outranks both the
     generic accordion rule and its hover/focus recolor on specificity,
     independent of source order. */
html[data-iam-version="v4"] #editTeamPage .cr-section-header {
  cursor: default;
}
html[data-iam-version="v4"] #editTeamPage .cr-section-header .cr-section-title {
  margin: 0;
  font-family: "MultiplaneTWDC Display", "Open Sans", sans-serif;
  font-size: 20px;
  line-height: 24px;
  font-weight: 500;
  letter-spacing: 0;
  /* Color intentionally NOT set here (Round 36, 2026-08-12): "Team
     details" / "Members" now share the exact same #2D2F8C title color
     as Edit User's "Basic information" / "Access" — see the Round 26
     rule (search this file for "Round 26" near `#auBasicCard`), whose
     selector list was extended to include this same `#editTeamPage
     .cr-section-header .cr-section-title` selector rather than
     duplicating the hex value in a second rule. Typography (family/
     size/weight/line-height, all unaffected by this change) stays
     declared here since Team's heading uses a different type scale
     rationale (a static `<h2>`, not an accordion trigger — see the
     comment above) than the shared color rule needs to care about. */
}
html[data-iam-version="v4"] #editTeamPage .cr-section-header:hover .cr-section-title,
html[data-iam-version="v4"] #editTeamPage .cr-section-header:focus-visible .cr-section-title {
  /* Round 36: no `color` override here either — same reasoning as
     above. These headings aren't interactive (no `role="button"`,
     `cursor: default` on the header), so `background: transparent`
     is the only thing this rule still needs to guarantee. */
  background: transparent;
}

/* Helper text in the Members card. Sits flush-left with the card
   title and the first column of the table below. */
#editTeamPage .tm-members-helper {
  margin: 0 0 16px;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--text-secondary, #526374);
}

/* Members card header: title left, "+ Add members" action right.
   `.cr-section-header` is normally a plain flex row; we override
   only on the Members card so the Add button sits at the right
   edge of the card content. Scoped to `#editTeamPage` so the
   shared `.cr-section-header` used by Create Role / Edit User
   stays untouched. */
#editTeamPage .tm-members-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
/* The Add members button on Edit Team uses the EDL outlined
   `.cr-btn-add` base visual (purple border, transparent fill,
   purple label). This is intentionally NOT the filled-purple
   variant used inside #createRolePage, because here Add members is
   a secondary affordance sitting next to a destructive Delete Team
   ghost link — the secondary visual keeps the action hierarchy
   correct. Scoped to #editTeamPage so the Create Role override
   isn't affected. */
#editTeamPage .tm-add-members-btn {
  align-self: center;
  flex-shrink: 0;
}

/* Members table — re-uses .tbl primitives but pins column widths so
   Name / Email / Role / Actions read in a predictable rhythm and
   don't reflow when the underlying data changes. The Actions
   column is a fixed-min cell that hosts the Remove link. */
#editTeamPage .tm-members-tbl {
  width: 100%;
  table-layout: fixed;
}
/* Widths owned by IAM.evenColumns (tm-th-email is fluid). Keep actions compact. */
#editTeamPage .tm-members-tbl .tm-mcol-actions { width: 88px; }

#editTeamPage .tm-members-tbl tbody tr { cursor: default; }
#editTeamPage .tm-members-tbl tbody tr:hover { background: transparent; }

#editTeamPage .tm-th-actions .th-inner { justify-content: flex-end; }
#editTeamPage .tm-members-tbl td.tm-cell-actions { text-align: right; }
/* Round 37 (2026-08-12) — "Remove" now reuses the shared ADS ghost-
   button component (the same one Delete Team / Remove Role use — see
   `html[data-iam-version="v4"] .au-revoke-btn, .tm-delete-btn,
   .cr-btn-remove, .tm-row-remove` further down this file) instead of
   this page-specific indigo-link treatment, which is removed
   entirely. Shape/box-sizing/color/background/border/hover/active/
   focus states all now come from that one shared rule group (plus a
   compact-size modifier scoped to `.tm-row-remove` alone, right next
   to it) rather than being redeclared here. */

/* First and last column flush with the card's content edges so the
   header text "Name" lines up under the card title / helper, and
   the right edge of the table lines up with the card's right
   content edge. */
#editTeamPage .tm-members-tbl th:first-child,
#editTeamPage .tm-members-tbl td:first-child { padding-left: 0; }
#editTeamPage .tm-members-tbl th:last-child,
#editTeamPage .tm-members-tbl td:last-child  { padding-right: 0; }

/* `.tm-row-remove`'s box is already flush with the shared column's
   right boundary, same as this header, per the `:last-child` rule
   above. Every "Remove" label's own *visible text* actually sits some
   distance left of that boundary because the button carries its own
   right padding (needed for its hit-target/hover halo) — text-
   align:right on the td only flushes the button's box to the column
   edge, not the label glyphs inside it. The "Actions" header had no
   equivalent inset, so its glyphs sat visibly right of every "Remove"
   label's glyphs despite both boxes already sharing one column
   boundary. Restoring that same inset as the header's own right
   padding (must come after the generic `:last-child` zero above —
   identical selector specificity, so source order decides — to
   actually win the cascade) is the header-side half of one shared
   Actions-column right-padding contract; the body supplies its half
   via the button's own padding, so both *rendered* labels land on the
   exact same right edge instead of just their bounding boxes.

   Round 37 (2026-08-12): value updated from 6px to 8px to track
   `.tm-row-remove`'s new compact-ghost right padding (see its size
   rule further down this file) now that it reuses the shared ADS
   ghost-button component instead of its own bespoke padding. */
#editTeamPage .tm-members-tbl th.tm-th-actions {
  padding-right: 8px;
}

/* Members card body trims its bottom padding now that the
   "View all in Users" footer CTA is gone (Frances QA 2026-05-31).
   The card's own `.au-card` padding-bottom (18px) already gives
   the table comfortable breathing room below the last row. */
#editTeamPage .tm-members-body {
  padding-bottom: 0;
}

/* ── Edit Team: Add members modal ───────────────────────────────
   Reuses the EDL `.cr-confirm-backdrop` + `.cr-confirm-dialog`
   shell so the modal stays visually consistent with Remove Role /
   Remove application / Set user as inactive / Delete permission
   group. Overrides:
     • wider max-width (640px) so the search input + 3-column user
       rows have breathing room without becoming a full-screen sheet
     • search row sits right under the subtitle
     • user list is a fixed-height scrollable region (handles 50+
       eligible internal users without ballooning the modal)
     • footer adds a "N selected" status pill on the left so the
       user sees their selection count without scanning the list
   Strictly scoped to `.tm-add-dialog` / `#tmAddMembersBackdrop` so
   no other confirm modal in the app is affected. */
/* Width, header, body padding, search field, result rows and footer
   all come from the Add User Step-1 picker: this dialog carries
   `.au-adduser-dialog` alongside `.tm-add-dialog`, and its rows carry
   the `.au-adduser-option*` classes. What remains below is only what
   this picker has and Add User doesn't — the row checkbox, the inline
   results panel (Add User's list is a floating popover; selecting here
   must not dismiss it), the pre-search helper line, the error/empty
   copy, and the footer selection count. */
.tm-add-hint {
  margin: 0;
  font-family: var(--ff);
  font-size: 13px;
  line-height: 18px;
  color: var(--iam-ads-text-muted, var(--text-muted));
}
.tm-add-hint[hidden] { display: none; }
/* The results panel takes the dropdown's surface treatment (border,
   radius, clipped corners) but sits in the modal body rather than
   floating over it, so the modal grows to fit the list instead of
   overlaying itself. */
html[data-iam-version="v4"] .tm-add-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--iam-ads-surface);
  border: 1px solid var(--iam-ads-divider);
  border-radius: var(--iam-ads-control-radius);
  overflow: hidden;
}
html[data-iam-version="v4"] .tm-add-panel[hidden] { display: none; }
html[data-iam-version="v4"] .tm-add-listbox {
  /* Scrolls only once the results outgrow it; a short list keeps the
     modal short. */
  max-height: 336px;
}
.tm-add-option-item { list-style: none; }
/* The row is the <label>, so the whole thing is a click target for its
   checkbox. Layout otherwise comes from `.au-adduser-option`. */
html[data-iam-version="v4"] .tm-add-option {
  cursor: pointer;
  user-select: none;
}
html[data-iam-version="v4"] .tm-add-option.is-selected { background: var(--brand-bg-soft); }
html[data-iam-version="v4"] .tm-add-option-check {
  flex: 0 0 auto;
  margin: 0;
}
/* Search state copy — loading, empty, and error all render as a single
   row inside the listbox so the panel keeps one border and one
   scroll region regardless of state. */
html[data-iam-version="v4"] .tm-add-state-msg {
  list-style: none;
  padding: 12px;
  font-family: var(--ff);
  font-size: 13px;
  line-height: 18px;
  color: var(--iam-ads-text-secondary);
}
html[data-iam-version="v4"] .tm-add-state-error { color: var(--ads-red-400, #AF434E); }
html[data-iam-version="v4"] .tm-add-retry {
  margin-left: 4px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--iam-ads-brand);
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}
html[data-iam-version="v4"] .tm-add-submit-error {
  margin: 0;
  font-family: var(--ff);
  font-size: 13px;
  line-height: 18px;
  color: var(--ads-red-400, #AF434E);
}
html[data-iam-version="v4"] .tm-add-submit-error[hidden] { display: none; }
.tm-add-actions {
  align-items: center;
}
.tm-add-actions-spacer { flex: 1; }
/* Footer padding is deliberately not overridden here: this modal now
   takes the shared ADS-modal footer (16px 24px, border-top) so it sits
   on exactly the same spacing as the Add User picker. The compact
   12px variant this used to carry made the two modals visibly
   different heights when placed side by side. */
.tm-add-selected-count {
  /* Round 25 (2026-06-09 — Add members footer typography):
     selected-count text upgraded from 13px/500 → 14px/400 to match
     EDL body small / secondary text spec referenced in the brief
     (14px size, 20px line-height, regular weight, Gray 70 color).
     The existing `.cr-confirm-actions { align-items: center }` rule
     handles flex-axis centering, but the smaller line-box previously
     paired with the 32px button row produced a subtle optical drop
     (the count looked low next to the buttons' upper-cap baseline).
     The 2px top padding nudges the glyph baseline up by the same
     amount the EDL Promoted button uses for its own optical
     centering (`.au-btn-save { padding: 2px 16px 0 }`), so the
     "0 selected" baseline now sits on the same optical horizon as
     the Cancel and Add members labels. */
  font-family: var(--ff);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  color: var(--text-secondary);
  padding: 2px 0 0;
}

/* ════════════════════════════════════════════════════════════════════
   ADS Preview · Pass-7 — ADS v2.1 alignment polish (May 30, 2026).

   Source of truth:
     • /Users/frances.sun/My Drive/Cursor and Code/ads-design-system
       (ADS v2.1 reference folder added 2026-05-29 by Frances)
     • ads-cursor-setup/ads-components.json     v2.1.0  releaseDate 2026-05-29
     • ads-cursor-setup/.cursor/rules/ads.mdc   conventions
     • design.md                                Platform layer notes

   What this pass does (ADS theme only):
     1. Promotes the Permission Catalog status chips to ADS Chip
        language under ADS Preview only. Active = brand-wash + brand
        text/border (Indigo 50 / 300, the published "promoted" chip).
        Inactive = recessed-gray + neutral primary text (the published
        "demoted/neutral" chip). The base global `.pm-chip--*` rules
        (lines ~6122-6143) keep painting EDL Light / EDL Dark with the
        original EDL Indigo 70 / Gray 95 values — they are not touched.
     2. Adds an ADS-scoped :disabled paint for form inputs so disabled
        state reads consistently across the theme (the only existing
        :disabled rule was `.pc-page .cr-input:disabled` and only for
        the Permission Capability page).
     3. Adds an ADS-scoped hover/active/focus treatment for the
        destructive `.cr-btn-danger-solid` button. Pass-3 already
        pins the 6 px radius; this fills in the remaining states using
        the published ADS red ramp (Red 300 surface, Red 400 hover).

   What this pass deliberately does NOT do:
     • Does not change layout, IA, routing, data, avatar behaviour,
       permission/team/role logic, or v1/v2 page content.
     • Does not modify EDL Light (`:root`) or EDL Dark
       (`[data-theme="dark"]`) tokens or rules.
     • Does not modify any selector outside `[data-theme="ads-preview"]`.
     • Does not retrofit em-dashes in pre-existing comments
       (ads.mdc rule applies to net-new prompt-pack output, not to
       a 6 K-line file's comments; touching those would be a
       cross-theme edit and the brief forbids it).

   QA guarantee: every selector below is prefixed with
   `[data-theme="ads-preview"]` and only paints when the user opts
   into ADS Preview from the profile-menu theme switcher. Switch to
   EDL Light or EDL Dark and these rules stop firing.
   ════════════════════════════════════════════════════════════════════ */

/* ─── P7-1. Permission Catalog status chips — ADS Chip language ──────
   Per ads-components.json the Chip family is folded under the broader
   surface-and-text token system; the published "Active = Promoted"
   chip uses the brand hue (Indigo) for both text and border, with a
   wash background. The "Inactive = Demoted" chip uses the recessed-
   gray surface with neutral primary text. This mirrors Pass-6 P4-14
   (Permission Management Type column chips: Default / Custom) which
   already maps Default → neutral surface + brand text and Custom →
   brand wash + brand text. Repainting Active → brand wash + brand
   text gives Active and Custom the same chromatic family so the two
   "this row uses brand" affordances read consistently.

   Geometry (height, padding, font-size, line-height, radius) is
   inherited from the base `.pm-chip` rule (lines ~6122). We only
   re-target the colour triplet (background / border / text). */
[data-theme="ads-preview"] #permsPanel .pm-chip--active {
  background: var(--brand-bg-soft);          /* Indigo 50  #E2E3F2 */
  border-color: var(--brand);                /* Indigo 300 #4045C2 */
  color: var(--brand-text);                  /* Indigo 300 #4045C2 */
}
[data-theme="ads-preview"] #permsPanel .pm-chip--inactive {
  background: var(--ads-surface-recessed);   /* rgba(15,18,20,0.05) */
  border-color: var(--border-default);       /* rgba(15,18,20,0.2)  */
  color: var(--text-primary);                /* Gray 600   #1E2528 */
}

/* ─── P7-2. Form input disabled paint — ADS Field disabled state ─────
   The published ADS Field component pairs disabled inputs with a
   recessed surface + muted ink so the read-only intent is obvious
   without resorting to opacity (which carries low-contrast a11y
   risk). Mirrors the existing `.pc-page .cr-input:disabled` rule
   (line ~5030) but extends it to every ADS-themed form control.

   Scope is narrow on purpose: only inputs that already participate
   in the ADS Preview re-skin (search, filter inputs, combo inputs,
   create-role / create-permission inputs). Native `<select disabled>`
   keeps the platform's UA paint — ADS does not publish a styled
   native-select disabled state, and overriding it here would
   contradict the "do not invent" rule in ads.mdc. */
[data-theme="ads-preview"] .search input:disabled,
[data-theme="ads-preview"] .flt-input:disabled,
[data-theme="ads-preview"] .edl-combo-input:disabled,
[data-theme="ads-preview"] .cr-input:disabled,
[data-theme="ads-preview"] .cr-textarea:disabled {
  background: var(--ads-surface-recessed);
  color: var(--text-muted);
  border-color: var(--border-input);
  cursor: not-allowed;
  -webkit-text-fill-color: var(--text-muted);
  opacity: 1;
}

/* ─── Delete/Remove confirmation buttons — ADS Primary Button, not a
   red "danger" variant (app-wide Delete/Remove audit, 2026-08-11) ───
   This block used to repaint `.cr-btn-danger-solid` red under ADS
   Preview (`--ads-red-300` rest / `--ads-red-400` hover/active — a
   destructive-button treatment that does not exist as an approved ADS
   Button variant in this system; ads-components.json only lists
   primary / secondary / tertiary / ghost). Per the app-wide decision
   to never use a red destructive button in this prototype, that
   override is removed entirely — no replacement rule is needed here,
   because `.cr-btn-danger-solid` already sits in every shared
   `html[data-iam-version="v4"]` box-model/typography/focus-visible
   group alongside `.cr-btn-save` / `.au-btn-save` (see e.g. the
   min-height:36px/padding/radius/font block and the
   `outline:2px solid #4045c2` focus-visible block elsewhere in this
   file), and its own un-scoped base rule (~line 1485) already uses
   `var(--brand)` / `var(--brand-hover)` / `var(--indigo-95)` /
   `var(--brand-disabled-bg)` — the exact same tokens `.cr-btn-save`
   uses. Removing this block simply lets that base rule (and the
   shared box-model rules) win under ADS Preview too, so every button
   with this class now renders pixel-identical to the canonical ADS
   Primary Button in every state (rest/hover/active/focus/disabled) —
   reusing the existing component instead of inventing a new
   "destructive" visual language. The class name `.cr-btn-danger-solid`
   is left as-is (renaming it is a larger, purely mechanical change
   across HTML/JS with no visual benefit — every consumer's loading-
   spinner wiring and JS `.classList` toggles key off this exact
   class name), but nothing about its rendered appearance is
   destructive/red any longer. Consumers: Remove Role, Remove
   application, Remove Member, Delete Team, Delete Permission Group,
   Set as Inactive, Change User — every one of them now renders as
   ADS Primary. */

/* ════════════════════════════════════════════════════════════════════
   ADS Preview · Pass-8 — Coverage polish from the May 30 audit.

   Three doubly-scoped fixes that the Part 3 audit surfaced as the only
   remaining ADS spec gaps inside this theme. Every rule below begins
   with [data-theme="ads-preview"]; nothing here can reach EDL Light or
   EDL Dark by CSS specificity. No HTML, no JS, no token authoring.

   Items intentionally NOT included in Pass-8 (held for product call):
     - Inline form error styling: ads-components.json publishes a Field
       validation sub-component, but no IAM screen ships inline error
       text yet. ads.mdc rule "tokens follow implementation" applies.
     - Edit User permission card radius (16): explicitly designed at
       16 in the project Figma (node 847:16382). ADS Card publishes 6.
       The brief blocks Edit User layout edits, so this stays at 16
       across all themes pending a design decision.
   ═══════════════════════════════════════════════════════════════════ */

/* ─── P8-A. Filter drawer close button — ADS Modal close anatomy ────
   The audit noted that the drawer Close (filter panel, scoped under
   .flt-close) had radius and target size aligned, but no hover or
   focus treatment under ADS. ads-components.json publishes Modal /
   Sheet close as "always neutral" with a hover wash via
   color/surface/recessed; ads.mdc reinforces this as a hard rule
   (close buttons are never status-tinted, in any variant).

   We add the missing hover wash and focus ring. Color stays neutral
   (we do not push brand or status), which is what ADS expects. */
[data-theme="ads-preview"] .flt-close {
  transition: background-color .12s ease, color .12s ease;
}
[data-theme="ads-preview"] .flt-close:hover {
  background: var(--ads-surface-recessed);
  color: var(--text-primary);
}
[data-theme="ads-preview"] .flt-close:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}

/* ─── P8-B. Dropdown option disabled state — ADS Dropdown spec ──────
   The audit noted that .cr-dd-option.is-disabled already had its
   hover background suppressed under ADS (Pass-5 §P5), but did not
   carry the matching ink and cursor that ads-components.json
   Dropdown publishes for the disabled option state (text/muted +
   cursor: not-allowed). Today this is a latent issue: no IAM
   screen ships a disabled option in the live data set, but the
   class can be applied at runtime by the access-level dropdown if
   a license tier reduces options. Closing the loop now keeps the
   theme self-consistent regardless of which option set ships. */
[data-theme="ads-preview"] .cr-dd-option.is-disabled {
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 1;
}

/* ─── P8-C. Edit User identity status icon — ADS Success token ──────
   The Basic Information block on the Edit User page renders a green
   check-circle SVG to signal an Active user. Inline markup ships
   stroke="#056C07" (EDL Green 70). ads-components.json names
   color/green/300 (#568E6D) as the success anchor under ADS v2.1.

   CSS overrides the inline SVG stroke attribute because presentation
   attributes have lowest CSS specificity; any matching CSS rule wins.
   Selector is doubly-scoped: ADS theme + .au-id-status descendant
   svg only. EDL Light / EDL Dark continue rendering #056C07 from
   the inline attribute. We reach through the existing --ads-green-300
   token declared at the top of this theme block (file ~3040), so we
   author no new token. */
[data-theme="ads-preview"] .au-id-status svg {
  stroke: var(--ads-green-300);
}


/* ═══════════════════════════════════════════════════════════════════════════
   IAM VERSION 4 (ADS) — standalone overrides, additive.

   V4 is a byte-identical fork of V3 whose HTML forces
   `<html data-theme="ads-preview" data-iam-version="v4">` on boot. Every
   existing token/selector in this stylesheet keeps working; the ADS
   Preview block above supplies the full ADS visual language.

   This block only carries the V4-specific *product* affordances that
   don't belong in the ADS Preview theme itself:
     1. Hide the Theme submenu (V4 is locked to ADS, so exposing a
        theme toggle would be misleading — clicking Light/Dark would
        appear to succeed for one paint but bootstrap re-forces
        ads-preview on the next load).
     2. Emit a subtle "V4 · ADS" chip next to the H1 so anyone
        comparing side-by-side can tell V3 from V4 at a glance.
     3. A small pass of ADS polish that ADS Preview under V3 did not
        need (V3 shipped as an opt-in preview; V4 is the default surface).

   Source of truth:
     • ADS DS component manifest — /Users/frances.sun/Downloads/ads-components.json
     • ADS DS design.md — brand hue Indigo, body Open Sans, display MultiplaneTWDC
     • Figma layout node 770-17443 — Users table with Filter / Internal-External /
       Search / Add Users toolbar and sortable header, indigo brand, opaque rows
     • Rate Card visual direction (for polish only — no product content leaks)

   All selectors below are scoped to [data-iam-version="v4"]. V3 renders
   the same file without this attribute and is unaffected.
   ─────────────────────────────────────────────────────────────────────── */

/* 1. Lock V4 to ADS by hiding the Theme submenu.
      V4's HTML bootstrap hard-sets data-theme="ads-preview" every
      pageload, ignoring localStorage. Exposing the toggle would let
      users click "EDL Light" and see a broken flash for one session
      before ADS reasserts on reload. Cleaner to remove the affordance
      entirely on V4. V3 continues to expose all three themes. */
[data-iam-version="v4"] #userMenuTheme,
[data-iam-version="v4"] #userMenuTheme + .user-menu-sep {
  display: none;
}

/* 2. V4 · ADS chip — a small pill inline with the page title so
      the version is visible without opening the user menu. Uses
      the ADS Indigo 50 brand-wash + Indigo 300 anchor already
      declared in the ADS Preview block, so no new token is
      authored. Positioned inline via inline-flex so it never
      wraps to its own line at the current desktop widths. */
[data-iam-version="v4"] .hdr {
  position: relative;
}
[data-iam-version="v4"] .hdr h1 {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
[data-iam-version="v4"] .hdr h1::after {
  content: "V4 · ADS";
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  font-family: 'Open Sans', var(--ff);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--ads-indigo-300, #4045C2);
  background: var(--ads-indigo-50, #E2E3F2);
  border: 1px solid var(--ads-indigo-100, #6567CE);
  border-radius: var(--ads-radius-pill, 100px);
  vertical-align: middle;
  -webkit-font-smoothing: antialiased;
}

/* 3. Small ADS polish beyond the V3 ads-preview theme. Each of these
      is a targeted refinement that a real production ADS surface
      would ship, but that V3's opt-in preview omitted (V3 kept
      diffs minimal to protect the EDL default). All rules are
      scoped to [data-iam-version="v4"] so V3 is untouched. */

/* 3a. Card surface — ADS DS Card publishes a hairline border on the
       elevation/low variant. V3 ads-preview kept the EDL card shadow
       to minimize visual diff; V4 elevates cards with the ADS
       hairline + a single soft shadow so tables feel like ADS
       "surface-chrome wrapper" cards, not floating panels. */
[data-iam-version="v4"] .card {
  border: 1px solid var(--border-default);
  box-shadow: var(--shadow-tip);
}

/* 3b. Sort arrows — REMOVED (2026-08-10, ADS sort-header audit).
       This rule set `color` on the sort SVG/wrapper, but the arrow
       paths use an explicit `fill` (not `fill: currentColor`), so it
       never actually painted anything — dead CSS masking the real
       icon-color bug (see the shared `.sort-dn`/`.sort-up` rules,
       which now carry the exact Figma-specified colors). */

/* 3c. Row hover — ADS DS Table publishes an opaque hover surface
       aliased to `color/surface/table/hover`. V3 ads-preview supplies
       a wash via --bg-hover-soft; V4 layers a subtle indigo tint so
       row hover reads as brand-family without becoming a "selected"
       state. Selected rows continue to use the brand-wash background
       supplied by the ADS Preview block. */
[data-iam-version="v4"] .tbl tbody tr:hover:not(.is-selected):not([aria-selected="true"]) {
  background: color-mix(in srgb, var(--ads-indigo-50) 45%, var(--bg-surface));
}

/* 3d. Primary action buttons — ADS DS Button publishes a subtle
       shadow on the primary variant to lift it off dense table
       toolbars. V3 ads-preview left the flat treatment; V4
       reintroduces the ADS elevation. */
[data-iam-version="v4"] .btn-primary,
[data-iam-version="v4"] .flt-btn-apply,
[data-iam-version="v4"] .cr-btn-save,
[data-iam-version="v4"] .au-btn-save {
  box-shadow: 0 1px 2px rgba(15, 18, 20, 0.14);
}
[data-iam-version="v4"] .btn-primary:hover,
[data-iam-version="v4"] .flt-btn-apply:hover,
[data-iam-version="v4"] .cr-btn-save:hover,
[data-iam-version="v4"] .au-btn-save:hover {
  box-shadow: 0 2px 6px rgba(15, 18, 20, 0.18);
}
[data-iam-version="v4"] .btn-primary:active,
[data-iam-version="v4"] .flt-btn-apply:active,
[data-iam-version="v4"] .cr-btn-save:active,
[data-iam-version="v4"] .au-btn-save:active {
  box-shadow: inset 0 1px 2px rgba(15, 18, 20, 0.12);
}

/* 3e. Section headers — ADS DS uses MultiplaneTWDC Display for
       heading anchors. V3 already routes .hdr h1 to the Display
       family; V4 extends this to the secondary section headers
       used on Edit User / Edit Role / Edit Team, so the whole
       stack reads consistently as ADS product typography. */
[data-iam-version="v4"] .cr-title,
[data-iam-version="v4"] .au-title,
[data-iam-version="v4"] .tm-title {
  font-family: 'MultiplaneTWDC Display', 'Open Sans', var(--ff);
  letter-spacing: -0.005em;
}

/* 3f. Nav — the ADS DS navigation component pairs Indigo 300 with
       tighter horizontal padding on the top-bar links. V3
       ads-preview supplies the color; V4 tightens the padding so
       the top nav reads at ADS product density (matches the Rate
       Card polish direction — cleaner, more enterprise). */
[data-iam-version="v4"] .nav-c .nav-a {
  padding-left: 12px;
  padding-right: 12px;
}

/* 3g. Pagination — ADS DS Pagination publishes `pagination/size/item`
       with a minimum-width of 36px on the digit variant (see
       ads-components.json note: "Digit variants HUG + minWidth 36
       for page 100+ breathing room"). V4 enforces the min-width so
       the numeric page cells maintain even rhythm regardless of
       digit count. */
[data-iam-version="v4"] .pgn .pgn-page,
[data-iam-version="v4"] .pgn .pg-nums button {
  min-width: 36px;
}

/* 3h. Focus ring — a single semantic focus pattern per the ADS DS
       global rule ("One semantic focus pattern; no per-component
       focus tokens.") V4 makes sure the ring is visible on every
       interactive element regardless of what V3 ads-preview
       covered. Uses the ADS Indigo 300 anchor and the ADS
       standard 2px ring + 2px offset. */
[data-iam-version="v4"] :focus-visible {
  outline: 2px solid var(--ads-indigo-300, #4045C2);
  outline-offset: 2px;
}

/* 3i. Chip/pill treatment for the "+N roles" affordance in the
       Users table Role column. ADS DS Chip publishes a filled
       indigo-brand-wash variant with Indigo 300 text; the Figma
       node 770:17443 renders this exactly. V3 ads-preview left
       the EDL treatment on this specific element. Restyle here. */
[data-iam-version="v4"] .role-extra {
  flex: 0 0 auto;
  background: var(--ads-indigo-50, #E2E3F2);
  color: var(--ads-indigo-300, #4045C2);
  border-radius: var(--ads-radius-pill, 100px);
  padding: 2px 8px;
  font-weight: 600;
}
[data-iam-version="v4"] .role-extra:hover {
  background: color-mix(in srgb, var(--ads-indigo-100, #6567CE) 22%, var(--ads-indigo-50, #E2E3F2));
  color: var(--ads-indigo-300, #4045C2);
}


/* ═══════════════════════════════════════════════════════════════════════════
   V4 — Round 33 refinement pass.

   Rigorous QA against Figma node 770-17443 and the ADS component manifest
   surfaced a small handful of remaining EDL leftovers plus polish gaps.
   Each item here has a documented Figma or ADS-JSON justification. Rules
   are scoped to [data-iam-version="v4"] so V3 stays byte-clean.

   Sources:
   • Figma 770:17443 metadata dump — header row 32px, data rows 48px,
     avatars 40x40, table columns Name 296 / Role 408 / Status 64 /
     Team 264 / Region 144, toolbar 16px symmetric padding
   • ads-components.json — Table (opaque rows, sticky-ready header
     underline), Chip (indigo wash + Indigo 300 text), Field (6px
     radius, 0.2-alpha border), Modal (18 tokens, neutral close),
     Accordion (Card wrapper, foreground-only hover, indigo trigger)
   • design.md — Green 300 = success, Red 300 = destructive
   ─────────────────────────────────────────────────────────────────────── */

/* R33-1. Display face for the page title.
   The ADS Preview block (line ~5015) intentionally routes .hdr h1 through
   `var(--ff)` (Open Sans) so V3's ADS preview could ship without the
   private Disney Multiplane face. V4 already carries the MultiplaneTWDC
   Display .woff2 in `public/assets/fonts/` and declares it via @font-face
   at the top of this stylesheet — so on V4 we can and should restore the
   real Disney display face on page titles for a true ADS product feel.
   Weight/size/line-height/tracking follow the ADS DS display slot:
   Medium (500), 30px, 36px line, -1% tracking. */
[data-iam-version="v4"] .hdr h1,
[data-iam-version="v4"] .cr-title,
[data-iam-version="v4"] .au-title {
  font-family: 'MultiplaneTWDC Display', 'Open Sans', var(--ff);
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* R33-2. Adjust the "V4 · ADS" chip vertical rhythm now that the H1
   uses MultiplaneTWDC at 500 weight. The 24px chip height sits cleanly
   on the 36px display cap so the chip and the title top-align to the
   same optical baseline. */
[data-iam-version="v4"] .hdr h1::after {
  height: 24px;
  padding: 0 12px;
  align-self: center;
  transform: translateY(1px); /* nudge to optical center of Multiplane cap */
}

/* R33-3. Status icons in the Users table — the icons ship as inline
   SVG with hardcoded EDL greens/reds (`fill="#056C07"` for Active,
   `fill="#D40909"` for Inactive). ADS DS names Green 300 (#568E6D)
   as the success anchor and Red 300 (#AF434E) as the destructive
   anchor (see the tokens declared at the top of the ADS Preview
   block). CSS `fill:` overrides the SVG presentation attribute, so
   we can remap without touching the JS render path. Selector uses
   the `data-status-tooltip` attribute which the JS always sets on
   the wrapper (renderStatusHtml in app.js). */
[data-iam-version="v4"] .status-icon-wrap[data-status-tooltip="Active"] svg path {
  fill: var(--ads-green-300, #568E6D);
}
[data-iam-version="v4"] .status-icon-wrap[data-status-tooltip="Inactive"] svg path {
  fill: var(--ads-red-300, #AF434E);
}

/* R33-4. Table header — bump weight and darken slightly for stronger
   scanability at ADS enterprise density. ADS DS Table row-header
   uses Gray 200 (#3B4347) at 12px/500 with a subtle 0.04em tracking.
   The 32px row height + 1px 0.2-alpha bottom border is already set
   by the ADS Preview block. */
[data-iam-version="v4"] .tbl thead th {
  color: var(--text-secondary);          /* Gray 200 #3B4347 */
  font-weight: 500;
  letter-spacing: 0.01em;
}
[data-iam-version="v4"] .tbl thead th[data-sort]:hover,
[data-iam-version="v4"] .tbl thead th[data-rp-sort]:hover,
[data-iam-version="v4"] .tbl thead th[data-tm-sort]:hover {
  color: var(--text-primary);
}

/* R33-5. Pagination current-page pill — the 0.5-alpha bold border was
   leftover from the neutral-focus token; on a filled indigo pill it
   reads as a stroke halo. ADS DS Pagination shows the selected item
   as a seamless filled brand pill (no stroke). Radius stays 8px per
   `pagination/size/item/radius`. */
[data-iam-version="v4"] .pgn .pg-nums button.on,
[data-iam-version="v4"] .pgn .pg-nums button[aria-current] {
  border: 1px solid transparent;
  box-shadow: 0 1px 2px rgba(15, 18, 20, 0.14);
}
[data-iam-version="v4"] .pgn .pg-nums button:not(.on):not([aria-current]):hover {
  background: var(--ads-indigo-50, #E2E3F2);
  color: var(--ads-indigo-300, #4045C2);
}

/* R33-6. Toolbar right-padding — V3 shipped .tbar with asymmetric
   padding (`8px 56px 8px 16px`) to leave clearance for a legacy
   secondary action. Figma 770:17443 shows 16px symmetric horizontal
   padding on the toolbar with the Add User button aligned to the
   card's right edge. Normalize on V4 so the primary CTA hugs the
   card's inner right rail like the Figma reference. */
[data-iam-version="v4"] .tbar {
  padding-right: 16px;
}

/* R33-7. Edit User / Edit Role / Edit Team inner cards — the outer
   .card on the users list already carries the ADS hairline (rule
   R32-3a above), but the inner .au-card / .cr-card / .tm-details-card
   fell back to the EDL card shadow-only treatment. ADS DS Card
   elevation/low = 1px 0.1-alpha border + 0 1px 4px 0.3-alpha shadow,
   so we restate the hairline explicitly. */
[data-iam-version="v4"] .au-card,
[data-iam-version="v4"] .cr-card,
[data-iam-version="v4"] .tm-details-card,
[data-iam-version="v4"] .tm-members-card {
  border: 1px solid var(--border-subtle);
  box-shadow: 0 1px 4px rgba(15, 18, 20, 0.06);
}

/* R33-8. Section header inside cards — .cr-section-header is the
   shared expand/collapse trigger used by Edit User, Edit Role, and
   Edit Team. ADS DS Accordion trigger spec: title + caret in brand
   (Indigo 300), foreground-only hover (title + caret shift to the
   hover indigo, no background wash — that's an explicit "don't" in
   ads-components.json). Padding uses spacing tokens comparable to
   the Card content padding so the trigger reads as part of the
   Card, not a separate row. */
[data-iam-version="v4"] .cr-section-header {
  transition: color .12s ease;
}
[data-iam-version="v4"] .cr-section-header .cr-section-title,
[data-iam-version="v4"] .cr-section-header .cr-section-chev {
  color: var(--ads-indigo-300, #4045C2);
  transition: color .12s ease;
}
[data-iam-version="v4"] .cr-section-header:hover .cr-section-title,
[data-iam-version="v4"] .cr-section-header:hover .cr-section-chev,
[data-iam-version="v4"] .cr-section-header:focus-visible .cr-section-title,
[data-iam-version="v4"] .cr-section-header:focus-visible .cr-section-chev {
  color: var(--ads-indigo-400, #3B3FBA);
  background: transparent;      /* ADS "don't" — no bg tint on hover */
}
[data-iam-version="v4"] .cr-section-header {
  background: transparent;
}

/* R33-9. Access table inside Edit User — the small effective-access
   table's header row was rendering at the same 400 weight as body
   text (very faint). Bring it up to the same ADS Table Header treatment
   used on the main Users table for consistency across the app.
   Selector matches the V3 declaration at line 6130 (2 IDs + 2 classes)
   so we tie on specificity and win on cascade order. */
[data-iam-version="v4"] #addUsersPage #auRolesCard .au-eff-tbl thead th {
  color: var(--text-secondary);
  font-weight: 500;
  letter-spacing: 0.01em;
  border-bottom: 1px solid var(--border-default);
}

/* R33-10. Form input focus — ADS DS Field / Input publishes a single
   semantic focus-ring pattern (2px indigo outline). The universal
   :focus-visible rule (R32-3h) covers keyboard focus; add a matching
   input-focus style to also handle mouse-focus on <input> where
   browsers may not fire :focus-visible under certain input methods. */
[data-iam-version="v4"] .cr-input:focus,
[data-iam-version="v4"] .cr-textarea:focus,
[data-iam-version="v4"] .au-input:focus,
[data-iam-version="v4"] .flt-input:focus,
[data-iam-version="v4"] .edl-combo-input:focus,
[data-iam-version="v4"] .flt-select:focus {
  border-color: var(--ads-indigo-300, #4045C2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ads-indigo-300, #4045C2) 18%, transparent);
  outline: none;
}

/* R33-11. Row cursor — clicking a user row's name-link navigates to
   Edit User. Reflect that affordance with a hand cursor on the
   entire clickable name area (Figma link semantics). */
[data-iam-version="v4"] #usersTable tbody tr .name-link,
[data-iam-version="v4"] #usersTable tbody tr a[data-uid],
[data-iam-version="v4"] #teamsTable tbody tr .name-link {
  cursor: pointer;
}

/* R33-12. Modal chrome — ADS DS Modal ships with a 12px border-radius
   (larger than Card's 6px per ads-components.json size scale) plus
   a stronger elevation/high shadow. V3 renders modals with the EDL
   default 8px radius. Under V4, restate the ADS chrome. Selectors
   cover the shared modal patterns used across Edit User / Edit Team
   / Edit Role: `.tm-add-modal`, `.au-eff-breakdown`, `.cr-confirm-dialog`. */
[data-iam-version="v4"] .tm-add-modal,
[data-iam-version="v4"] .au-eff-breakdown,
[data-iam-version="v4"] .cr-confirm-dialog,
[data-iam-version="v4"] .modal-panel,
[data-iam-version="v4"] .flt-panel {
  border-radius: var(--ads-radius-lg, 12px);
  box-shadow: 0 8px 24px rgba(15, 18, 20, 0.3), 0 1px 2px rgba(15, 18, 20, 0.3);
  border: 1px solid var(--border-subtle);
}

/* R33-13. Modal / dialog close buttons — ADS DS global rule (see
   ads-components.json globalRules.closeButtons): "Always neutral,
   never tinted by status." V3 tints some close buttons with brand;
   force neutral under V4 across every modal chrome we've defined. */
[data-iam-version="v4"] .tm-add-close,
[data-iam-version="v4"] .au-eff-close,
[data-iam-version="v4"] .cr-confirm-close,
[data-iam-version="v4"] .modal-close,
[data-iam-version="v4"] .flt-close {
  color: var(--text-secondary);
  background: transparent;
}
[data-iam-version="v4"] .tm-add-close:hover,
[data-iam-version="v4"] .au-eff-close:hover,
[data-iam-version="v4"] .cr-confirm-close:hover,
[data-iam-version="v4"] .modal-close:hover,
[data-iam-version="v4"] .flt-close:hover {
  background: rgba(15, 18, 20, 0.05);
  color: var(--text-primary);
}

/* R33-14. Toast — superseded by the full ADS Toast token block under
   "R52 — Toast" further down this file (exact Figma 70:62 values:
   6px radius, 5px semantic left border only, no all-round hairline,
   dismiss button tinted per variant to match the exported assets).
   Kept as a comment marker so this section number isn't silently
   reused. */

/* R33-15. Empty avatar treatment — internal users without a photo
   fall back to `.name-avatar` (a colored circle with initials).
   Existing rule (line 3765) sets background: --ads-violet-10; keep
   that but tighten to ADS Indigo 50 for consistency with the brand
   wash used everywhere else. Also lock the border-radius to 50%
   in case any inline style leaks through. */
[data-iam-version="v4"] .name-avatar {
  background: var(--ads-indigo-50, #E2E3F2);
  color: var(--ads-indigo-300, #4045C2);
  border-radius: 50%;
  font-weight: 600;
  font-size: 13px;
}

/* R33-16. Toggle Group (Internal / External) — ADS DS Toggle Group
   selected-state anchors to the brand-wash (Indigo 50) with Indigo 300
   text and a subtle 1px hairline on the parent container. The V3
   ads-preview theme delivers most of this; we tighten the transition
   and ensure the selected pill is inset by 2px inside the container
   so the outer border reads cleanly (rather than the pill touching
   the container edge). */
[data-iam-version="v4"] .seg-ctrl {
  padding: 1px;
  gap: 0;
}
[data-iam-version="v4"] .seg-btn {
  transition: background-color .12s ease, color .12s ease;
  border-radius: 5px;         /* -1 vs container 6px so the pill fits inside */
}
[data-iam-version="v4"] .seg-btn.on {
  box-shadow: 0 1px 2px rgba(15, 18, 20, 0.08);
}

/* R33-17. Filter button icon-label alignment — ADS DS Button ships
   with a 6px icon-to-label gap on the sm size; V3 renders the Filter
   icon flush against the label. Add the ADS gap so the icon reads
   as a separate glyph rather than a prefix. */
[data-iam-version="v4"] .tbar .btn-std {
  gap: 6px;
}

/* R33-18. Table cell text — ADS DS Table body ships at 14px/500 on
   primary text and 13px/400 on secondary. Body cells are already
   14px; tune the vertical rhythm on the Name cell so the two-line
   name-link + email reads with balanced leading.
   Selector matches the V3 declaration at line 647 (2 IDs + 1 tag +
   1 class) so we tie on specificity and win on cascade order. */
[data-iam-version="v4"] #usersPanel #usersTable tbody .name-link {
  font-weight: 500;
}
[data-iam-version="v4"] #usersTable tbody td.c-nm .name-email,
[data-iam-version="v4"] #usersTable tbody td.c-nm .row-email {
  font-size: 13px;
  color: var(--text-muted);
}

/* R33-19. Filter side panel — the ADS Preview block already restyles
   .flt-panel; V4 adds the ADS Modal chrome (radius+shadow) via R33-12
   and here tightens the section spacing so the panel reads as a
   modern ADS filter drawer rather than a raw form column. */
[data-iam-version="v4"] .flt-title {
  font-family: 'MultiplaneTWDC Display', 'Open Sans', var(--ff);
  font-weight: 500;
  letter-spacing: -0.005em;
}

/* R33-20. Nav bar height — Figma 770:17443 renders the ADS top bar
   at 48px height (see nav's `height: 48` in our audit). V3 shipped
   the nav at 64px height under EDL; the ads-preview theme scaled it
   down. Enforce the 48px height explicitly on V4 in case any late-
   loading rule (or window-height math) tries to expand it.
   NOTE: R34 (below) supersedes this and pushes the nav to 56px per
   the Q2C nav reference (Figma node 3606:53124). The 48px rule is
   left in the file for cascade documentation but is overridden. */
[data-iam-version="v4"] .nav {
  min-height: 48px;
}


/* ═══════════════════════════════════════════════════════════════════════════
   V4 — Round 34 — Top navigation bar: Q2C / ADS treatment.

   Source of truth (nav layout + tokens):
   • Figma node 3606:53124 — Q2C Design ATLAS Navigation
     https://www.figma.com/design/I616m31h1PZ5YlSYB2Hoe9/Q2C-Design-%E2%80%94-ATLAS?node-id=3606-53124
   • ads-components.json — TopBar + Icon tokens
   • design.md — Indigo 300 brand anchor, Open Sans body / Multiplane display

   Q2C nav spec (from the Figma metadata):
     • Container height    = 56px  (was 48px on V4)
     • Horizontal padding  = 24px  (was 32px on V4)
     • Background          = Indigo 300 #4045C2 (already correct)
     • Brand cluster (LEFT):
         • Vector 32×28 logo  ← we KEEP Marge's wordmark unchanged
         • "Disney Advertising" MultiplaneTWDC Display Bold 18/24 white
           (already baked into the current logo SVG — no new node)
         • 8px gap between icon and text (already correct in SVG)
     • Middle: two flex spacers — no product-nav in the Q2C reference
     • Utilities (RIGHT):
         • Bell    20×20  (was 15×17 — swapped in HTML for the Figma path)
         • Sparkle 20×20  (replaces the old three-dot "More" glyph)
         • Avatar  32×32  ← Marge Simpson avatar, kept unchanged
         • 16px gap between each utility (already correct)

   User carve-outs honored:
     • Marge Simpson W-logo wordmark stays byte-identical (../nav/logo.svg)
     • Marge Simpson avatar stays byte-identical (../nav/avatar.png)
     • The logo's visual size (145×26) is preserved; only the container
       height changed. Flex align-items:center keeps it visually centered.

   Product-nav strategy:
     The Q2C Figma reference contains NO center product nav — only
     brand + utilities. To match the layout, the .nav-c cluster is
     hidden on V4 (display:none). The DOM stays intact so V3 renders
     the product-nav normally under EDL.

   All selectors below are scoped to [data-iam-version="v4"] so V3
   remains byte-clean.
   ─────────────────────────────────────────────────────────────────────── */

/* R34-1. Container height + horizontal padding per Figma. Overrides the
   R33-20 48px rule above (later cascade + equal specificity wins).
   The right inset (24px) is measured directly off the utilities group
   in Figma node 1003:10545 and lines up exactly with this codebase's
   rendered bell/sparkle/avatar cluster already.

   LEFT inset is now 0 — the old 16px value here was a padding-based
   approximation of "(64 - 32) / 2 = 16" (centering the D-glyph on the
   64px-wide `.sidebar` rail by faking the rail's geometry with nav
   padding instead of building a real rail element). Final-QA
   (product-name horizontal position correction) replaced that hack
   with an actual `.atlas-brand-rail` box below, sized to the sidebar's
   own 64px width, so this padding would now double-count the inset —
   removed accordingly. */
[data-iam-version="v4"] .nav {
  min-height: 56px;
  height: 56px;
  padding: 0 24px 0 0;
  gap: 0;
  align-items: center;
}

/* R34-2. Hide the center product-nav.
   Q2C nav layout has brand LEFT + utilities RIGHT with only flex spacers
   between them. Sales/Planning/Ad Ops/Billing/Admin do not appear in the
   Figma reference and are hidden on V4. The DOM elements remain so any
   V3 CSS or JS references stay valid — they simply do not render on V4. */
[data-iam-version="v4"] .nav-c {
  display: none;
}

/* R34-3. Brand cluster — the wordmark image is preserved at its native
   size. Vertically center in the 56px container via flex (nav's
   align-items:center takes care of this). Left offset is now 24px
   (nav padding) instead of 32px per the Q2C reference. */
[data-iam-version="v4"] .nav-l {
  padding: 0;
  margin: 0;
}
[data-iam-version="v4"] .nav-logo-img {
  /* Locked width/height so the wordmark's visual identity never shifts,
     even if the surrounding container gets restyled again. */
  height: 26px;
  width: auto;
  display: block;
}

/* R34-4. Utilities cluster — the Q2C spec puts these on the far right
   with 16px gap between items. Existing V3/V4 CSS already applies
   16px gap; restate explicitly so any downstream override doesn't
   break the rhythm. */
[data-iam-version="v4"] .nav-r {
  gap: 16px;
  padding: 0;
  margin-left: auto; /* pushes cluster to the right rail per Figma spacers */
}

/* R34-5. Utility buttons — 40×40 hit target with a centered 20×20 icon.
   The Figma vector containers are 20×20 (just the icon), but we keep
   the surrounding 40×40 hit target for WCAG 2.5.5 (target size).
   Icon color inherits from the nav's white text, which is already set
   in the ADS Preview block. */
[data-iam-version="v4"] .nav-r .nav-r-btn {
  width: 40px;
  height: 40px;
  padding: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: transparent;
  color: #FFFFFF;
  border: 0;
  transition: background-color .12s ease;
}
[data-iam-version="v4"] .nav-r .nav-r-btn .nav-ico {
  width: 20px;
  height: 20px;
  display: block;
}
[data-iam-version="v4"] .nav-r .nav-r-btn:hover {
  background: rgba(255, 255, 255, 0.12);
}
[data-iam-version="v4"] .nav-r .nav-r-btn:active {
  background: rgba(255, 255, 255, 0.18);
}
[data-iam-version="v4"] .nav-r .nav-r-btn:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
  background: rgba(255, 255, 255, 0.12);
}

/* R34-6. Avatar — Marge Simpson's photo is kept at exactly 32×32 per
   the Figma reference AND the user's explicit "do not resize" carve-out.
   The 40×40 button around it is unchanged from V3 (accessibility hit
   target). We only tune the img's on-screen size, not the wrapper. */
[data-iam-version="v4"] #userMenuTrigger {
  width: 40px;
  height: 40px;
  padding: 0;
}
[data-iam-version="v4"] .nav-avatar-img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: block;
  object-fit: cover;
}

/* R34-7. Legacy nav divider spacer (`.nav-divider`) — the V3 nav ships
   a small vertical rule between the logo group and the module label
   under EDL. The Q2C reference has no such divider; hide it on V4. */
[data-iam-version="v4"] .nav-divider {
  display: none;
}

/* R34-8. Legacy EDL bell <img> is hidden on V4 in favor of the inline
   SVG (which now uses the Figma Q2C path at native 20×20). Restate the
   hide rule explicitly with V4 specificity so it doesn't rely on the
   older ads-preview theme block. */
[data-iam-version="v4"] .nav-bell-img {
  display: none;
}

/* R34-9. Ensure the V4 · ADS chip on the page-body H1 stays a chip and
   never leaks into the nav bar. Guardrail — no functional change under
   normal renders, but blocks any future accidental nav ::after chip. */
[data-iam-version="v4"] .nav::after,
[data-iam-version="v4"] .nav::before {
  content: none;
}

/* R34-10. Page body offset — no change needed. The .nav sits above
   `<main class="page">` which has `padding-top: 0` and no fixed
   positioning. Bumping the nav from 48 → 56px shifts the whole page
   down by 8px, which is exactly the desired outcome (page body
   itself is untouched per the "nav bar only" scope). */

/* R58. Responsive content-container model — fixes the "empty right
   side at 1920/2560" regression. `main.page` (above) intentionally has
   `max-width: none` so its *padding* can encode the sidebar offset;
   that leaves the actual growth-and-centering job to its direct list
   card. Below ~1888px available content width (1920 viewport minus
   the collapsed-sidebar gutters) the card just fills 100% of
   `main.page`'s content box, so it grows continuously from 1024 up
   through 1440 and 1920 with no artificial ceiling. Only once the
   *available* width exceeds `--v4-content-max-width` (2560-class
   viewports and wider) does growth stop and the leftover space
   resolve into equal left/right whitespace via `margin-inline: auto`
   — i.e. centered *within the content region to the right of the
   fixed sidebar*, not the full browser viewport (a fixed sidebar is
   not a "gutter" and is intentionally excluded from that centering).

   1920px was chosen as the max because the ADS pilot itself only
   commits to two desktop targets — 1440px and 1920px (see
   `ads-design-system/design.md`, "Pilot constraint") — so 1920px is
   the largest width the table/typography/column system was actually
   designed against. Beyond it we hold the line rather than inventing
   an undesigned, arbitrarily-wider table.

   This must resolve to a *single* declaration for `main.page > .card`
   in the whole file — a second, later rule that re-sets `max-width`
   on `main.page` itself previously undid the `max-width: none` above
   by cascade order (same selector, same specificity, declared later
   wins) and was the actual root cause of the bug; see R58 note by
   the `background: transparent` header-band rule further down. */
html[data-iam-version="v4"] main.page > .card {
  width: 100%;
  max-width: var(--v4-content-max-width, 1920px);
  margin-inline: auto;
}

/* ═══════════════════════════════════════════════════════════════════
   R39 — ATLAS brand composition parity (V4 only)

   Figma reference: Q2C-Design — ATLAS
     • file: I616m31h1PZ5YlSYB2Hoe9
     • navigation node:      3606:53124  (56×1440, bg #4045c2)
     • brand cluster node:   3606:51560  (gap 8, 32×28 glyph + text)
     • D-glyph vector:       3606:51561  (32×28, `imgVector`)
     • "Disney Advertising": 3606:51562  (MultiplaneTWDC Display Bold 18/24 white)

   R34 already delivered the container geometry (height 56, padding
   0 24, bg #4045c2), utility buttons (40×40 hit target, 20×20 icons),
   Marge avatar (32×32 preserved), and the hidden `.nav-c` product-
   nav. The remaining drift was the BRAND composition: the .nav-mod
   wrapper still carried an EDL padding-left of 48px, which offset
   the logo to ~72px from the viewport edge (24 + 48). The Figma
   spec starts the D-glyph at exactly 24px (nav's padding), followed
   by the MultiplaneTWDC "Disney Advertising" wordmark 8px later.

   This block:
     • zeroes .nav-mod / .nav-logo-group / .nav-logo-link padding
     • lays the D-glyph + text on a flex track with 8px gap
     • sizes the glyph to Figma's exact 32×28 and paints it white
     • renders the text in MultiplaneTWDC Display 18/24 (weight 500,
       the only Multiplane weight shipped in /assets/fonts — 500
       reads visually equivalent to Figma's 700 given the small
       size and the white-on-indigo contrast; documenting the
       trade-off here in case the Bold woff2 becomes available)

   All rules are scoped to `html[data-iam-version="v4"]` so V1/V2/V3
   remain visually untouched (they still ship their own logo.svg
   wordmark via the base .nav-logo-img rule). */

/* R39-1. Strip residual EDL padding off the brand-cluster ancestors
   so the D-glyph sits at exactly 24px from the viewport edge. Higher
   specificity than the base `.nav-mod { padding: 10px 16px 10px 48px }`
   at line 208. */
html[data-iam-version="v4"] .nav-mod {
  padding: 0;
  gap: 0;
  height: 100%;
  align-items: center;
}
html[data-iam-version="v4"] .nav-logo-group {
  padding: 0;
  gap: 0;
  height: 100%;
  align-items: center;
}
html[data-iam-version="v4"] .nav-logo-link {
  padding: 0;
  margin: 0;
  height: 100%;
  align-items: center;
}

/* R53. Brand-lockup gap tightening (Ad Console moved closer to logo) —
   the shared wrapper for the two brand pieces (`.atlas-brand-rail` +
   `.atlas-brand-text`). R52 first collapsed a two-place 32px-effective
   gap down to one real flex `gap: 12px` (see its comment below, still
   accurate history-wise). This pass tightens that single gap further,
   from 12px to the exact 8px Figma originally specified for the brand
   cluster (node 3606:51560, "gap 8" — see the R39 header comment
   above). `flex-wrap: nowrap` is explicit (not just the flex default)
   so the lockup can never wrap onto two lines regardless of viewport.
   This remains the ONLY rule in the codebase that sets this gap — no
   page-level override, no per-breakpoint value (R39-6 below only
   resizes the text's font-size at ≤768px, never this gap) — so every
   V4 page renders the identical 8px lockup automatically. */
html[data-iam-version="v4"] .atlas-brand {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 8px;
  color: #ffffff;
  text-decoration: none;
  line-height: 1;
  border-radius: 4px;
}
html[data-iam-version="v4"] .atlas-brand:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 3px;
}

/* R39-2a. Logo rail — Final-QA (product-name horizontal position
   correction). Previously the D-glyph's centering on the left-nav's
   64px rail column was faked with asymmetric `.nav` padding (`16px`
   left vs `24px` right, see R34-1's old comment) and the product name
   sat a flat 8px after the glyph itself — which put "Ad Console"'s
   left edge at viewport x=56, i.e. INSIDE the 64px rail column instead
   of clear of it.

   This box is a real rail matching `.sidebar`'s own 64px width
   (`.nav`'s own left padding is now 0, see R34-1), so the D-glyph
   centers inside it exactly where it already rendered before —
   `(64 - 32) / 2 = 16`, unchanged, per the "do not move the logo"
   constraint — while now being an actual structural column instead of
   a padding approximation. The product name (R39-2b) is a sibling
   positioned AFTER this rail's right edge, not after the glyph. */
html[data-iam-version="v4"] .atlas-brand-rail {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 100%;
  flex-shrink: 0;
}

/* R39-3. D-glyph — Figma renders it at 32×28 in WHITE on the indigo
   bar. Because R40 inlines the SVG element (was <img> in R39, which
   isolated the SVG from CSS color inheritance and rendered the
   glyph in the browser default black), the parent's `color: #fff`
   now cascades into `<svg fill="currentColor">` and paints the
   path white. Explicit `fill: #ffffff` also set on the .path
   selector below as a defensive belt-and-suspenders in case the
   `fill` attribute is dropped by future refactors. */
html[data-iam-version="v4"] .atlas-brand-glyph {
  display: block;
  width: 32px;
  height: 28px;
  flex-shrink: 0;
  color: #ffffff;
  fill: currentColor;
}
html[data-iam-version="v4"] .atlas-brand-glyph path {
  fill: currentColor;
}

/* R39-4. Wordmark — MultiplaneTWDC Display 18/24 white. Figma spec
   is weight 700; the /assets/fonts folder ships only the Medium
   woff2 (500), and browsers will substitute Medium for 500 requests
   cleanly (any synthetic bold looks blurred against the tiny 18px
   x-height, so we don't force it). The text is uppercase-free —
   preserves the "Disney Advertising" case exactly from Figma.

   R52: the old `margin-left: 16px` (superseded R39-2b) is removed —
   spacing now comes entirely from `.atlas-brand`'s own `gap: 12px`
   above, so there is exactly one source of truth for the logo↔text
   gap instead of a margin stacked on a fixed rail width. */
html[data-iam-version="v4"] .atlas-brand-text {
  font-family: 'MultiplaneTWDC Display', 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 18px;
  line-height: 24px;
  color: #ffffff;
  letter-spacing: 0;
  white-space: nowrap;
  display: inline-block;
}

/* R39-5. Neutralize the legacy `.nav-logo-img` sizing on V4 so any
   future/stale reference to that class can't apply the 145×26
   wordmark dimensions to a 32×28 glyph. `.atlas-brand-glyph`'s
   fixed dimensions win on the current markup, but this is a
   defensive rule for any future stylesheet reordering. */
html[data-iam-version="v4"] .atlas-brand .atlas-brand-glyph.nav-logo-img,
html[data-iam-version="v4"] .atlas-brand .nav-logo-img {
  width: 32px;
  height: 28px;
}

/* R39-6. Responsive parity — the brand text never wraps or clips,
   even at narrower viewports. The R34 nav padding already reduces
   at ≤1024/≤768, but the brand cluster's own gap and glyph size
   stay pinned to the Figma spec. */
@media (max-width: 768px) {
  html[data-iam-version="v4"] .atlas-brand-text { font-size: 16px; line-height: 22px; }
}

/* ═══════════════════════════════════════════════════════════════════
   R38 — IAM table card parity with Rate Card Manager (V4 only)

   Wraps the tabs row + all three panels (Users/Roles/Teams) into a
   single elevated white "table card" that visually matches the Rate
   Card Manager table treatment. This is a container-level parity fix
   only — every internal element (tabs, toolbar controls, table rows,
   pagination) keeps its existing content, layout, columns, sort
   logic, and JS behavior. What changes:

     • Outer surface  → white card, 16px radius, subtle box-shadow,
                        hairline border, overflow:hidden so all four
                        corners clip cleanly.
     • Page canvas    → unchanged; ADS Ink 05 (#ECEEEE) already reads
                        as the Rate Card gray canvas behind the card.
     • Tabs row       → seats at top of card, hairline underline as
                        divider before the toolbar (was already there,
                        now sits inside the rounded frame).
     • Toolbar        → drops its 16px external bottom margin; picks
                        up 16px 20px internal padding so filter /
                        segmented / search / Add User buttons sit on
                        the card's inner grid.
     • Table body     → unchanged density (32px thead, 48-64px rows);
                        removes the residual outer horizontal padding
                        that pushed cells past the card edges.
     • Pagination     → gains a 1px top divider and 12px 20px padding,
                        inherits the card's rounded bottom corners
                        automatically via overflow:hidden.

   The card is scoped to V4 only (`html[data-iam-version="v4"]`), so
   V1/V2/V3 remain visually untouched. The `.v4-card` wrapper element
   was added in index.html (R38); no other JS/HTML behavior changed. */

/* R38-1. Card container. Uses higher specificity than the base
   `#usersPanel { padding-top: 12px }` so the residual padding is
   removed and the tabs row sits flush with the card's top edge. */
html[data-iam-version="v4"] .v4-card {
  background: #ffffff;
  border: 1px solid rgba(15, 18, 20, 0.08);
  border-radius: 16px;
  box-shadow:
    0 1px 2px rgba(15, 18, 20, 0.04),
    0 4px 12px rgba(15, 18, 20, 0.06);
  overflow: hidden;
  margin: 4px 0 24px;
}

/* R38-2. Tabs row inside the card — flush to top, gray hairline
   underline separates tabs from the toolbar. The base rule already
   provides border-bottom + padding; we only override the padding to
   sit on the card's inner 20px grid and drop the 8px right/bottom
   asymmetry from the pre-card layout. */
html[data-iam-version="v4"] .v4-card .tabs-row {
  padding: 12px 20px 0;
  border-bottom: 1px solid rgba(15, 18, 20, 0.1);
  background: #ffffff;
}

/* R38-3. Panel wrappers drop their top padding (the card already
   gives internal chrome its rhythm via the tabs-row + tbar padding). */
html[data-iam-version="v4"] .v4-card #usersPanel,
html[data-iam-version="v4"] .v4-card #rolesPanel,
html[data-iam-version="v4"] .v4-card #teamsPanel {
  padding-top: 0;
}

/* R38-4. Toolbar — internal 16px vertical / 20px horizontal padding,
   drops the pre-card bottom margin so the table butts up cleanly
   against the underlying divider. Height auto so wrapped controls
   don't clip when the page is narrower than 1280px. */
html[data-iam-version="v4"] .v4-card .tbar {
  padding: 16px 20px;
  margin-bottom: 0;
  height: auto;
  min-height: 56px;
  background: #ffffff;
}
/* Base rule sets `#usersPanel .tbar { margin-bottom: 10px }` — reset. */
html[data-iam-version="v4"] .v4-card #usersPanel .tbar { margin-bottom: 0; }

/* R38-5. Table wrapper — no extra horizontal padding, keep h-scroll. */
html[data-iam-version="v4"] .v4-card .tbl-wrap {
  padding: 0;
  background: #ffffff;
}

/* R38-6 (superseded — Figma final-QA, node 1003:17844/1003:17845-51,
   "Data Table / Example Row Header"): Dev Mode shows `bg-white` on the
   header row with a single hairline `border-b border-[#d4dee3]` — no
   gray tint and no border-top. The previous #FAFAFB "Rate Card" tint
   was an approximation from an earlier pass; this exact node overrides
   it. Border moves to `th` (not `tr`) because table row borders are
   not reliably painted by browsers — the divider must live on the
   cell to guarantee a single, visible header/body divider. */
html[data-iam-version="v4"] .v4-card .tbl thead tr {
  background: var(--iam-ads-surface);
}
html[data-iam-version="v4"] .v4-card .tbl thead th {
  background: var(--iam-ads-surface);
  border-bottom: 1px solid var(--iam-ads-divider);
}

/* R38-7. Pagination footer — 1px top divider, 12px vertical / 20px
   horizontal padding. Rounded bottom corners inherit from `.v4-card
   { overflow: hidden; border-radius: 16px }` on the parent, so no
   explicit radius needed here. */
html[data-iam-version="v4"] .v4-card .pgn {
  padding: 12px 20px;
  height: auto;
  min-height: 48px;
  border-top: 1px solid rgba(15, 18, 20, 0.08);
  background: #ffffff;
}

/* R38-8. Bottom edge of the card — make sure the last block inside
   the card (whichever panel is active) doesn't add trailing space.
   The panels themselves have no bottom margin, but the pagination
   already sits at the bottom of each panel, so this is a safety
   guard for future panel additions. */
html[data-iam-version="v4"] .v4-card > div:last-child { margin-bottom: 0; }

/* R38-9. Responsive parity — narrower viewports keep the card's
   internal padding proportional (base tbar/pgn rules already reduce
   horizontal padding at 1280/1024/768; we only need to keep them
   in sync with the card's 20px inner grid). */
@media (max-width: 1024px) {
  html[data-iam-version="v4"] .v4-card .tabs-row { padding-left: 16px; padding-right: 16px; }
  html[data-iam-version="v4"] .v4-card .tbar     { padding: 12px 16px; }
  html[data-iam-version="v4"] .v4-card .pgn      { padding: 10px 16px; }
}
@media (max-width: 768px) {
  html[data-iam-version="v4"] .v4-card { border-radius: 12px; }
  html[data-iam-version="v4"] .v4-card .tabs-row { padding-left: 12px; padding-right: 12px; }
  html[data-iam-version="v4"] .v4-card .tbar     { padding: 10px 12px; }
  html[data-iam-version="v4"] .v4-card .pgn      { padding: 8px 12px; }
}

/* ═══════════════════════════════════════════════════════════════════
   R37 — ATLAS nav parity pass (V4 only)

   Figma reference: Q2C-Design — ATLAS
     • file: I616m31h1PZ5YlSYB2Hoe9
     • top nav node: 3606:53124  (56×1440, bg #4045c2)

   The R34+R36 stack already delivers pixel parity for the top nav
   (56px height, 24px horizontal padding, #4045c2 background from
   `--ads-surface-brand`, 8px brand-cluster gap, 16px utilities gap,
   20×20 icons, 32×32 avatar). No CSS change needed for the top nav
   in this round — only the sidebar item list was rebuilt in HTML.

   The R35/R36 sidebar CSS is agnostic to the number of items and
   which item is active — it keys off `.sb-item` and the `sb-item-
   active` / `data-active="true"` markers. R37's HTML swap therefore
   inherits every existing token: 240 open / 62 collapsed, 40px item
   height, 20×20 icons, 6px radius, #e2e3f2 active bg, #4045c2 active
   text/indicator, Open Sans font stack, exact Figma padding.

   Item mapping (R36 → R37):
     • R36 Orders     → R37 Orders      (icon unchanged: shopping-bag-open)
     • R36 Inventory  → R37 Inventory   (icon unchanged: tray)
     • R36 Targeting  → R37 Targeting   (icon unchanged: briefcase-metal)
     • R36 Rate Card  → R37 Pricing     (icon unchanged: tag)
     • R36 Finance    → R37 Invoices    (icon unchanged: invoice)
     • R36 Identity   → R37 Identity    (still ACTIVE, still user-list)
     • R36 Settings   → R37 Settings    (icon unchanged: gear-fine)
     • (new)          → R37 Dashboard   (Phosphor squares-four, at top)

   Net result: same visual system, 8 items instead of 7, ATLAS naming.
   All CSS declarations for R37 live in the R35 / R36 blocks above. */


/* ═══════════════════════════════════════════════════════════════════════════
   V4 — Round 46 — Rate Card visual-parity pass (Access Management)

   Objective: make Access Management visually indistinguishable from
   Rate Card at the design-system level while preserving every AM
   feature (tabs, Internal/External toggle, Add User, sort/filter,
   pagination totals, first/last nav, avatars, chips, status icons)
   and keeping Identity as the active left-nav item.

   Scope: strictly additive, scoped to [data-iam-version="v4"]. Every
   rule below is a small delta on top of R33/R34/R35/R36/R37/R38 — no
   product content changes, no route changes, no data changes.

   Sources of truth for the deltas:
     • Rate Card canonical render (screenshot, localhost:8001) — the
       shared ADS sibling used as the visual reference.
     • ads-components.json (v2.1) — Card, Button, Search, Field, Tab,
       Pagination, Chip token shapes.
     • design.md — Indigo brand, Open Sans body / Multiplane display.

   R46-1. Drop the "V4 · ADS" chip.
   R38 introduced a small brand-wash pill next to the page H1 so the
   version was obvious side-by-side with V3. Rate Card has no version
   chip; matching that surface means suppressing this ::after chip.
   The chip is authored via `content: "V4 · ADS"` on `.hdr h1::after`
   at R32-3 (line ~8195) and re-tuned at R33-2 (line ~8374). Neither
   supplies a display:none pathway, so we clear it here.
   ─────────────────────────────────────────────────────────────────── */
[data-iam-version="v4"] .hdr h1::after {
  content: none !important;
  display: none !important;
}
/* Restore the H1 to a plain title (drops the inline-flex + gap that
   only existed to accommodate the chip). Multiplane display face,
   500 weight, tightened tracking already come from R33-1. */
[data-iam-version="v4"] .hdr h1 {
  display: block;
  gap: 0;
  flex-wrap: nowrap;
}

/* R46-2. Flatten the nested card surfaces.
   The V3 markup wraps the tabs/toolbar/table/pagination in `.card`
   (the EDL container). V4/R38 added a `.v4-card` inside that same
   `.card` to supply the Rate-Card-style rounded frame. Both surfaces
   currently render border + shadow + radius, producing a subtle
   double-frame at the corners (outer 8px, inner 16px).

   Solution: when a `.v4-card` is present, neutralize the outer
   `.card` chrome so only the inner card paints the surface. This
   keeps the DOM byte-clean and applies exclusively where the
   `.v4-card` wrapper is used (the Access Management list surface). */
[data-iam-version="v4"] .card:has(> .v4-card) {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
  margin-bottom: 0;
}

/* R46-3. Card radius parity.
   Rate Card's table card uses a mid-scale radius, not the Modal
   scale. R38-1 set the inner wrapper to 16px (Modal-scale); Rate
   Card renders closer to 12px (`radius/lg`). Bring V4 down to 12px
   for parity. Corners inherit through overflow:hidden to the tabs
   row (top) and pagination footer (bottom) automatically. */
html[data-iam-version="v4"] .v4-card {
  border-radius: 12px;
}

/* R46-4. Page rhythm.
   Rate Card places the page header on a comfortable 32px cushion
   above the card, with a tight 4-6px gap between the display title
   and the secondary subtitle. R32-based `.hdr { padding: 29px 0 33px }`
   and the `.hdr h1 { margin-bottom: 8px }` from the base sheet are
   both close; tighten the title→subtitle gap slightly and normalize
   header→card spacing so the card sits at the same optical distance
   as Rate Card. Scoped to V4 so V3 stays untouched. */
[data-iam-version="v4"] .hdr {
  padding: 32px 0 24px;
}
[data-iam-version="v4"] .hdr h1 {
  margin-bottom: 4px;
}

/* R46-5. Filter button — parity with Rate Card's Filter chip.
   Rate Card's Filter button reads as a light indigo-wash chip
   (`background: --ads-indigo-50`) with `--ads-indigo-300` icon +
   label at 32px height and 8px radius. V4's base `.btn-std` sets
   the outline treatment; the wash variant here is the ADS "tonal
   secondary" pattern used for tertiary filters. */
[data-iam-version="v4"] .v4-card .tbar .btn-std {
  background: var(--ads-indigo-50, #E2E3F2);
  border-color: transparent;
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .tbar .btn-std:hover {
  background: color-mix(in srgb, var(--ads-indigo-100, #6567CE) 22%, var(--ads-indigo-50, #E2E3F2));
  border-color: transparent;
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .tbar .btn-std:focus-visible {
  outline: 2px solid var(--ads-indigo-300, #4045C2);
  outline-offset: 2px;
}
/* Icon inherits currentColor so it always tracks the indigo label. */
[data-iam-version="v4"] .v4-card .tbar .btn-std svg {
  color: currentColor;
}

/* R46-6. Add User primary button — parity with Rate Card's "Create
   rate card" indigo primary. V4 renders Add User via `.btn-ghost`
   (V3 markup carry-over — the class name is legacy, the visual
   should be a solid primary). Restate the primary treatment here
   without touching V3.

   Radius 8px (matches ADS Button md size), height 32px, indigo bg
   from Indigo 300, white label + icon, subtle 1px shadow that
   lifts it above the toolbar surface. */
[data-iam-version="v4"] .v4-card .tbar .btn-ghost {
  height: 32px;
  padding: 0 14px;
  border-radius: 8px;
  background: var(--ads-indigo-300, #4045C2);
  color: #ffffff;
  border: 1px solid var(--ads-indigo-300, #4045C2);
  box-shadow: 0 1px 2px rgba(15, 18, 20, 0.14);
  transition: background-color .12s ease, box-shadow .12s ease, border-color .12s ease;
}
[data-iam-version="v4"] .v4-card .tbar .btn-ghost:hover {
  background: var(--ads-indigo-400, #3B3FBA);
  border-color: var(--ads-indigo-400, #3B3FBA);
  color: #ffffff;
  box-shadow: 0 2px 6px rgba(15, 18, 20, 0.18);
}
[data-iam-version="v4"] .v4-card .tbar .btn-ghost:active {
  background: var(--ads-indigo-500, #2E32A5, #333697);
  color: #ffffff;
  box-shadow: inset 0 1px 2px rgba(15, 18, 20, 0.12);
}
[data-iam-version="v4"] .v4-card .tbar .btn-ghost:focus-visible {
  outline: 2px solid var(--ads-indigo-300, #4045C2);
  outline-offset: 2px;
}
[data-iam-version="v4"] .v4-card .tbar .btn-ghost svg {
  color: currentColor;
}

/* R46-7. Search input — parity with Rate Card's search field.
   Rate Card renders the search input as a full white field with a
   leading magnifier icon and the placeholder in Gray 200. V4's
   base sheet places the icon on the RIGHT — swap to the leading
   position under V4 for Rate-Card parity while preserving JS
   selectors (icon element stays in the same DOM position; only its
   `left` / `right` coordinates change). */
[data-iam-version="v4"] .v4-card .tbar .search {
  width: 360px;
}
[data-iam-version="v4"] .v4-card .tbar .search input {
  height: 32px;
  padding: 0 12px 0 36px;
  border-radius: 8px;
  border: 1px solid var(--border-input, rgba(15, 18, 20, 0.2));
  background: #ffffff;
  font-size: 14px;
  line-height: 20px;
}
[data-iam-version="v4"] .v4-card .tbar .search .search-ico {
  left: 12px;
  right: auto;
  color: var(--text-secondary);
  stroke: currentColor;
}
[data-iam-version="v4"] .v4-card .tbar .search .search-clear {
  right: 8px;
}

/* R46-8. Segmented control (Internal / External).
   Final-QA correction, inspected directly against Figma Dev Mode node
   1003:17834 ("Toggle Group" / ADS Toggle Group component) — every
   value below is a measured node property, not an approximation:
     • Outer "Toggle Group": 180×44 total, 4px padding on all sides,
       6px radius, track background rgba(15,18,20,0.05) (a neutral
       black-wash, NOT the opaque --iam-ads-canvas #f3f3f3 used
       elsewhere), NO border/stroke.
     • Each "Toggle Group Item": 86×36 (0 gap between the two items —
       differentiated purely by background, not a divider), 16px/8px
       padding-x/y, 6px radius (same as outer), 6px internal gap
       (unused here — no leading icon on Internal/External).
     • Selected item ("Internal" in the reference): white background,
       drop-shadow 0px 1px 1.5px rgba(15,18,20,0.3), text Open Sans
       SemiBold 14px/20px #1e2528 (--iam-ads-text).
     • Unselected item ("External"): transparent background, text Open
       Sans Regular 14px/20px #3b4347 (--iam-ads-text-secondary).
   `flex:1` on each item (below) keeps the two segments equal-width —
   matching the node's own 86/86 split — and keeps the control's own
   footprint stable when the selection toggles, instead of letting the
   heavier SemiBold label subtly resize its segment. The control's
   overall size still comes from its own content + padding (not
   stretched by the toolbar), so it cannot grow wider than Figma. */
[data-iam-version="v4"] .v4-card .tbar .seg-ctrl {
  height: 44px;
  /* Base `.seg-ctrl` (shared with V1-V3) sets `margin-left: 8px`,
     which was stacking on top of `.tbar-l`'s own 12px flex `gap` and
     pushing the Filter→Internal/External gap to 20px instead of the
     same 12px rhythm used for Internal/External→Search. Zeroing it
     here lets `.tbar-l`'s gap alone govern spacing on both sides. */
  margin-left: 0;
  display: flex;
  align-items: stretch;
  border-radius: 6px;
  padding: 4px;
  border: 0;
  background: rgba(15, 18, 20, 0.05);
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn {
  flex: 1 1 0;
  /* The shared base `.seg-btn` rule (used by V1-V3's segmented
     controls) sets `min-width: 96px`, which was silently padding this
     control out to 200px total (96×2 + 2×4px) — 20px wider than
     Figma's measured 180px (86×2 + 2×4px). Overriding to `auto` here
     lets each segment size to its own 16px-padding + text content,
     matching the node exactly (both labels render ~54px wide at this
     font, so 16+54+16 = 86px either way — Figma's own two segments
     independently land on the same width, not by a forced min-width). */
  min-width: 0;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: 6px;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  border: 0;
  background: transparent;
  color: var(--iam-ads-text-secondary, #3b4347);
  white-space: nowrap;
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn:not(.on):hover {
  color: var(--iam-ads-text, #1e2528);
  background: rgba(15, 18, 20, 0.04);
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn.on {
  background: var(--iam-ads-surface, #ffffff);
  color: var(--iam-ads-text, #1e2528);
  font-weight: 600;
  box-shadow: 0 1px 1.5px rgba(15, 18, 20, 0.3);
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn.on:hover {
  background: var(--iam-ads-surface, #ffffff);
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
  z-index: 1;
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn + .seg-btn {
  border-left: 0;
}

/* R46-9. Tabs — parity polish.
   V4 base sheet renders `.tab-btn` at 18px/800 (very bold). The
   Rate Card / ADS tab pattern uses 14px/600 with a 2px indigo
   underline on the selected tab. Under V4 only, restyle the tabs
   inside the .v4-card so the tab-row reads as an ADS TopBarTab
   rather than an EDL heading. */
[data-iam-version="v4"] .v4-card .tabs-row {
  height: 44px;
  padding: 0 20px;
  align-items: stretch;
  border-bottom: 1px solid rgba(15, 18, 20, 0.08);
}
[data-iam-version="v4"] .v4-card .tabs-row nav {
  gap: 20px;
  align-items: stretch;
  height: 100%;
}
[data-iam-version="v4"] .v4-card .tab-btn {
  height: 44px;
  padding: 0 4px;
  align-items: center;
  font-family: 'Open Sans', var(--ff);
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  letter-spacing: 0;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
}
[data-iam-version="v4"] .v4-card .tab-btn:hover:not(.on) {
  color: var(--text-primary);
}
[data-iam-version="v4"] .v4-card .tab-btn.on {
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .tab-btn.on::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--ads-indigo-300, #4045C2);
  border-radius: 1px;
}

/* R46-10. Pagination page-cell parity.
   Rate Card renders numeric page cells as 32×32 squares (8px radius
   base, filled indigo when selected). R33-5 set the selected pill
   correctly; here we restate the base cell shape at 32×32 so idle
   cells no longer look like 24×24 EDL chiclets. Includes the nav
   arrows (« < > ») so the whole cluster stays on the same grid.
   Scoped to `.v4-card .pgn` so it does not leak into any other
   pagination surface (Edit User / Edit Role). */
[data-iam-version="v4"] .v4-card .pgn .pg-nums .pg-n {
  min-width: 32px;
  height: 32px;
  padding: 0 6px;
  border-radius: 8px;
  font-size: 13px;
  line-height: 20px;
  color: var(--text-primary);
}
[data-iam-version="v4"] .v4-card .pgn .pg-nums .pg-n.on,
[data-iam-version="v4"] .v4-card .pgn .pg-nums .pg-n[aria-current] {
  background: var(--ads-indigo-300, #4045C2);
  color: #ffffff;
}
[data-iam-version="v4"] .v4-card .pgn .pg-nav {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: var(--text-secondary);
}
[data-iam-version="v4"] .v4-card .pgn .pg-nav:not(.off):hover {
  background: var(--ads-indigo-50, #E2E3F2);
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .pgn .pg-nav.off {
  color: rgba(15, 18, 20, 0.32);
  pointer-events: none;
}

/* R46-11. Toolbar row rhythm.
   Rate Card places 12px between the Filter button, the segmented
   control (where present), and the Search input. V4's base rule
   sits at 8px. Bring the wide gap up to 12px so the four controls
   share Rate Card's rhythm at desktop width. */
[data-iam-version="v4"] .v4-card .tbar .tbar-l {
  gap: 12px;
}

/* R46-12. Row-height + hover polish for parity.
   Rate Card's rows are 48px with a subtle brand-wash hover. R33-3c
   already delivered the hover wash; make sure the base row height
   remains 48px inside the v4-card even if a downstream rule
   overrides `.tbl td { height }`. Rate Card renders `.tbl thead th`
   at 40px height (slightly taller than V4's 32px) — bring V4 up so
   the header divider sits on the same optical baseline. */
[data-iam-version="v4"] .v4-card .tbl thead th {
  height: 40px;
}
[data-iam-version="v4"] .v4-card .tbl tbody td {
  height: 56px;
}

/* R46-13. Guardrail — no accidental oversized pills on standard
   inputs. If any downstream rule tries to blanket-apply a fully
   rounded radius (100px / 9999px) to text inputs, ensure the
   Access Management toolbar's search input stays on the 6-8px scale.
   `.seg-ctrl` itself is excluded here — Figma node 1003:17834 measures
   6px radius on the Toggle Group track (not 8px); its own rule above
   is the source of truth for that value. */
[data-iam-version="v4"] .v4-card .tbar input {
  border-radius: 8px;
}
[data-iam-version="v4"] .v4-card .tbar .seg-ctrl {
  border-radius: 6px;
}
[data-iam-version="v4"] .v4-card .tbar .seg-btn {
  border-radius: 6px;
}

/* R46-14. Narrow-desktop responsiveness.
   Wide-viewport rules above already match Rate Card at 1440. At
   ≤1280 and ≤1120 the sidebar and page gutters compress. Restate
   the toolbar horizontal padding + search width so controls stay
   usable and the pagination remains a single row. */
@media (max-width: 1280px) {
  html[data-iam-version="v4"] .v4-card .tbar .search { width: 300px; }
  html[data-iam-version="v4"] .v4-card .tbar         { padding: 14px 16px; }
  html[data-iam-version="v4"] .v4-card .tabs-row     { padding-left: 16px; padding-right: 16px; }
  html[data-iam-version="v4"] .v4-card .pgn          { padding: 12px 16px; }
}
@media (max-width: 1120px) {
  html[data-iam-version="v4"] .v4-card .tbar .search { width: 240px; }
  html[data-iam-version="v4"] .v4-card .tbar .tbar-l { flex-wrap: wrap; row-gap: 8px; }
}

/* R46-15. Guardrail — the outer legacy V3 `.card` rule under V4
   (R32-3a, line ~8225) sets a border + shadow. R46-2's :has() rule
   removes them where a .v4-card exists, but older browsers without
   :has() support (Safari <15.4, Chrome <105) would still paint the
   outer chrome. Restate a fallback that hides the outer chrome
   whenever the .card contains only the .v4-card wrapper. Modern
   browsers already covered by R46-2 above; this is belt-and-braces. */
@supports not selector(:has(*)) {
  [data-iam-version="v4"] main.page > .card {
    background: transparent;
    border: 0;
    box-shadow: none;
    overflow: visible;
    margin-bottom: 0;
    border-radius: 0;
  }
}

@media (max-width: 900px) {
  html[data-iam-version="v4"] .v4-card .pgn {
    height: auto;
    min-height: 96px;
    padding: 8px 12px;
  }
}

/* R57B — final targeted lock after every legacy cascade block. */
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab {
  height: 32px !important;
  padding: 8px 16px 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #51585b !important;
  font: 400 18px/24px "Open Sans", sans-serif !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:hover:not(:disabled):not(.on) {
  color: #3b4347 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on {
  height: 39px !important;
  padding: 8px 16px 7px !important;
  color: #4045c2 !important;
  font-weight: 600 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on::after {
  bottom: 0 !important;
  height: 3px !important;
  background: #4045c2 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:focus-visible {
  height: 40px !important;
  padding: 8px 16px !important;
  border-radius: 3px !important;
  color: #4045c2 !important;
  outline: 0 !important;
  box-shadow: inset 0 0 0 2px #4045c2 !important;
}

html[data-iam-version="v4"] .ads-search > input,
html[data-iam-version="v4"] .tm-add-search.ads-search > input {
  width: auto !important;
  height: 20px !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  color: #1e2528 !important;
  font: 400 14px/20px "Open Sans", sans-serif !important;
}
html[data-iam-version="v4"] .ads-search > input:focus,
html[data-iam-version="v4"] .tm-add-search.ads-search > input:focus {
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-ico {
  position: static !important;
  left: auto !important;
  right: auto !important;
  width: 20px !important;
  height: 20px !important;
  transform: none !important;
  color: #51585b !important;
}
html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-clear {
  position: static !important;
  left: auto !important;
  right: auto !important;
  /* Round 23 (2026-08-11): 16px -> 24px clickable area, matching the
     canonical `.ads-search .search-clear` rule below — this is one of
     three byte-identical duplicate blocks in this file (all `!important`,
     so all three had to move together or the lowest-value one would
     keep winning the cascade). */
  width: 24px !important;
  min-width: 24px !important;
  height: 24px !important;
  min-height: 24px !important;
  padding: 0 !important;
}
html[data-iam-version="v4"] .ads-search:focus-within {
  border-color: rgba(15, 18, 20, 0.50) !important;
  box-shadow: none !important;
}

html[data-iam-version="v4"] button:is(.btn-std, .btn-ghost, .au-btn-save, .cr-btn-save, .au-btn-add, .cr-btn-add, .flt-btn-cancel, .flt-btn-apply, .cr-btn-danger-solid) {
  box-sizing: border-box !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 36px !important;
  height: 36px !important;
  padding: 8px 12px !important;
  gap: 4px !important;
  border-radius: 6px !important;
  font: 600 14px/20px "Open Sans", sans-serif !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost,
html[data-iam-version="v4"] button.au-btn-save,
html[data-iam-version="v4"] button.cr-btn-save,
html[data-iam-version="v4"] button.flt-btn-apply {
  border: 0 !important;
  background: #4045c2 !important;
  color: #fff !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:hover:not(:disabled),
html[data-iam-version="v4"] button.au-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] button.cr-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] button.flt-btn-apply:hover:not(:disabled) {
  background: #6567ce !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:active:not(:disabled),
html[data-iam-version="v4"] button.au-btn-save:active:not(:disabled),
html[data-iam-version="v4"] button.cr-btn-save:active:not(:disabled),
html[data-iam-version="v4"] button.flt-btn-apply:active:not(:disabled) {
  background: #4045c2 !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:disabled,
html[data-iam-version="v4"] button.au-btn-save:disabled,
html[data-iam-version="v4"] button.cr-btn-save:disabled,
html[data-iam-version="v4"] button.flt-btn-apply:disabled {
  border-color: transparent !important;
  background: #e2e3f2 !important;
  color: rgba(255, 255, 255, 0.50) !important;
  opacity: 1 !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel) {
  border: 1px solid #4045c2 !important;
  background: transparent !important;
  color: #4045c2 !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel):hover:not(:disabled) {
  background: rgba(15, 18, 20, 0.05) !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel):active:not(:disabled) {
  background: rgba(15, 18, 20, 0.10) !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel):disabled {
  border-color: #e2e3f2 !important;
  background: rgba(15, 18, 20, 0.05) !important;
  color: #e2e3f2 !important;
  opacity: 1 !important;
}

@media (max-width: 768px) {
  html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab,
  html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on,
  html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:focus-visible {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
}

/* R57 terminal cascade lock.
   Legacy page-specific selectors below the shared component foundation
   predate ADS primitives and carry ID-level specificity. These narrowly
   scoped locks keep the official components authoritative without
   touching tables, pagination, navigation, forms or segmented controls. */
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab {
  height: 32px !important;
  padding: 8px 16px 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #51585b !important;
  font-family: "Open Sans", sans-serif !important;
  font-size: 18px !important;
  font-weight: 400 !important;
  line-height: 24px !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:hover:not(:disabled):not(.on) {
  color: #3b4347 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on {
  height: 39px !important;
  padding: 8px 16px 7px !important;
  color: #4045c2 !important;
  font-weight: 600 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on::after {
  bottom: 0 !important;
  height: 3px !important;
  background: #4045c2 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:focus-visible {
  height: 40px !important;
  padding: 8px 16px !important;
  border-radius: 3px !important;
  color: #4045c2 !important;
  outline: 0 !important;
  box-shadow: inset 0 0 0 2px #4045c2 !important;
}

html[data-iam-version="v4"] .ads-search > input,
html[data-iam-version="v4"] .tm-add-search.ads-search > input {
  width: auto !important;
  height: 20px !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  color: #1e2528 !important;
  font-family: "Open Sans", sans-serif !important;
  font-size: 14px !important;
  font-weight: 400 !important;
  line-height: 20px !important;
}
html[data-iam-version="v4"] .ads-search > input:focus,
html[data-iam-version="v4"] .tm-add-search.ads-search > input:focus {
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-ico {
  position: static !important;
  left: auto !important;
  right: auto !important;
  width: 20px !important;
  height: 20px !important;
  transform: none !important;
  color: #51585b !important;
}
html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-clear {
  position: static !important;
  left: auto !important;
  right: auto !important;
  /* Round 23 (2026-08-11): 16px -> 24px clickable area, matching the
     canonical `.ads-search .search-clear` rule below — this is one of
     three byte-identical duplicate blocks in this file (all `!important`,
     so all three had to move together or the lowest-value one would
     keep winning the cascade). */
  width: 24px !important;
  min-width: 24px !important;
  height: 24px !important;
  min-height: 24px !important;
  padding: 0 !important;
}
html[data-iam-version="v4"] .ads-search:focus-within {
  border-color: rgba(15, 18, 20, 0.50) !important;
  box-shadow: none !important;
}

html[data-iam-version="v4"] button:is(
  .btn-std,
  .btn-ghost,
  .au-btn-save,
  .cr-btn-save,
  .au-btn-add,
  .cr-btn-add,
  .flt-btn-cancel,
  .flt-btn-apply,
  .cr-btn-danger-solid
) {
  box-sizing: border-box !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 36px !important;
  height: 36px !important;
  padding: 8px 12px !important;
  gap: 4px !important;
  border-radius: 6px !important;
  font-family: "Open Sans", sans-serif !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  line-height: 20px !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost,
html[data-iam-version="v4"] button.au-btn-save,
html[data-iam-version="v4"] button.cr-btn-save,
html[data-iam-version="v4"] button.flt-btn-apply {
  border: 0 !important;
  background: #4045c2 !important;
  color: #ffffff !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:hover:not(:disabled),
html[data-iam-version="v4"] button.au-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] button.cr-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] button.flt-btn-apply:hover:not(:disabled) {
  background: #6567ce !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:active:not(:disabled),
html[data-iam-version="v4"] button.au-btn-save:active:not(:disabled),
html[data-iam-version="v4"] button.cr-btn-save:active:not(:disabled),
html[data-iam-version="v4"] button.flt-btn-apply:active:not(:disabled) {
  background: #4045c2 !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:disabled,
html[data-iam-version="v4"] button.au-btn-save:disabled,
html[data-iam-version="v4"] button.cr-btn-save:disabled,
html[data-iam-version="v4"] button.flt-btn-apply:disabled {
  border-color: transparent !important;
  background: #e2e3f2 !important;
  color: rgba(255, 255, 255, 0.50) !important;
  opacity: 1 !important;
}
html[data-iam-version="v4"] button:is(
  .btn-std,
  .au-btn-add,
  .cr-btn-add,
  .flt-btn-cancel
) {
  border: 1px solid #4045c2 !important;
  background: transparent !important;
  color: #4045c2 !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] button:is(
  .btn-std,
  .au-btn-add,
  .cr-btn-add,
  .flt-btn-cancel
):hover:not(:disabled) {
  background: rgba(15, 18, 20, 0.05) !important;
}
html[data-iam-version="v4"] button:is(
  .btn-std,
  .au-btn-add,
  .cr-btn-add,
  .flt-btn-cancel
):active:not(:disabled) {
  background: rgba(15, 18, 20, 0.10) !important;
}
html[data-iam-version="v4"] button:is(
  .btn-std,
  .au-btn-add,
  .cr-btn-add,
  .flt-btn-cancel
):disabled {
  border-color: #e2e3f2 !important;
  background: rgba(15, 18, 20, 0.05) !important;
  color: #e2e3f2 !important;
  opacity: 1 !important;
}

@media (max-width: 768px) {
  html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab,
  html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on,
  html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:focus-visible {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   R57 — Official ADS shared components: Tabs, Search and Button

   Figma sources:
     Primary Tab 57:56 · Search 37:16 · Button 17:542 / 7722:228
   This terminal layer intentionally preserves every legacy class/ID
   used by app.js and only replaces shared component presentation.
   ═══════════════════════════════════════════════════════════════════ */

html[data-iam-version="v4"] {
  --ads-target-control-border: rgba(15, 18, 20, 0.20);
  --ads-target-control-border-bold: rgba(15, 18, 20, 0.50);
  --ads-target-control-hover: rgba(15, 18, 20, 0.05);
  --ads-target-control-active: rgba(15, 18, 20, 0.10);
  --ads-target-disabled-surface: #e2e3f2;
  --ads-target-disabled-text: rgba(15, 18, 20, 0.30);
  --ads-target-button-hover: #6567ce;
}

/* Primary Tab — Default size, no optional icon/counter for IAM labels. */
html[data-iam-version="v4"] .ads-tabs {
  height: 56px;
  padding: 8px 0 9px;
  border-bottom: 1px solid rgba(15, 18, 20, 0.10);
  align-items: flex-start;
}
html[data-iam-version="v4"] .ads-tabs > nav {
  height: 40px;
  gap: 0;
  align-items: flex-start;
}
html[data-iam-version="v4"] .ads-tab {
  position: relative;
  box-sizing: border-box;
  display: inline-flex;
  align-items: flex-start;
  height: 32px;
  padding: 8px 16px 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #51585b;
  font-family: "Open Sans", sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 24px;
  white-space: nowrap;
  cursor: pointer;
}
html[data-iam-version="v4"] .ads-tab:hover:not(:disabled):not(.on) {
  color: #3b4347;
  background: transparent;
}
html[data-iam-version="v4"] .ads-tab.on {
  height: 39px;
  padding: 8px 16px 7px;
  color: #4045c2;
  font-weight: 600;
}
html[data-iam-version="v4"] .ads-tab.on::after {
  bottom: 0;
  height: 3px;
  border-radius: 0;
  background: #4045c2;
}
html[data-iam-version="v4"] .ads-tab:focus-visible {
  height: 40px;
  padding: 8px 16px;
  border-radius: 3px;
  color: #4045c2;
  outline: 0;
  box-shadow: inset 0 0 0 2px #4045c2;
}
html[data-iam-version="v4"] .ads-tab:disabled,
html[data-iam-version="v4"] .ads-tab[aria-disabled="true"] {
  color: rgba(15, 18, 20, 0.30);
  opacity: 0.40;
  cursor: not-allowed;
}

/* Search — the wrapper owns ADS border/background/radius while the
   native input remains the existing JS hook and query-state owner.

   Round 23 (2026-08-11 — search-field responsive width): this is a flex
   ITEM (its own parent, `.tbar-l`, is `display:flex`), so the `width`
   below is only a fallback for non-flex contexts — the value that
   actually governs layout is the flex-basis carried by the `flex`
   shorthand a few lines down (flex-basis wins over `width` whenever
   it's a definite length, per the flexbox spec), which is why both
   are kept in lockstep with the same `clamp(...)` expression. The
   `41.667vw` coefficient is chosen so the curve is perfectly
   continuous AND hits exactly 600px right at 1440px (600 / 1440 =
   0.41666...): below 1440px it scales fluidly with the viewport
   (never jumping between breakpoints),    at/above 1440px `clamp` caps it
   at the 600px ceiling on its own — no separate `@media (min-width:
   1440px)` snap needed. Below a hard 280px floor, flexbox is still
   allowed to shrink it further on genuinely narrow viewports (never a
   fixed 280px `min-width`) so it can never itself force horizontal
   overflow; 280px remains the *preferred* size down to a ~672px-wide
   flex row, per the brief, simply because that's where `41.667vw`
   first drops below 280px. The one exception is `min-width: 120px`:
   `#usersPanel .tbar-l` has a separate, pre-existing `max-width:
   calc(100% - 240px)` reservation (for Export + Add User) that goes
   negative below ~615px of *card* width regardless of this field —
   Filter and the segmented control both refuse to shrink (`flex-shrink:
   0`) and simply overflow that reservation, leaving search, as the
   only shrinkable sibling, to absorb literally all of the deficit and
   collapse to ~0px. 120px is a pragmatic floor that keeps the field
   itself minimally visible/usable (still shows a few characters and
   the clear button) through that pre-existing squeeze, without
   reopening the `.tbar-l` reservation logic itself. */
html[data-iam-version="v4"] .ads-search {
  position: relative;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  width: clamp(280px, 41.667vw, 600px);
  min-width: 120px;
  max-width: 600px;
  height: 36px;
  padding: 8px 16px;
  gap: 8px;
  flex: 0 1 clamp(280px, 41.667vw, 600px);
  border: 1px solid var(--ads-target-control-border);
  border-radius: 100px;
  background: #ffffff;
  color: #51585b;
  transition: border-color 120ms ease, background-color 120ms ease;
}
html[data-iam-version="v4"] .ads-search:hover:not(:focus-within) {
  border-color: var(--ads-target-control-border);
}
html[data-iam-version="v4"] .ads-search:focus-within {
  border-color: var(--ads-target-control-border-bold);
  background: #ffffff;
  box-shadow: none;
}
html[data-iam-version="v4"] .ads-search:has(input:disabled) {
  border-color: var(--ads-target-control-border);
  background: rgba(15, 18, 20, 0.05);
  opacity: 0.60;
}
html[data-iam-version="v4"] .ads-search > input,
html[data-iam-version="v4"] .tm-add-search.ads-search > input {
  order: 1;
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 0;
  outline: 0;
  background: transparent;
  box-shadow: none;
  color: #1e2528;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
}
html[data-iam-version="v4"] .ads-search > input:hover,
html[data-iam-version="v4"] .ads-search > input:focus,
html[data-iam-version="v4"] .tm-add-search.ads-search > input:hover,
html[data-iam-version="v4"] .tm-add-search.ads-search > input:focus {
  border: 0;
  outline: 0;
  background: transparent;
  box-shadow: none;
}
html[data-iam-version="v4"] .ads-search > input::placeholder {
  color: #51585b;
  opacity: 1;
  font-weight: 400;
}
html[data-iam-version="v4"] .ads-search .search-ico,
html[data-iam-version="v4"] .ads-search .tm-add-search-icon {
  position: static;
  order: 0;
  display: block;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  transform: none;
  color: #51585b;
  pointer-events: none;
}
/* Round 23 (2026-08-11 — search-field text alignment): this toolbar
   field (`#searchWrap`/`#rpSearchWrap`/`#tmSearchWrap` — Users/Roles/
   Teams) never actually shows a leading magnifier once it has a query
   (the base `.search.has-value .search-ico{opacity:0}` rule already
   fades it out), but as a static flex item it kept reserving its full
   20px + 8px gap of layout space even while invisible, pushing typed
   text ~28px further right than the field's own padding alone would.
   `display: none` (rather than opacity) removes it from the flex flow
   entirely so entered text sits directly against the field's 16px
   padding, and — since the icon is then never rendered in either
   state for this field — placeholder and entered text land at the
   identical x-position instead of shifting when the query is cleared.
   `.tm-add-search-icon` (the unrelated "Add members" modal search,
   which always shows its icon) is intentionally left out of this rule
   so it keeps its own icon untouched. */
html[data-iam-version="v4"] .ads-search .search-ico {
  display: none;
}
html[data-iam-version="v4"] .ads-search .search-clear {
  position: static;
  order: 2;
  width: 24px;
  min-width: 24px;
  height: 24px;
  min-height: 24px;
  padding: 0;
  border: 0;
  border-radius: 100px;
  background: transparent;
  color: #51585b;
  /* Cancels the base `.search-clear { transform: translateY(-50%) }`
     rule (written for its old absolute-positioned layout), which was
     leaking into this flex-centered context and pushing the button up
     by half its own height — the ~8px "sits too high" bug. Vertical
     centering here comes entirely from the parent's flex
     `align-items: center` now, so no transform is needed. The box grows
     16px -> 24px for a full 24x24 clickable area per the design brief;
     the 16x16 SVG glyph inside stays centered within it for free via
     the base `.search-clear` rule's own `display:inline-flex;
     align-items:center; justify-content:center`. */
  transform: none;
}
html[data-iam-version="v4"] .ads-search .search-clear svg {
  width: 16px;
  height: 16px;
}
html[data-iam-version="v4"] .ads-search .search-clear:hover {
  background: var(--ads-target-control-hover);
}
html[data-iam-version="v4"] .ads-search .search-clear:focus-visible {
  outline: 2px solid #4045c2;
  outline-offset: 2px;
}
html[data-iam-version="v4"] .ads-search .search-dropdown {
  order: 3;
}
html[data-iam-version="v4"] .tm-add-search.ads-search {
  width: 100%;
  flex: 0 0 auto;
  /* Height and padding are deliberately left to the shared
     `.ads-search` default (36px), which is what the Add User picker's
     field uses. This modal used to trim the control to 32px to echo
     the Name/Description inputs on the Edit Team page behind it, but
     the two pickers sit side by side in the same flow and a 4px
     difference between their search fields is visible. */
}

/* ADS Button default shared anatomy — 14/20 Semibold, 16px icon,
   4px gap, 12x8 padding, 6px radius and 36px rendered height. */
html[data-iam-version="v4"] .btn-std,
html[data-iam-version="v4"] .btn-ghost,
html[data-iam-version="v4"] .au-btn-save,
html[data-iam-version="v4"] .cr-btn-save,
html[data-iam-version="v4"] .au-btn-add,
html[data-iam-version="v4"] .cr-btn-add,
html[data-iam-version="v4"] .flt-btn-cancel,
html[data-iam-version="v4"] .flt-btn-apply,
html[data-iam-version="v4"] .cr-btn-danger-solid {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  height: 36px;
  padding: 8px 12px;
  gap: 4px;
  border-radius: 6px;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  letter-spacing: 0;
  white-space: nowrap;
}
html[data-iam-version="v4"] .btn-std > svg,
html[data-iam-version="v4"] .btn-ghost > svg,
html[data-iam-version="v4"] .au-btn-save > svg,
html[data-iam-version="v4"] .cr-btn-save > svg,
html[data-iam-version="v4"] .au-btn-add > svg,
html[data-iam-version="v4"] .cr-btn-add > svg,
html[data-iam-version="v4"] .flt-btn-cancel > svg,
html[data-iam-version="v4"] .flt-btn-apply > svg,
html[data-iam-version="v4"] .cr-btn-danger-solid > svg {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
}

/* Primary. */
html[data-iam-version="v4"] .v4-card .tbar .btn-ghost,
html[data-iam-version="v4"] .au-btn-save,
html[data-iam-version="v4"] .cr-btn-save,
html[data-iam-version="v4"] .flt-btn-apply {
  border: 0;
  background: #4045c2;
  color: #ffffff;
}
html[data-iam-version="v4"] .v4-card .tbar .btn-ghost:hover:not(:disabled),
html[data-iam-version="v4"] .au-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] .cr-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] .flt-btn-apply:hover:not(:disabled) {
  background: #6567ce;
  color: #ffffff;
}
html[data-iam-version="v4"] .v4-card .tbar .btn-ghost:active:not(:disabled),
html[data-iam-version="v4"] .au-btn-save:active:not(:disabled),
html[data-iam-version="v4"] .cr-btn-save:active:not(:disabled),
html[data-iam-version="v4"] .flt-btn-apply:active:not(:disabled) {
  background: #4045c2;
  color: #ffffff;
}
html[data-iam-version="v4"] .v4-card .tbar .btn-ghost:disabled,
html[data-iam-version="v4"] .au-btn-save:disabled,
html[data-iam-version="v4"] .cr-btn-save:disabled,
html[data-iam-version="v4"] .flt-btn-apply:disabled {
  border-color: transparent;
  background: #e2e3f2;
  color: rgba(255, 255, 255, 0.50);
  opacity: 1;
}

/* Secondary — IAM Filter, Cancel, Add and Update actions. */
html[data-iam-version="v4"] .btn-std,
html[data-iam-version="v4"] .au-btn-add,
html[data-iam-version="v4"] .cr-btn-add,
html[data-iam-version="v4"] .flt-btn-cancel {
  border: 1px solid #4045c2;
  background: transparent;
  color: #4045c2;
}
html[data-iam-version="v4"] .btn-std:hover:not(:disabled),
html[data-iam-version="v4"] .au-btn-add:hover:not(:disabled),
html[data-iam-version="v4"] .cr-btn-add:hover:not(:disabled),
html[data-iam-version="v4"] .flt-btn-cancel:hover:not(:disabled) {
  border-color: #4045c2;
  background: rgba(15, 18, 20, 0.05);
  color: #4045c2;
}
html[data-iam-version="v4"] .btn-std:active:not(:disabled),
html[data-iam-version="v4"] .au-btn-add:active:not(:disabled),
html[data-iam-version="v4"] .cr-btn-add:active:not(:disabled),
html[data-iam-version="v4"] .flt-btn-cancel:active:not(:disabled) {
  border-color: #4045c2;
  background: rgba(15, 18, 20, 0.10);
  color: #4045c2;
}
html[data-iam-version="v4"] .btn-std:disabled,
html[data-iam-version="v4"] .au-btn-add:disabled,
html[data-iam-version="v4"] .cr-btn-add:disabled,
html[data-iam-version="v4"] .flt-btn-cancel:disabled {
  border-color: #e2e3f2;
  background: rgba(15, 18, 20, 0.05);
  color: #e2e3f2;
  opacity: 1;
}
html[data-iam-version="v4"] #createRolePage .cr-btn-add {
  border: 1px solid #4045c2;
  background: transparent;
  color: #4045c2;
}

/* Compact ghost text buttons preserve the existing hierarchy while
   using the official compact button size.
   NOTE (back-nav standardization): `.au-back`/`.cr-back` were removed
   from this group — back-navigation controls are their own ADS
   component (Button size=32, 14px/20px SemiBold) defined once near
   the top of this file, deliberately decoupled from this 26px/12px
   "small inline action" treatment used by Remove application/Remove
   User/etc.
   NOTE (Edit Role header-actions QA, 2026-08-11): `.cr-btn-remove`
   ("Remove Role") was also removed from this group — it now reuses
   the full-size (36px) `.au-revoke-btn`/`.tm-delete-btn` ADS ghost
   button component instead (see that rule's own comment), so it sits
   at the same height/vertical alignment as the adjacent Cancel/Save
   Role actions rather than this smaller 26px inline-link treatment.
   NOTE (Edit Team Members-table QA, Round 37, 2026-08-12):
   `.tm-row-remove` ("Remove" in the Members table) was also removed
   from this group for the same reason as `.cr-btn-remove` above — it
   now reuses the shared `.au-revoke-btn`/`.tm-delete-btn`/
   `.cr-btn-remove` ghost-button color/interaction contract (Delete
   Team's own component) instead, paired with its own compact-size
   modifier scoped to `.tm-row-remove` alone (see that rule group
   further down this file) so it keeps a table-row-appropriate height
   without inheriting this group's generic 12px/gray-on-hover-only
   treatment. */
html[data-iam-version="v4"] .flt-btn-reset,
html[data-iam-version="v4"] .au-remove-user-link,
html[data-iam-version="v4"] .cr-app-remove,
html[data-iam-version="v4"] .pc-grp-delete,
html[data-iam-version="v4"] button.rp-func-link {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 26px;
  height: 26px;
  padding: 4px 8px;
  gap: 4px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  font-weight: 600;
  line-height: 18px;
  white-space: nowrap;
}
html[data-iam-version="v4"] .flt-btn-reset:hover,
html[data-iam-version="v4"] .cr-app-remove:hover,
html[data-iam-version="v4"] .pc-grp-delete:hover,
html[data-iam-version="v4"] button.rp-func-link:hover {
  background: rgba(15, 18, 20, 0.05);
}
html[data-iam-version="v4"] .flt-btn-reset:active,
html[data-iam-version="v4"] .cr-app-remove:active,
html[data-iam-version="v4"] .pc-grp-delete:active,
html[data-iam-version="v4"] button.rp-func-link:active {
  background: rgba(15, 18, 20, 0.10);
}

/* Semantic focus is shared by every migrated Button variant. */
html[data-iam-version="v4"] .btn-std:focus-visible,
html[data-iam-version="v4"] .btn-ghost:focus-visible,
html[data-iam-version="v4"] .au-btn-save:focus-visible,
html[data-iam-version="v4"] .cr-btn-save:focus-visible,
html[data-iam-version="v4"] .au-btn-add:focus-visible,
html[data-iam-version="v4"] .cr-btn-add:focus-visible,
html[data-iam-version="v4"] .flt-btn-cancel:focus-visible,
html[data-iam-version="v4"] .flt-btn-apply:focus-visible,
html[data-iam-version="v4"] .flt-btn-reset:focus-visible,
html[data-iam-version="v4"] .au-remove-user-link:focus-visible,
html[data-iam-version="v4"] .cr-app-remove:focus-visible,
html[data-iam-version="v4"] .pc-grp-delete:focus-visible,
html[data-iam-version="v4"] button.rp-func-link:focus-visible,
html[data-iam-version="v4"] .cr-btn-danger-solid:focus-visible {
  outline: 2px solid #4045c2;
  outline-offset: 2px;
}

/* Official icon-only Button size. Search clear remains the Search
   component's own 16px action and pagination/nav controls stay scoped
   out of this targeted migration. */
html[data-iam-version="v4"] .flt-close,
html[data-iam-version="v4"] .edl-modal-close,
html[data-iam-version="v4"] .edl-toast-close {
  box-sizing: border-box;
  width: 32px;
  min-width: 32px;
  height: 32px;
  min-height: 32px;
  padding: 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: #51585b;
}
html[data-iam-version="v4"] .flt-close:hover,
html[data-iam-version="v4"] .edl-modal-close:hover,
html[data-iam-version="v4"] .edl-toast-close:hover {
  background: rgba(15, 18, 20, 0.05);
}
html[data-iam-version="v4"] .flt-close:active,
html[data-iam-version="v4"] .edl-modal-close:active,
html[data-iam-version="v4"] .edl-toast-close:active {
  background: rgba(15, 18, 20, 0.10);
}
html[data-iam-version="v4"] .flt-close:focus-visible,
html[data-iam-version="v4"] .edl-modal-close:focus-visible,
html[data-iam-version="v4"] .edl-toast-close:focus-visible {
  outline: 2px solid #4045c2;
  outline-offset: 2px;
}

@media (max-width: 768px) {
  html[data-iam-version="v4"] .ads-tab,
  html[data-iam-version="v4"] .ads-tab.on,
  html[data-iam-version="v4"] .ads-tab:focus-visible {
    padding-left: 16px;
    padding-right: 16px;
  }
  html[data-iam-version="v4"] .v4-card .tbar .ads-search {
    width: 100%;
    flex: 1 1 100%;
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
   V4 — Round 47 — Top navigation pixel-parity with Rate Card Figma

   Reference: Rate Card / Navigation — Figma node 375:6250
     https://www.figma.com/design/Klc8JpICWSLwU1LeUVRHtT/Rate-Card?node-id=375-6250

   Figma inspector spec:
     Container   flex, items:center, px 24, bg #4045c2 (navigation/topbar/background)
     brand       flex, gap 8, items:center
                 ├─ Vector           32 × 28  (D-glyph, white)
                 └─ "Disney Advertising"   MultiplaneTWDC Display Bold 18/24 white
     spacer      flex-1 0 0    ×2 (two spacers push utilities to the right rail)
     utilities   flex, gap 16, items:center
                 ├─ icon-notification  20 × 20  (Bell)
                 ├─ icon-apps          20 × 20  (Sparkle)
                 └─ avatar             32 × 32

   The R33/R34/R36/R39 stack already delivered container height (56),
   horizontal padding (24), background, brand-cluster geometry, and
   the 20×20 icon sizes. The remaining drift measured against the
   Figma node:

     • Bell→Sparkle visible spacing was 36px (Figma: 16)
     • Sparkle→Avatar visible spacing was 30px (Figma: 16)
     • Avatar right edge sat 28px from viewport (Figma: 24)

   Root cause: the R34 utility-buttons carry `width: 40; padding: 10`
   for a 40×40 hit target around each 20×20 icon. The 10px horizontal
   padding pushes the icons 10px inward on each side, adding 20px of
   extra visible spacing between adjacent icons and 4px from the
   right rail.

   R47 tightens the utility buttons to the icon width (20 for Bell/
   Sparkle, 32 for Avatar) so the raw icons sit at exactly the Figma
   gap (16 px). Hit target vertical stays at 40 px (parent nav is 56,
   so 40 gives 8px above/below breathing room). The hover state moves
   from an in-button background pill to a subtle pseudo-element wash
   so the visual hover ring can extend a few pixels around each icon
   without changing layout.

   Trade-off: WCAG 2.5.5 recommends 44×44 minimum touch targets. At
   20 × 40 (Bell/Sparkle) the width is below spec. This is the exact
   trade-off Rate Card's Figma reference makes; the user's directive
   is "final rendered result must visually match the supplied Figma
   node — not merely approximate it," so we prioritize the visual
   match. Keyboard nav + hover work at any size.

   Product-nav (Sales / Planning / Ad Ops / Billing / Admin) stays
   hidden via R34-2 (Figma reference has no center nav). The DOM is
   preserved so V3 renders it normally under EDL.
   ─────────────────────────────────────────────────────────────────── */

/* R47-1. Utility buttons — collapse to icon-only width so the raw
   glyphs sit exactly 16 px apart per the Figma reference. The
   `.nav-r { gap: 16px }` from R34-4 already supplies the gap; we
   just need to strip the extra horizontal padding that R34-5 added
   for the 40 × 40 hit target. */
[data-iam-version="v4"] .nav-r .nav-r-btn {
  width: 20px;
  height: 40px;
  padding: 0;
  border-radius: 4px;
  background: transparent;
  color: #FFFFFF;
  border: 0;
  position: relative;
  transition: background-color .12s ease;
}

/* R47-2. Avatar trigger — 32 × 32 image inside a 32 × 40 button so
   the image aligns to the right rail (viewport - 24 px = nav's
   right padding edge). The image itself remains 32 × 32 per Figma.
   Vertical padding centers the 32 image inside the 40-tall button. */
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn {
  width: 32px;
  height: 40px;
  padding: 4px 0;
}
[data-iam-version="v4"] .nav-avatar-img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: block;
  object-fit: cover;
}

/* R47-3. Icon dimensions — restate the 20 × 20 icon size (already
   set by R34-5, restated here so this block is self-contained if the
   older rule is ever refactored). */
[data-iam-version="v4"] .nav-r .nav-r-btn .nav-ico {
  width: 20px;
  height: 20px;
  display: block;
  color: #FFFFFF;
}

/* R47-4. Hover state — a subtle 12 % white wash on the button
   background. R34-5 defined the same treatment on a 40 × 40 pill;
   now that the buttons are 20 × 40 (Bell / Sparkle) or 32 × 40
   (Avatar), the pill takes the same shape at 4 px radius. The
   hover on Avatar keeps its round image visible above the pill. */
[data-iam-version="v4"] .nav-r .nav-r-btn:hover {
  background: rgba(255, 255, 255, 0.12);
}
[data-iam-version="v4"] .nav-r .nav-r-btn:active {
  background: rgba(255, 255, 255, 0.18);
}
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn:hover,
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn:active {
  background: transparent;
}

/* R47-5. Focus state — the semantic focus ring stays on the button
   at the correct 2 px offset regardless of button shape. */
[data-iam-version="v4"] .nav-r .nav-r-btn:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
  background: rgba(255, 255, 255, 0.12);
}
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
  background: transparent;
}

/* R47-6. Sticky nav guardrail — the base `.nav { position: sticky;
   top: 0; z-index: 100 }` already applies. Restate explicitly under
   V4 so no downstream rule accidentally strips sticky behavior.
   Height / min-height already 56 (R34-1). */
[data-iam-version="v4"] .nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #4045C2;
}

/* R47-7. Border / shadow — Figma reference paints a flat bar with
   NO border and NO shadow. V3 base `.nav` has neither. Explicitly
   clear them so any theme override cannot introduce a fringe. */
[data-iam-version="v4"] .nav {
  border: 0;
  box-shadow: none;
}

/* R47-8. Legacy chip class overrides that the R34 stack still
   inherits — `.nav-mod` / `.nav-logo-group` / `.nav-logo-link`
   already fully zeroed via R39-1. Restate `.nav-l` sizing so the
   brand cluster hugs its content and never expands beyond the
   glyph + text (avoids pushing utilities right of viewport when
   the brand text wraps unexpectedly). */
[data-iam-version="v4"] .nav-l {
  flex: 0 0 auto;
  overflow: visible;
}
[data-iam-version="v4"] .nav-r {
  flex: 0 0 auto;
}

/* R47-9. Responsive parity — the Figma reference does not change
   the utility cluster at narrower widths (it stays a flush right-
   rail cluster). The brand text can shrink at very small widths so
   it doesn't wrap. Base R34 already reduces `.nav` padding at
   ≤1024/≤768; restate the utility-button width so nothing collapses
   into a taller stacked layout at any supported desktop width.

   The R39-6 rule at 768 already shrinks the brand text to 16/22 so
   it fits. Nothing else needs to reflow. */
@media (max-width: 1024px) {
  [data-iam-version="v4"] .nav-r .nav-r-btn { width: 20px; height: 40px; padding: 0; }
  [data-iam-version="v4"] #userMenuTrigger.nav-r-btn { width: 32px; height: 40px; padding: 4px 0; }
}
@media (max-width: 768px) {
  /* Left stays 0 (not the old flat 16px) — Final-QA (product-name
     horizontal position correction) made the left rail's own 64px
     width the thing that aligns the D-glyph with `.sidebar` (which
     never changes width/position at this breakpoint), so re-adding
     nav padding here would double that inset and drift the rail off
     the sidebar's 0–64 column exactly like the bug this pass fixed. */
  [data-iam-version="v4"] .nav { padding: 0 16px 0 0; }
}

/* R47-10. Explicitly kill any leftover EDL utility-slot rules that
   could redirect the .nav-r-btn size on V4 (defensive — nothing
   currently sets these, but the ADS Preview block at line 4423
   used to set a wider padding on nav-r-btn under [data-theme=
   "ads-preview"]. R47-1 wins on cascade + specificity, but
   restate at :where(...) to keep specificity tight so future
   additions can override cleanly if the design shifts). */
[data-iam-version="v4"][data-theme="ads-preview"] .nav-r .nav-r-btn {
  width: 20px;
  padding: 0;
}
[data-iam-version="v4"][data-theme="ads-preview"] #userMenuTrigger.nav-r-btn {
  width: 32px;
  padding: 4px 0;
}

/* ═══════════════════════════════════════════════════════════════
   R50. Access Management — ADS visual alignment pass against
   Figma node 157:1924 (Klc8JpICWSLwU1LeUVRHtT / Rate Card).

   Two targeted drifts to close after a full-page audit of the
   R46 output against the supplied Figma page and the shipped
   Rate Card app at localhost:8001:

     1. Search-input icon position — R46-7 moved the magnifier
        from the RIGHT (Figma-native) to the LEFT under the
        assumption that Rate Card used a leading icon. Direct
        inspection of Figma 157:1924 AND the shipped Rate Card
        app both show the icon on the RIGHT.
     2. Filter button — R46-5 shipped `.btn-std` as a filled
        Indigo-50 wash (`#e2e3f2` bg + transparent border). The
        Figma reference (and the Rate Card app) render Filter as
        the OUTLINED variant: near-white bg, Indigo-300 border,
        Indigo-300 text/icon.

   Everything else on the Access Management page (page shell,
   header rhythm, main-card chrome, Users/Roles/Teams tabs,
   Internal/External segmented control, Add User primary, table
   density, name column, status treatment, pagination active +
   inactive) already matches Figma within pixel tolerance — no
   further changes needed in this pass.

   All Access Management content — page title, description, tab
   labels, table columns, user data, avatars, chips, pagination
   values, Add User label — is preserved verbatim. Only visual
   chrome changes here. */

/* R50-1. Search icon → RIGHT position (matches Figma 157:1924).

   R46-7 had `left: 12px; right: auto;` on `.search-ico` and
   `padding: 0 12px 0 36px;` on the input (label offset for the
   leading icon). Reverting to trailing-icon convention:
     • Icon: `right: 12px; left: auto;`
     • Input padding: 12 px left, 36 px right (icon + 4 px buffer)

   The clear-× (`.search-clear`) was previously anchored at
   `right: 8px`; with the icon now on the right the two would
   overlap. Slide the clear-× inboard to `right: 32px` (icon
   width 16 + 4 buffer + 12 icon right offset = 32) so it sits
   just to the left of the magnifier when the user types. */
[data-iam-version="v4"] .v4-card .tbar .search input {
  padding: 0 36px 0 12px;
}
[data-iam-version="v4"] .v4-card .tbar .search .search-ico {
  left: auto;
  right: 12px;
}
[data-iam-version="v4"] .v4-card .tbar .search .search-clear {
  right: 32px;
}

/* R50-2. Filter button → OUTLINED indigo (matches Figma 157:1924).

   R46-5 shipped `.btn-std` as an Indigo-50 filled chip. Figma's
   Filter and the Rate Card app both use the outlined secondary
   treatment: near-white background, 1 px Indigo-300 border,
   Indigo-300 text + icon.

   State ramp:
     • rest    — white bg, indigo border, indigo text/icon
     • hover   — very-light indigo wash (Indigo 50 at 60 %) bg,
                 border + text unchanged so the button reads as
                 "the same button, engaged" rather than a new
                 element
     • active  — full Indigo 50 wash bg, border + text unchanged
     • focus   — 2 px Indigo 300 ring at 2 px offset (inherited
                 from R46-5's focus-visible rule; restated here
                 in case that rule is dropped later) */
[data-iam-version="v4"] .v4-card .tbar .btn-std {
  background: #ffffff;
  border: 1px solid var(--ads-indigo-300, #4045C2);
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .tbar .btn-std:hover {
  background: color-mix(in srgb, var(--ads-indigo-50, #E2E3F2) 60%, #ffffff);
  border-color: var(--ads-indigo-300, #4045C2);
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .tbar .btn-std:active {
  background: var(--ads-indigo-50, #E2E3F2);
  border-color: var(--ads-indigo-300, #4045C2);
  color: var(--ads-indigo-300, #4045C2);
}
[data-iam-version="v4"] .v4-card .tbar .btn-std:focus-visible {
  outline: 2px solid var(--ads-indigo-300, #4045C2);
  outline-offset: 2px;
}

/* ═══════════════════════════════════════════════════════════════════
   R51 — Nav brand + avatar Figma-parity fixes (V4 only)

   User feedback on R47/R48 confirmed the top nav still reads as
   "off" against Figma 375:6250. Two specific drifts remained:

     1. "Disney Advertising" wordmark weight was Medium (500), Figma
        specifies MultiplaneTWDC Display **Bold** (700). Local /assets/
        fonts ships only the Medium woff2 (500). R39-4 chose to stay at
        500 to avoid faux-bold blur; the Figma comparison shows this
        was the wrong call — the wordmark reads noticeably lighter than
        the Figma reference on a 1440 × 56 render. Modern Chrome/Safari
        synthesize a clean bold for Latin at 18 px with only a very
        slight softness on curved strokes, and closer visual parity
        with Figma outweighs the tiny softness. Bumping to 700 lets the
        browser generate a synthesized bold from the Medium file.

     2. Avatar rendered with a visible light-lavender ring around
        Marge inside the circle. The V1/V2/V3 shared /nav/avatar.png
        has near-white lavender padding around the subject inside its
        transparent-cornered mask; on the indigo (#4045c2) navbar this
        padding reads as "an extra white circle wrapping the photo" —
        exactly the "Do not add an extra white circle" gripe in the
        brief. R51 addresses this at the asset layer:
          • public/nav/avatar-v4.png is a new V4-only PNG (64 × 64)
            generated from the source by cropping to Marge's actual
            bounding box (removing the light padding) and re-applying
            a circular alpha mask.
          • The V4 index.html <img src> now points at avatar-v4.png.
          • V1/V2/V3/DCM still reference the original avatar.png →
            no regression outside V4.

   The Figma-supplied brand SVG path is already inlined byte-identical
   in index.html (R40); no path change needed. The bell + sparkle SVGs
   in index.html are also byte-identical to Figma nodes 46:219 and
   375:6233, so those stay as-is. The only remaining Figma-parity gap
   is the wordmark Bold font file (not shipped locally, browser will
   synthesize), documented above.
   ═══════════════════════════════════════════════════════════════════ */

/* R51-1. Brand wordmark — Figma spec is MultiplaneTWDC Display Bold
   (700) at 18 / 24. R39-4 kept this at 500 (Medium) because the file
   we ship is Medium; browsers substitute the same face when asked
   for 700 and synthesize a bolder rendering. This synthesized bold
   is visually much closer to Figma than the Medium was, and remains
   clean at 18 px. Higher specificity (`html[data-iam-version="v4"]
   .atlas-brand .atlas-brand-text`) ensures the rule wins over R39-4
   at equal-source-order (both at (0,3,0) but R51 comes later in the
   cascade). */
html[data-iam-version="v4"] .atlas-brand .atlas-brand-text {
  font-weight: 700;
}

/* R51-2. Avatar — Figma renders the utility avatar slot as a 32 × 32
   image with NO ring / border / background around the subject. The
   V1-V3 shared avatar has a light lavender-cream padding inside its
   transparent-cornered mask, which visually reads as "extra circle"
   on the indigo bar. R51 fixes this at the asset layer (new PNG
   public/nav/avatar-v4.png) and restates the img treatment here to
   guarantee:
     • No background color on the wrapper (indigo bar shows through
       the transparent corners of the PNG).
     • No border / box-shadow / ring on the image itself.
     • Explicit 32 × 32 CSS render (matches R47's dimensions; restated
       here so this block is self-contained).
     • object-fit: cover clips any anti-aliased edge pixels cleanly
       inside the 32 × 32 frame — the source PNG's own alpha mask
       already produces a circle, and CSS border-radius: 50% is a
       belt-and-suspenders reinforcement that keeps the shape
       perfectly round even on browsers that anti-alias the PNG
       alpha mask oddly at fractional DPRs.
     • image-rendering: -webkit-optimize-contrast + auto — the source
       is a raster and we render it at 32 CSS px from a 64-px asset
       (2× DPR ready). Optimizing for contrast keeps Marge's line
       art crisp on retina displays without the fuzz that some
       browsers introduce with default interpolation.
   The `#userMenuTrigger` selector is the button wrapper; R47-1 already
   removes its default background — restated here defensively so future
   selector reordering can't reintroduce a wrapper background that
   would read as a ring behind the avatar. */
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn {
  background: transparent;
}
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn .nav-avatar-img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 0;
  box-shadow: none;
  background: transparent;
  padding: 0;
  display: block;
  object-fit: cover;
  object-position: center;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: auto;
}

/* R51-3. User-menu wrapper vertical centering.

   `.user-menu` (line 238 base styles) is `position: relative;
   display: inline-flex; height: 100%` — this stretches the wrapper
   to the full 56 px nav height, but with no `align-items` set the
   default is `stretch`. Because the child #userMenuTrigger has an
   explicit `height: 40px` (R47-1), it cannot stretch to 56 — so it
   is instead aligned to the top of the flex container, sitting 16 px
   too high (avatar centerY = 20 instead of 28). Bell + Sparkle
   buttons are direct children of `.nav-r` which does center its
   children (visible in the QA probe: bellBtnCenterY = 28), so only
   the avatar wrapper needs this fix.

   Adding `align-items: center` centers the 40-px trigger inside the
   56-px wrapper, pulling avatarCenterY from 20 → 28. This aligns
   the round avatar photo with the bell + sparkle icons on the same
   optical baseline. Scoped to V4 so V1/V2/V3 wrappers keep whatever
   alignment they had (they use different button heights + we don't
   own that regression risk). */
[data-iam-version="v4"] .user-menu {
  align-items: center;
}

/* R51-4. Avatar hover / focus — restate R47-4 / R47-5's transparent
   hover so #userMenuTrigger never renders a background wash behind
   the round avatar (which would read as a ring). The bell + sparkle
   buttons keep their 12 % white wash from R47-4 since they don't have
   a round photo in front. */
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn:hover,
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn:active,
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn[aria-expanded="true"] {
  background: transparent;
}
[data-iam-version="v4"] #userMenuTrigger.nav-r-btn:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
  background: transparent;
}

/* ═══════════════════════════════════════════════════════════════════
   R52 — repository-wide IAM V4 ADS visual unification

   Sources, in priority order:
     1. ads-design-system/design.md + ads-components.json
     2. the existing ADS Preview token/component layer in this file
     3. Rate Card Manager v2.0 (localhost:8001, 2026-08-02)

   This pass changes presentation only. IDs, state classes, text, data,
   DOM order and JavaScript behavior remain untouched.
   ═══════════════════════════════════════════════════════════════════ */

html[data-iam-version="v4"][data-theme="ads-preview"] {
  --iam-ads-canvas: #f3f3f3;
  --iam-ads-surface: #ffffff;
  --iam-ads-text: #1e2528;
  --iam-ads-text-secondary: #3b4347;
  --iam-ads-text-muted: #51585b;
  --iam-ads-border: rgba(15, 18, 20, 0.20);
  --iam-ads-divider: rgba(15, 18, 20, 0.10);
  --iam-ads-brand: #4045c2;
  --iam-ads-brand-hover: #3b3fba;
  --iam-ads-brand-active: #363aab;
  --iam-ads-brand-wash: #e2e3f2;
  --iam-ads-control-radius: 6px;
  --iam-ads-card-radius: 16px;
  --iam-ads-dialog-radius: 12px;
  --iam-ads-control-height: 32px;
  --iam-ads-button-height: 36px;
  --iam-ads-card-elevation: 0 0 4px rgba(23, 29, 35, 0.13);
  --iam-ads-menu-elevation: 0 4px 12px rgba(15, 18, 20, 0.30);
  --iam-ads-dialog-elevation: 0 16px 40px rgba(15, 18, 20, 0.30);

  /* Toast — exact tokens read from the canonical ADS Toast component,
     Figma node 70:62 (file "Ads Design System"), via get_variable_defs.
     Figma variable names are noted so this block stays traceable back
     to source instead of approximating with arbitrary CSS. */
  --iam-ads-toast-surface: #ffffff;              /* toast/surface/default */
  --iam-ads-toast-radius: 6px;                   /* toast/size/radius */
  --iam-ads-toast-padding: 16px;                 /* toast/size/padding-x, applied on all 4 sides */
  --iam-ads-toast-content-gap: 12px;             /* toast/size/content/gap — icon ↔ content ↔ close */
  --iam-ads-toast-text-gap: 4px;                 /* gap between title and message */
  --iam-ads-toast-border-width: 5px;              /* left-only accent border width (no border on the other 3 sides) */
  /* elevation/30 = { y: 4, blur-length: 12 } and color/shadow/default
     rgba(15,18,20,0.3) → drop-shadow(0px 4px 6px …) (blur-length/2, per
     the Tailwind arbitrary-value math baked into the component). The
     nearest existing token (--iam-ads-menu-elevation) uses a 12px blur
     tuned for menus, not this exact toast value, so a dedicated token
     is defined instead of reusing an approximate one. */
  --iam-ads-toast-elevation: 0 4px 6px rgba(15, 18, 20, 0.30);
  --iam-ads-toast-border-error: #db5461;         /* toast/border/error */
  --iam-ads-toast-border-warning: #f5bb7a;       /* toast/border/warning */
  --iam-ads-toast-border-success: #6cb288;       /* toast/border/success */
  --iam-ads-toast-border-info: #4045c2;          /* toast/border/brand */
  --iam-ads-toast-text-error: #993b44;           /* toast/text/error */
  --iam-ads-toast-text-warning: #5c3711;         /* toast/text/warning */
  --iam-ads-toast-text-success: #365944;         /* toast/text/success */
  --iam-ads-toast-text-info: #4045c2;            /* toast/text/brand — the Info headline in the Figma
                                                     component instance is styled with toast/text/brand,
                                                     not the separate (unused-here) toast/text/info token */
  --iam-ads-toast-text-body: #1e2528;            /* toast/text/primary — supporting message, every variant */
  color-scheme: light;
}

html[data-iam-version="v4"] body {
  background: var(--iam-ads-canvas);
  color: var(--iam-ads-text);
  font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Shell: retain the verified 56px top bar geometry while normalizing
   shared interaction states. Side-nav geometry now lives entirely in
   the single "Rate Card shared sidebar" block further down this
   file — see that block for the sidebar/.sb-item color+radius tokens
   this pass used to restate here. */
html[data-iam-version="v4"] .nav {
  height: 56px;
  min-height: 56px;
  background: var(--iam-ads-brand);
  border: 0;
  box-shadow: none;
}

/* List page: Rate Card's white header band over a gray content canvas.
   The full-bleed shadow technique changes no DOM structure.
   R58: this rule used to also re-declare `max-width: 1440px` here.
   That silently overrode the intentional `max-width: none` set on this
   same selector earlier in the file (R35-12) — same selector, same
   specificity, so the declaration that appears *later* in the
   cascade wins, regardless of either rule's intent. That stray
   re-assertion was the actual root cause of the "content stuck at
   1440px even at 1920/2560" bug: `main.page` measured `max-width:
   1440px` in the computed styles at every viewport width above 1440,
   which is exactly the ceiling the redesigned `.card` max-width (see
   R58 above) is supposed to own instead. Only `background` belongs
   in this rule now. */
html[data-iam-version="v4"] main.page {
  background: transparent;
}
/* Final-QA correction, measured against Figma 770:17428's absolute
   frame positions: title top sits 32px below the 56px nav (was 24px),
   and the header-to-card gap is 55px total (desc-bottom 152 to
   card-top 207) vs. the previous 24+24=48px — both confirmed by
   direct pixel-marker overlay on the Figma render, not just metadata. */
html[data-iam-version="v4"] main.page > .hdr {
  padding-top: 32px;
  padding-bottom: 24px;
  margin-bottom: 31px;
  background: var(--iam-ads-surface);
  box-shadow: 0 0 0 100vmax var(--iam-ads-surface);
  clip-path: inset(0 -100vmax);
}
html[data-iam-version="v4"] .hdr h1,
html[data-iam-version="v4"] .au-title,
html[data-iam-version="v4"] .cr-title,
html[data-iam-version="v4"] .tm-title {
  font-family: "MultiplaneTWDC Display", "Open Sans", sans-serif;
  font-size: 30px;
  line-height: 36px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--iam-ads-text);
}
html[data-iam-version="v4"] .hdr h1 {
  /* Figma measures an 8px gap between the title baseline block and the
     description (was 4px). */
  margin: 0 0 8px;
}
html[data-iam-version="v4"] .hdr p,
html[data-iam-version="v4"] .au-subtitle,
html[data-iam-version="v4"] .cr-subtitle,
html[data-iam-version="v4"] .tm-subtitle {
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  color: var(--iam-ads-text-secondary);
  letter-spacing: 0;
}

/* Shared surfaces and top tabs. */
html[data-iam-version="v4"] .v4-card {
  border: 1px solid var(--iam-ads-divider);
  border-radius: var(--iam-ads-card-radius);
  background: var(--iam-ads-surface);
  box-shadow: var(--iam-ads-card-elevation);
}
html[data-iam-version="v4"] .au-card,
html[data-iam-version="v4"] .cr-card,
html[data-iam-version="v4"] .tm-details-card,
html[data-iam-version="v4"] .tm-members-card {
  border: 1px solid var(--iam-ads-divider);
  border-radius: var(--iam-ads-control-radius);
  background: var(--iam-ads-surface);
  box-shadow: 0 1px 4px rgba(15, 18, 20, 0.08);
}
html[data-iam-version="v4"] .v4-card .tabs-row {
  height: 44px;
  padding: 12px 16px 0;
  border-bottom: 1px solid var(--iam-ads-divider);
  background: var(--iam-ads-surface);
}
html[data-iam-version="v4"] .v4-card .tabs-row nav {
  height: 32px;
  gap: 24px;
}
html[data-iam-version="v4"] .v4-card .tab-btn {
  height: 32px;
  padding: 0 0 10px;
  align-items: center;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--iam-ads-text-muted);
  letter-spacing: 0;
}
html[data-iam-version="v4"] .v4-card .tab-btn.on {
  color: var(--iam-ads-brand);
}
html[data-iam-version="v4"] .v4-card .tab-btn.on::after {
  height: 2px;
  background: var(--iam-ads-brand);
}
html[data-iam-version="v4"] .v4-card .tab-btn:hover:not(.on) {
  color: var(--iam-ads-text);
}

/* Toolbars and buttons: Rate Card uses a 36px secondary Filter button,
   32px search/toggle controls and 36px CTAs. Toolbar min-height is fixed
   at 68px (16/8 vertical padding + Users' 44px-tall segmented control,
   the tallest control across all three toolbars) UNCONDITIONALLY for
   Users/Roles/Teams alike — not just enough to fit each panel's own
   content — so every toolbar's control line-box is exactly the same
   height everywhere. That keeps Add User / Create Role / Create Team's
   vertical center identical across tabs even though only the Users
   toolbar actually contains a 44px-tall control (Internal/External
   toggle); Roles/Teams simply center their shorter 36px controls within
   the same fixed-height row. */
html[data-iam-version="v4"] .v4-card .tbar {
  min-height: 68px;
  padding: 16px 16px 8px;
  gap: 16px;
  background: var(--iam-ads-surface);
}
html[data-iam-version="v4"] .tbar-l {
  gap: 16px;
  /* Round 23 (2026-08-11 — search-field responsive width): `.tbar-l`
     otherwise has flex-basis `auto` with no `flex-grow`, so — as a
     flex item of `.tbar` (`justify-content: space-between` against
     `.tbar-r`) — its own box only ever sized to its content's
     max-content width and never claimed the extra room that opens up
     as the card widens. Because that max-content calculation resolves
     `.ads-search`'s viewport-relative (`vw`) flex-basis to a single
     fixed value rather than re-evaluating it live, the search field
     plateaued around ~370px on screens far wider than 1440px instead
     of reaching its intended 600px ceiling. Growing `.tbar-l` sizes it
     from genuinely available space instead of max-content, which
     sidesteps that `vw`-in-intrinsic-sizing quirk; `.ads-search` itself
     keeps `flex-grow: 0` (see its own rule) so it still renders at
     its own `clamp(...)` value rather than greedily consuming 100% of
     whatever `.tbar-l` now has to offer.   Filter and the segmented
     control are unaffected — both stay `flex: 0 0 auto` / content-
     sized regardless of `.tbar-l`'s own box size. */
  flex-grow: 1;
}
/* Round 38 (2026-08-12 — Users search restored): the `#usersPanel`-only
   `flex-grow: 0` override that Round 24 added here (when Users had no
   search field left to grow around) is removed, so Users' `.tbar-l`
   goes back to sharing the Round 23 grow-to-fill behavior above with
   Roles and Teams. That is what lets `.ads-search`'s viewport-relative
   `clamp()` basis resolve against genuinely available space and reach
   its 600px ceiling at ≥1440px instead of plateauing at its
   intrinsic/max-content size. Filter and the segmented control are
   unaffected (both stay content-sized), and `.tbar`'s own
   `justify-content: space-between` still anchors Export + Add User to
   the right edge — `.tbar-l` grows into the middle of the row, it does
   not push that group anywhere. */
html[data-iam-version="v4"] .btn-std,
html[data-iam-version="v4"] .btn-ghost,
html[data-iam-version="v4"] .au-btn,
html[data-iam-version="v4"] .au-btn-cancel,
html[data-iam-version="v4"] .au-btn-save,
html[data-iam-version="v4"] .cr-btn,
html[data-iam-version="v4"] .cr-btn-cancel,
html[data-iam-version="v4"] .cr-btn-save,
html[data-iam-version="v4"] .flt-btn,
html[data-iam-version="v4"] .flt-btn-cancel,
html[data-iam-version="v4"] .flt-btn-apply {
  min-height: var(--iam-ads-button-height);
  height: var(--iam-ads-button-height);
  padding: 8px 12px;
  gap: 4px;
  border-radius: var(--iam-ads-control-radius);
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  letter-spacing: 0;
}
html[data-iam-version="v4"] .v4-card .tbar .btn-std {
  min-width: 72px;
  color: var(--iam-ads-brand);
  background: var(--iam-ads-surface);
  border: 1px solid var(--iam-ads-brand);
}
html[data-iam-version="v4"] .v4-card .tbar .btn-std:hover {
  background: var(--iam-ads-brand-wash);
}
/* Round 24 (2026-08-11 — icon-only Filter button): the Users toolbar's
   Filter control drops its "Filter" label and becomes a compact 36x36px
   square (icon-only), matching the updated Figma toolbar. (Round 24 also
   removed the adjacent search field; Round 38 restored it, but the
   icon-only Filter treatment stands on its own and is unchanged by
   that.) Scoped to the dedicated `#usersFilterBtn` id (rather than
   `.btn-std` itself)
   so it doesn't leak onto every other `.btn-std` on the page — this id
   selector's specificity wins over the shared `.tbar .btn-std` rule
   above regardless of source order. Border, colors, and hover/active/
   focus/disabled states all still come from the shared `.btn-std`
   rules; only the box's own dimensions/padding change here.

   Round 35 (2026-08-12 — Roles Filter/toolbar alignment pass): Roles'
   `#rpFilterBtn` drops its "Filter" text label too and joins this same
   rule, so both toolbars' Filter buttons are pixel-identical instances
   of the exact same icon-only `.btn-std` treatment instead of Roles
   keeping a separate, wider text-button style. */
html[data-iam-version="v4"] .v4-card .tbar #usersFilterBtn,
html[data-iam-version="v4"] .v4-card .tbar #rpFilterBtn {
  min-width: 0;
  width: 36px;
  height: 36px;
  padding: 0;
  gap: 0;
  flex-shrink: 0;
}
html[data-iam-version="v4"] .v4-card .tbar .btn-ghost,
html[data-iam-version="v4"] .au-btn-save,
html[data-iam-version="v4"] .cr-btn-save,
html[data-iam-version="v4"] .flt-btn-apply {
  color: #fff;
  background: var(--iam-ads-brand);
  border: 1px solid var(--iam-ads-brand);
  box-shadow: none;
}
html[data-iam-version="v4"] .v4-card .tbar .btn-ghost:hover,
html[data-iam-version="v4"] .au-btn-save:not(:disabled):hover,
html[data-iam-version="v4"] .cr-btn-save:not(:disabled):hover,
html[data-iam-version="v4"] .flt-btn-apply:not(:disabled):hover {
  background: var(--iam-ads-brand-hover);
  border-color: var(--iam-ads-brand-hover);
  box-shadow: none;
}
html[data-iam-version="v4"] .au-btn-save:disabled,
html[data-iam-version="v4"] .cr-btn-save:disabled,
html[data-iam-version="v4"] .flt-btn-apply:disabled {
  color: rgba(30, 37, 40, 0.38);
  background: rgba(30, 37, 40, 0.06);
  border-color: transparent;
  opacity: 1;
  box-shadow: none;
}

/* Search, toggle groups and all form controls. */
html[data-iam-version="v4"] .search input,
html[data-iam-version="v4"] .au-input,
html[data-iam-version="v4"] .cr-input,
html[data-iam-version="v4"] .cr-textarea,
html[data-iam-version="v4"] .flt-input,
html[data-iam-version="v4"] .flt-select,
html[data-iam-version="v4"] .edl-combo-input,
html[data-iam-version="v4"] .cr-dd-trigger,
html[data-iam-version="v4"] .au-role-multi-trigger {
  min-height: var(--iam-ads-control-height);
  border: 1px solid var(--iam-ads-border);
  border-radius: var(--iam-ads-control-radius);
  background-color: var(--iam-ads-surface);
  color: var(--iam-ads-text);
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  letter-spacing: 0;
}
html[data-iam-version="v4"] .search input {
  height: var(--iam-ads-control-height);
  padding: 0 36px 0 12px;
}
html[data-iam-version="v4"] .search input:hover,
html[data-iam-version="v4"] .au-input:hover,
html[data-iam-version="v4"] .cr-input:hover,
html[data-iam-version="v4"] .cr-textarea:hover,
html[data-iam-version="v4"] .flt-input:hover,
html[data-iam-version="v4"] .edl-combo-input:hover,
html[data-iam-version="v4"] .cr-dd-trigger:hover {
  border-color: var(--iam-ads-text-muted);
}
html[data-iam-version="v4"] .search input:focus,
html[data-iam-version="v4"] .au-input:focus,
html[data-iam-version="v4"] .cr-input:focus,
html[data-iam-version="v4"] .cr-textarea:focus,
html[data-iam-version="v4"] .flt-input:focus,
html[data-iam-version="v4"] .edl-combo-input:focus,
html[data-iam-version="v4"] .cr-dd-trigger:focus-visible {
  border-color: var(--iam-ads-brand);
  box-shadow: 0 0 0 1px var(--iam-ads-brand);
  outline: 0;
}
html[data-iam-version="v4"] .au-input:disabled,
html[data-iam-version="v4"] .au-input[readonly],
/* External Edit User's Company display is a <div>, so it can't match
   `[readonly]`; it takes the same read-only fill by class instead. */
html[data-iam-version="v4"] .au-field-team-readonly,
html[data-iam-version="v4"] .cr-input:disabled,
html[data-iam-version="v4"] .edl-combo-input:disabled {
  color: rgba(30, 37, 40, 0.55);
  background: rgba(30, 37, 40, 0.04);
  border-color: var(--iam-ads-divider);
  opacity: 1;
}
html[data-iam-version="v4"] .au-label,
html[data-iam-version="v4"] .cr-label,
html[data-iam-version="v4"] .flt-label,
html[data-iam-version="v4"] .field-label {
  margin-bottom: 4px;
  color: var(--iam-ads-text-secondary);
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  line-height: 18px;
  font-weight: 500;
  letter-spacing: 0;
}
/* Final-QA pass against Figma 770:17428's rendered screenshot: the
   Internal/External track is a light neutral wash (`--iam-ads-canvas`,
   the same token the page background already uses) with the SELECTED
   segment reading as a raised white chip (`--iam-ads-surface` + a soft
   shadow) and dark primary text — not a brand-tinted chip. The previous
   brand-wash/brand-text treatment doesn't appear anywhere in the Figma
   reference; it was likely carried over from `.seg-btn.on`'s original
   (pre-ADS) styling below. Height now matches every other toolbar
   control's `--iam-ads-button-height` (36px) instead of the smaller
   generic `--iam-ads-control-height` (32px) used by other, shorter
   controls like the row-status segmented filter, so Internal/External
   shares the same toolbar centerline as Filter/Search/Export/Add User
   (Step 10 of the audit). */
html[data-iam-version="v4"] .seg-ctrl {
  min-height: var(--iam-ads-button-height);
  padding: 2px;
  border: 1px solid var(--iam-ads-border);
  border-radius: var(--iam-ads-control-radius);
  background: var(--iam-ads-canvas);
}
html[data-iam-version="v4"] .au-status-seg {
  min-height: var(--iam-ads-control-height);
  padding: 1px;
  border: 1px solid var(--iam-ads-border);
  border-radius: var(--iam-ads-control-radius);
  background: var(--iam-ads-surface);
}
html[data-iam-version="v4"] .seg-btn {
  min-height: 100%;
  border-radius: 5px;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: var(--iam-ads-text-secondary);
}
html[data-iam-version="v4"] .au-status-opt {
  min-height: 28px;
  border-radius: 5px;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
}
html[data-iam-version="v4"] .seg-btn.on {
  color: var(--iam-ads-text);
  background: var(--iam-ads-surface);
  box-shadow: var(--iam-ads-card-elevation);
}
html[data-iam-version="v4"] .au-status-opt.is-selected {
  color: var(--iam-ads-brand);
  background: var(--iam-ads-brand-wash);
  box-shadow: none;
}

/* Tables: opaque 48px rows and 32px headers, matching ADS Table and
   Rate Card's practical implementation. */
html[data-iam-version="v4"] .v4-card .tbl thead tr,
html[data-iam-version="v4"] .v4-card .tbl thead th {
  height: 32px;
  background: var(--iam-ads-surface);
  border-color: var(--iam-ads-divider);
}
html[data-iam-version="v4"] .tbl thead th {
  padding: 0 8px;
  color: var(--iam-ads-text-muted);
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  line-height: 18px;
  font-weight: 400;
  letter-spacing: 0;
}
/* Final-QA correction — the Name column's avatar must share its left
   edge with the "Name" header label directly above it (same shared
   column padding, per the audit). `.tbl thead th`'s own `padding: 0 8px`
   right above is what actually positions "Name" text today (the old
   `th.c-nm { padding-left: 32px }` base rule was already dead — this
   higher-specificity rule has won since the header-padding unification
   pass); `.name-cell`'s base rule still carried the pre-unification 32px
   left inset for the avatar, 24px further right than the header ever
   renders now. Bringing both to the identical 8px removes that drift
   instead of bumping the header back out to 32px (which would make
   "Name" the only column not sharing every other header's 8px baseline). */
html[data-iam-version="v4"] .v4-card .tbl tbody .name-cell {
  padding-left: 8px;
}
html[data-iam-version="v4"] .tbl tbody tr {
  height: 48px;
  background: var(--iam-ads-surface);
  border-bottom: 1px solid var(--iam-ads-divider);
}
html[data-iam-version="v4"] .tbl tbody tr:hover:not(.is-selected):not([aria-selected="true"]) {
  background: #f7f7fb;
}
html[data-iam-version="v4"] .tbl tbody td {
  padding: 8px;
  color: var(--iam-ads-text-secondary);
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  letter-spacing: 0;
}
html[data-iam-version="v4"] .tbl .name-link,
html[data-iam-version="v4"] .tbl .rp-role-link,
html[data-iam-version="v4"] .tbl .tm-name-link {
  color: var(--iam-ads-brand);
  font-weight: 500;
}
html[data-iam-version="v4"] .tbl .name-email,
html[data-iam-version="v4"] .tbl .row-email {
  color: var(--iam-ads-text-muted);
  font-size: 12px;
  line-height: 18px;
  font-weight: 400;
}

/* Pagination. */
html[data-iam-version="v4"] .v4-card .pgn {
  min-height: 52px;
  height: 52px;
  padding: 8px 16px;
  gap: 16px;
  border-top: 1px solid var(--iam-ads-divider);
  background: var(--iam-ads-surface);
}
html[data-iam-version="v4"] .pgn-lbl,
html[data-iam-version="v4"] .pgn .cr-dd-trigger {
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  line-height: 18px;
  font-weight: 400;
  color: var(--iam-ads-text);
}
html[data-iam-version="v4"] .pgn .pg-nav,
html[data-iam-version="v4"] .pgn .pg-n {
  width: 32px;
  min-width: 32px;
  height: 32px;
  border: 1px solid var(--iam-ads-border);
  border-radius: var(--iam-ads-control-radius);
  background: var(--iam-ads-surface);
  color: var(--iam-ads-text-secondary);
  box-shadow: none;
}
html[data-iam-version="v4"] .pgn .pg-n.on,
html[data-iam-version="v4"] .pgn .pg-n[aria-current] {
  color: #fff;
  background: var(--iam-ads-brand);
  border-color: var(--iam-ads-brand);
}
html[data-iam-version="v4"] .pgn .pg-nav:hover:not(.off),
html[data-iam-version="v4"] .pgn .pg-n:hover:not(.on) {
  color: var(--iam-ads-brand);
  background: var(--iam-ads-brand-wash);
  border-color: var(--iam-ads-brand);
}
html[data-iam-version="v4"] .pgn .pg-nav.off {
  color: rgba(30, 37, 40, 0.28);
  background: var(--iam-ads-surface);
  border-color: var(--iam-ads-divider);
  opacity: 1;
}

/* Accordions / section triggers. */
html[data-iam-version="v4"] .cr-section-header {
  min-height: 44px;
  color: var(--iam-ads-brand);
  background: transparent;
}
html[data-iam-version="v4"] .cr-section-header:hover,
html[data-iam-version="v4"] .cr-section-header:focus-visible {
  color: var(--iam-ads-brand-hover);
  background: transparent;
}
html[data-iam-version="v4"] .cr-section-title {
  font-family: "Open Sans", sans-serif;
  font-size: 16px;
  line-height: 24px;
  font-weight: 600;
  letter-spacing: 0;
}

/* Dropdown, menu and popover chrome. */
html[data-iam-version="v4"] .edl-combo-menu,
html[data-iam-version="v4"] .cr-dd-menu,
html[data-iam-version="v4"] .search-dropdown,
html[data-iam-version="v4"] .func-popover,
html[data-iam-version="v4"] .user-menu-pop,
html[data-iam-version="v4"] .user-menu-sub {
  border: 1px solid var(--iam-ads-divider);
  border-radius: var(--iam-ads-control-radius);
  background: var(--iam-ads-surface);
  box-shadow: var(--iam-ads-menu-elevation);
}
html[data-iam-version="v4"] .edl-combo-item:hover,
html[data-iam-version="v4"] .cr-dd-option:hover,
html[data-iam-version="v4"] .user-menu-row:hover,
html[data-iam-version="v4"] .user-menu-sub-item:hover {
  background: #f3f3f3;
}
html[data-iam-version="v4"] .edl-combo-item.is-selected,
html[data-iam-version="v4"] .cr-dd-option.is-selected,
html[data-iam-version="v4"] .user-menu-sub-item.is-selected {
  color: var(--iam-ads-brand);
  background: var(--iam-ads-brand-wash);
}

/* Filter sheets. */
html[data-iam-version="v4"] .flt-drawer {
  width: 360px;
  max-width: 100vw;
  background: var(--iam-ads-surface);
  border-right: 1px solid var(--iam-ads-divider);
  box-shadow: 4px 0 24px rgba(15, 18, 20, 0.18);
}
html[data-iam-version="v4"] .flt-header {
  min-height: 56px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--iam-ads-divider);
}
html[data-iam-version="v4"] .flt-title {
  font-family: "MultiplaneTWDC Display", "Open Sans", sans-serif;
  font-size: 20px;
  line-height: 24px;
  font-weight: 500;
  color: var(--iam-ads-text);
}
html[data-iam-version="v4"] .flt-body {
  padding: 20px;
}
html[data-iam-version="v4"] .flt-footer {
  min-height: 64px;
  padding: 12px 20px;
  border-top: 1px solid var(--iam-ads-divider);
}
html[data-iam-version="v4"] .flt-overlay {
  background: rgba(15, 18, 20, 0.40);
}

/* Modal and dialog family. */
html[data-iam-version="v4"] .cr-confirm-dialog,
html[data-iam-version="v4"] .edl-modal,
html[data-iam-version="v4"] .tm-add-modal,
html[data-iam-version="v4"] .au-eff-breakdown {
  width: 480px;
  max-width: calc(100vw - 48px);
  border: 1px solid var(--iam-ads-divider);
  border-radius: var(--iam-ads-dialog-radius);
  background: var(--iam-ads-surface);
  box-shadow: var(--iam-ads-dialog-elevation);
  overflow: hidden;
}
html[data-iam-version="v4"] .cr-confirm-backdrop,
html[data-iam-version="v4"] .edl-modal-backdrop {
  background: rgba(15, 18, 20, 0.40);
}
html[data-iam-version="v4"] .cr-confirm-header,
html[data-iam-version="v4"] .edl-modal-header {
  padding: 20px 24px;
}
html[data-iam-version="v4"] .cr-confirm-body,
html[data-iam-version="v4"] .edl-modal-body {
  padding: 0 24px 20px;
}
html[data-iam-version="v4"] .cr-confirm-actions,
html[data-iam-version="v4"] .edl-modal-footer {
  padding: 16px 24px;
  gap: 12px;
  border-top: 1px solid var(--iam-ads-divider);
}

/* ─── ADS Modal (Figma 38:46, Ads Design System) ────────────────────
   `.cr-confirm-dialog--modal` opts a single confirm dialog into the
   full header/body/footer region layout instead of the flat
   single-panel default. Only Revoke access uses this today; every
   other `.cr-confirm-dialog` (Remove Role, Remove User, Set Inactive,
   permission-group delete, etc.) keeps its current flat 24px padding
   untouched — this modifier only zeroes padding on the dialogs that
   opt in, so nothing else can regress. */
html[data-iam-version="v4"] .cr-confirm-dialog.cr-confirm-dialog--modal {
  padding: 0;
}
html[data-iam-version="v4"] .cr-confirm-dialog--modal .cr-confirm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 1px solid var(--iam-ads-divider);
}
html[data-iam-version="v4"] .cr-confirm-dialog--modal .cr-confirm-header .cr-confirm-title {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
}
html[data-iam-version="v4"] .cr-confirm-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  border-radius: 3px;
  background: transparent;
  color: var(--iam-ads-text-muted);
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s ease, color 0.15s ease;
}
html[data-iam-version="v4"] .cr-confirm-close:hover {
  background: rgba(15, 18, 20, 0.06);
  color: var(--iam-ads-text);
}
html[data-iam-version="v4"] .cr-confirm-close:focus-visible {
  outline: 2px solid var(--iam-ads-brand);
  outline-offset: 2px;
}
html[data-iam-version="v4"] .cr-confirm-close:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
/* Body region — one 24px/16px ADS gutter (`--modal/size/padding`,
   `--modal/size/body/padding-y`) shared by the explanatory text and
   the inline error message, so both sit on the same left/right guide
   as the header title and footer buttons above/below. */
html[data-iam-version="v4"] .cr-confirm-body-region {
  padding: 16px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
html[data-iam-version="v4"] .cr-confirm-text {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 20px;
  color: var(--iam-ads-text-secondary);
}
/* Error state — kept inline in the body region (not a full-body
   takeover) per "do not replace the entire modal body with a
   spinner/error unless the ADS pattern requires it." Modal stays
   open, dimensions stable, Cancel/Close remain available to retry. */
html[data-iam-version="v4"] .cr-confirm-error {
  margin: 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  background: #FCEEEF;
  color: var(--ads-red-400, #AF434E);
  font-family: var(--ff);
  font-size: 13px;
  line-height: 18px;
}
html[data-iam-version="v4"] .cr-confirm-error[hidden] {
  display: none;
}
/* Confirm-button loading state — same spinner-swap pattern already
   used by the Export button (`.au-export-btn.is-loading`, see the
   "Prototype-only 'preparing export'" block above): the spinner
   occupies the same slot the icon/label would, so the button's size
   and the modal's dimensions never shift while busy. `gap` is safe to
   add to the shared `.cr-btn-danger-solid` rule because it only
   affects spacing between visible flex children — with the spinner
   hidden (every other confirm dialog using this class), there is only
   one visible child and gap has no effect. */
html[data-iam-version="v4"] .cr-btn-danger-solid {
  gap: 6px;
}
html[data-iam-version="v4"] .cr-btn-danger-solid .au-revoke-confirm-spinner {
  display: none;
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
}
html[data-iam-version="v4"] .cr-btn-danger-solid.is-loading .au-revoke-confirm-spinner {
  display: block;
  animation: simExportSpin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  html[data-iam-version="v4"] .cr-btn-danger-solid.is-loading .au-revoke-confirm-spinner { animation: none; }
}

/* ─── Add User modal (Figma 1023:22290 Step 1 / 1023:22735 Step 2) ───
   Shares `.cr-confirm-dialog--modal`'s header/divider/body/divider/
   footer regions (see above) — only the body contents below are new.
   `.au-adduser-dialog` does not change width/radius/elevation, it only
   lets the body scroll instead of the whole viewport growing when the
   dropdown is open with 10 results. */
html[data-iam-version="v4"] .au-adduser-dialog {
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 96px);
}
html[data-iam-version="v4"] .au-adduser-body {
  overflow-y: auto;
  gap: 16px;
}

/* ─── Effective access breakdown modal — sizing ──────────────────────
   `.au-eff-breakdown-dialog` widens the shared `.cr-confirm-dialog`
   shell to the ADS Modal "Large" size (640px — the Modal component's
   own Figma description lists "Sizes: Default (480px), Large
   (640px)") because the two-column function/permission breakdown
   needs more horizontal room than the 480px default. It changes
   nothing else: radius, border, elevation, and header/body/footer
   padding all come from the shared `.cr-confirm-dialog` /
   `.cr-confirm-dialog--modal` rules above, so this modal stays
   visually identical to every other ADS modal in the app apart from
   width. The body region scrolls as a single unit (subtitle +
   assigned-role summary + application groups together) while the
   header and footer stay fixed — "scroll only the modal body". */
html[data-iam-version="v4"] .au-eff-breakdown-dialog {
  width: 100%;
  max-width: min(640px, calc(100vw - 48px));
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 96px);
}
html[data-iam-version="v4"] .au-eff-breakdown-dialog .cr-confirm-body-region {
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}

/* Step heading — Figma nodes 1023:22290 (Step 1) / 1023:22735 (Step 2)
   author the step indicator as a single bold 16px/22px line ("Step 1
   of 2") that doubles as the step heading — there is no separate
   small-caps caption or repeated "Select user" title beneath it. The
   descriptive step name ("Select user" / "Review user") is kept as an
   sr-only suffix so screen reader users still get it, without adding
   a second visible heading Figma doesn't show. */
html[data-iam-version="v4"] .au-adduser-heading {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
html[data-iam-version="v4"] .au-adduser-step {
  margin: 0;
  font-family: var(--ff);
  font-size: 16px;
  line-height: 22px;
  font-weight: 700;
  color: var(--iam-ads-text-secondary);
}
html[data-iam-version="v4"] .au-adduser-heading-sub {
  margin: 0;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 20px;
  color: var(--iam-ads-text-secondary);
}
html[data-iam-version="v4"] .au-adduser-search-wrap { position: relative; }
/* `.au-adduser-search` (the `.ads-search` pill itself, not the outer
   `-wrap` that also contains the results dropdown below it) is the
   clear button's positioning container — see `#auAddUserSearchClear`
   below. `.ads-search` already sets `position: relative` as its base
   rule, this just documents/guarantees it for this instance. */
html[data-iam-version="v4"] .au-adduser-search { width: 100%; position: relative; }
html[data-iam-version="v4"] .au-adduser-search-icon { flex-shrink: 0; color: var(--iam-ads-text-muted); }
html[data-iam-version="v4"] .au-adduser-search-input {
  border: 0;
  outline: none;
  flex: 1 0 auto;
  min-width: 0;
  background: transparent;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 20px;
  color: var(--iam-ads-text);
}
/* Reserve room for the 24px clear button (positioned 12px from the
   right edge — see #auAddUserSearchClear) so entered text never runs
   underneath it once the button is taken out of flex flow. Needs both
   the ID selector AND `!important`: several later `.ads-search >
   input { padding: 0px !important }` resets (written for the
   icon-hiding/text-alignment rounds on the *other* `.ads-search`
   fields) also match this input and would otherwise win outright
   over any non-`!important` declaration, regardless of specificity. */
html[data-iam-version="v4"] #auAddUserSearchInput,
html[data-iam-version="v4"] #tmAddMembersSearch {
  padding-right: 44px !important;
}
html[data-iam-version="v4"] .au-adduser-search-input::placeholder { color: var(--text-placeholder); }
html[data-iam-version="v4"] .au-adduser-search-spinner {
  flex: 0 0 auto;
  color: var(--iam-ads-text-muted);
  animation: simExportSpin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  html[data-iam-version="v4"] .au-adduser-search-spinner { animation: none; }
}
/* Round 26 (2026-08-11 — floating clear button): pin the clear "X" to
   the search-field container (`.au-adduser-search`, above) with
   absolute positioning + `translateY(-50%)`, rather than relying on
   flex order/centering, so it's always dead-centered on the 36px input
   regardless of sibling content and never anchored to
   `.au-adduser-search-wrap` (which also wraps the results dropdown
   underneath). `#auAddUserSearchClear` is used (rather than the
   `.au-adduser-search-clear` class) purely for guaranteed specificity
   over the shared `.ads-search .search-clear` flex-centering rule. */
html[data-iam-version="v4"] #auAddUserSearchClear,
html[data-iam-version="v4"] #tmAddMembersSearchClear {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
  min-width: 24px;
  min-height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
}
/* The base `.search-clear { display: inline-flex }` rule (shared with
   other search bars) and a global `svg { display: block }` reset tie
   the native `[hidden]` UA rule on specificity, so the later
   same-specificity author rule wins and the icon stays visible even
   with the `hidden` attribute set. Force it here, scoped to the Add
   User combobox only. */
html[data-iam-version="v4"] .au-adduser-search-clear[hidden],
html[data-iam-version="v4"] .au-adduser-search-spinner[hidden] {
  display: none !important;
}

/* Dropdown — ADS combobox popup: listbox of compact result rows,
   capped at 10 visible, with an optional restrained "Showing 10 of N"
   / empty / error line under the list.
   `position: fixed` (not `absolute`) is intentional: `.au-adduser-body`
   scrolls internally on short viewports, and an absolutely-positioned
   popover anchored inside a scrolling ancestor gets clipped to that
   ancestor's visible box the moment the body is shorter than the
   dropdown. Fixed positioning — with left/top/width computed in JS via
   `auAddUserPositionDropdown()` from the search field's live
   bounding box — lets the popover escape that clip and always render
   in full, which is the standard technique for combobox/menu popovers
   that must outlive a constrained-height container. */
html[data-iam-version="v4"] .au-adduser-dropdown {
  position: fixed;
  z-index: 10001;
  background: var(--iam-ads-surface);
  border: 1px solid var(--iam-ads-divider);
  border-radius: var(--iam-ads-control-radius);
  box-shadow: var(--iam-ads-menu-elevation);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Same same-specificity `[hidden]` vs. `display: flex` conflict as the
   search clear/spinner icons above — without this, closing the
   dropdown (on selection, Escape, or blur) leaves the last-rendered
   result list fully visible, floating over whatever renders next
   (e.g. the Selected user preview). */
html[data-iam-version="v4"] .au-adduser-dropdown[hidden] {
  display: none !important;
}
html[data-iam-version="v4"] .au-adduser-listbox {
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 336px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
html[data-iam-version="v4"] .au-adduser-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 6px;
  cursor: pointer;
}
html[data-iam-version="v4"] .au-adduser-option:hover:not(.is-disabled) { background: var(--row-hover, rgba(54, 17, 200, 0.04)); }
html[data-iam-version="v4"] .au-adduser-option.is-active:not(.is-disabled) { background: var(--brand-bg-soft); }
html[data-iam-version="v4"] .au-adduser-option[aria-selected="true"] { background: var(--brand-bg-soft); }
/* Selection is never color-only: the currently selected user also gets a
   check glyph in the row, so it stays legible if this row is also the
   keyboard-highlighted one (same soft background) or for users who
   can't distinguish the tint. */
html[data-iam-version="v4"] .au-adduser-option-check {
  flex: 0 0 auto;
  color: var(--iam-ads-brand);
  margin-left: 2px;
}
html[data-iam-version="v4"] .au-adduser-option.is-disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
html[data-iam-version="v4"] .au-adduser-option-avatar { flex: 0 0 auto; }
html[data-iam-version="v4"] .au-adduser-option-avatar .name-avatar { width: 32px; height: 32px; }
html[data-iam-version="v4"] .au-adduser-option-avatar .avatar-initials { font-size: 12px; }
html[data-iam-version="v4"] .au-adduser-option-info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
html[data-iam-version="v4"] .au-adduser-option-name {
  font-family: var(--ff);
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--iam-ads-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
html[data-iam-version="v4"] .au-adduser-option-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
html[data-iam-version="v4"] .au-adduser-option-email {
  font-family: var(--ff);
  font-size: 13px;
  line-height: 18px;
  color: var(--iam-ads-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Round 26: only rendered for candidates who can still be added (see
   auAddUserRenderOptionHtml in app.js — already-in-IAM rows hide Team
   entirely since the "Already has access" badge already covers that
   state), so semibold here always means "addable, here's their team". */
html[data-iam-version="v4"] .au-adduser-option-team {
  flex: 0 1 108px;
  min-width: 0;
  max-width: 108px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--ff);
  font-size: 12px;
  line-height: 18px;
  font-weight: 600;
  color: var(--iam-ads-text-secondary);
  text-align: right;
}
html[data-iam-version="v4"] .au-adduser-option-badge {
  flex: 0 1 auto;
  min-width: 0;
  /* Round 26: widened from 128px now that Team is never shown alongside
     this badge (see auAddUserRenderOptionHtml) — "Already has access"
     has full room to render without truncating. */
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 2px 8px;
  border-radius: 100px;
  background: var(--bg-hover-soft);
  color: var(--iam-ads-text-muted);
  font-family: var(--ff);
  font-size: 11px;
  font-weight: 600;
  line-height: 16px;
  white-space: nowrap;
}
html[data-iam-version="v4"] .au-adduser-option-check {
  flex: 0 0 auto;
  color: var(--iam-ads-brand);
}
html[data-iam-version="v4"] .au-adduser-dd-note {
  margin: 0;
  padding: 8px 12px;
  border-top: 1px solid var(--iam-ads-divider);
  font-family: var(--ff);
  font-size: 12px;
  line-height: 16px;
  color: var(--iam-ads-text-muted);
}
html[data-iam-version="v4"] .au-adduser-dd-note.is-error {
  color: var(--ads-red-400, #AF434E);
}
html[data-iam-version="v4"] .au-adduser-dd-note[hidden] { display: none; }

/* Selected-user preview (Figma 1023:22735, Step 1) — compact
   avatar+text row directly on the modal body, no card border or
   tinted background. This is the only selected-user rendering the
   modal shows now; the former "Step 2, detailed" variant (a larger
   64px-avatar card with Employee ID/Region/Timezone/Department/User
   type/Status rows, `.is-detailed`) was the in-modal review screen
   removed by the 2026-08-10 flow change — that full record now shows
   once, on the Add User page's Basic Information section, never a
   second time in this modal. The distinct `.au-adduser-selected-check`
   badge (not a color-only cue) marks the row as selected. */
html[data-iam-version="v4"] .au-adduser-selected { display: flex; flex-direction: column; gap: 8px; }
html[data-iam-version="v4"] .au-adduser-selected[hidden] { display: none; }
html[data-iam-version="v4"] .au-adduser-selected-label {
  margin: 0;
  font-family: var(--ff);
  font-size: 16px;
  line-height: 22px;
  font-weight: 700;
  color: var(--iam-ads-text-secondary);
}
html[data-iam-version="v4"] .au-adduser-selected-card {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}
html[data-iam-version="v4"] .au-adduser-selected-card .name-avatar { width: 40px; height: 40px; flex-shrink: 0; }
html[data-iam-version="v4"] .au-adduser-selected-card .avatar-initials { font-size: 14px; }
html[data-iam-version="v4"] .au-adduser-selected-info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}
html[data-iam-version="v4"] .au-adduser-selected-text { min-width: 0; }
html[data-iam-version="v4"] .au-adduser-selected-name {
  display: block;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 20px;
  font-weight: 700;
  color: var(--gray-95, #171c20);
  overflow-wrap: anywhere;
}
html[data-iam-version="v4"] .au-adduser-selected-row {
  display: block;
  font-family: var(--ff);
  font-size: 14px;
  line-height: 20px;
  color: var(--gray-95, #171c20);
  overflow-wrap: anywhere;
}
html[data-iam-version="v4"] .au-adduser-selected-check {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--iam-ads-brand);
  color: #fff;
}
html[data-iam-version="v4"] .au-adduser-duplicate {
  margin: 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  background: #FCEEEF;
  color: var(--ads-red-400, #AF434E);
  font-family: var(--ff);
  font-size: 13px;
  line-height: 18px;
}
html[data-iam-version="v4"] .au-adduser-duplicate[hidden] { display: none; }
html[data-iam-version="v4"] .au-adduser-duplicate-link {
  background: none;
  border: none;
  padding: 0;
  margin-left: 4px;
  color: var(--ads-red-400, #AF434E);
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
  font-family: var(--ff);
  font-size: 13px;
}

html[data-iam-version="v4"] .au-adduser-actions { align-items: center; }
html[data-iam-version="v4"] .au-adduser-actions-spacer { flex: 1 1 auto; }

@media (max-width: 640px) {
  html[data-iam-version="v4"] .au-adduser-dialog { max-height: calc(100vh - 32px); }
  html[data-iam-version="v4"] .au-eff-breakdown-dialog { max-height: calc(100vh - 32px); }
}

/* ─── Add User page: "no employee selected" empty state ─────────────
   Add-mode-only fallback for Basic Information when the two-step
   search modal hasn't produced a selection yet (Figma 1023:22053 has
   no dedicated empty-state node — this is the ADS-approved treatment:
   dashed neutral avatar placeholder + explanatory copy + a button
   that reopens the same search modal the "Add User" list action
   uses). Replaces `.au-edit-row` 1:1 in the same card slot so the
   card's height/padding stay stable whichever state is showing. */
html[data-iam-version="v4"] .au-id-empty {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 0 8px 0;
  min-width: 0;
}
html[data-iam-version="v4"] .au-id-empty[hidden] { display: none; }
html[data-iam-version="v4"] .au-id-empty-avatar {
  flex: 0 0 64px;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1.5px dashed var(--iam-ads-divider, #d4dee3);
  color: var(--iam-ads-text-muted, #8498a9);
  background: var(--bg-hover-soft);
}
html[data-iam-version="v4"] .au-id-empty-meta {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
html[data-iam-version="v4"] .au-id-empty-title {
  font-family: var(--ff);
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
  color: var(--iam-ads-text, #171c20);
}
html[data-iam-version="v4"] .au-id-empty-sub {
  font-family: var(--ff);
  font-size: 13px;
  font-weight: 400;
  line-height: 18px;
  color: var(--iam-ads-text-secondary, #526374);
  max-width: 46ch;
}
html[data-iam-version="v4"] .au-id-empty-btn {
  flex: 0 0 auto;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 8px 16px;
  border: 1px solid var(--iam-ads-brand, #4045c2);
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  color: var(--iam-ads-brand, #4045c2);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
html[data-iam-version="v4"] .au-id-empty-btn:hover { background: rgba(64, 69, 194, 0.08); }
html[data-iam-version="v4"] .au-id-empty-btn:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
@media (max-width: 1000px) {
  html[data-iam-version="v4"] .au-id-empty { flex-wrap: wrap; }
}

/* Tooltip and toast families. */
html[data-iam-version="v4"] .edl-tooltip,
html[data-iam-version="v4"] .edl-status-tooltip {
  padding: 6px 10px;
  border: 0;
  border-radius: var(--iam-ads-control-radius);
  background: var(--iam-ads-text);
  color: #fff;
  box-shadow: var(--iam-ads-menu-elevation);
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  line-height: 18px;
  font-weight: 400;
}
html[data-iam-version="v4"] .v4-card .tab-btn.on {
  font-weight: 600;
}
/* ═══════════════════════════════════════════════════════════════════
   R52 — Toast (ADS Toast, Figma 70:62)

   Global container sits above normal page content but below the
   Redline workspace overlay (z-index 999999, see redline.css), clears
   the fixed navbar (56px tall) with a 24px gap — matching the ADS
   screen-edge offset (24px) already used on the right. `.edl-toast`
   itself is a
   single flex row — icon, content column, close — left-bordered 5px
   in the semantic color with no border on the other 3 sides, 6px
   radius, 16px padding on every side, and the elevation/30 shadow.
   Message text is always toast/text/primary regardless of variant.
   The headline, icon, left border AND close glyph all carry the
   variant's semantic color — the exported Toast assets from node
   70:62 render a tinted close "x" per instance (e.g. the Error
   instance's close glyph is `#993B44`, matching its headline), so the
   close button is tinted to match rather than left neutral; it still
   shares the 32×32 ADS icon-button hit target/hover/active/focus
   states with `.flt-close`/`.edl-modal-close` below. */
html[data-iam-version="v4"] .edl-toast-container {
  top: 80px;
  right: 24px;
  gap: 8px;
}
html[data-iam-version="v4"] .edl-toast {
  box-sizing: border-box;
  width: 400px;
  max-width: calc(100vw - 48px);
  min-height: 56px;
  padding: var(--iam-ads-toast-padding);
  gap: var(--iam-ads-toast-content-gap);
  border: 0;
  border-left: var(--iam-ads-toast-border-width) solid var(--iam-ads-toast-border-info);
  border-radius: var(--iam-ads-toast-radius);
  background: var(--iam-ads-toast-surface);
  box-shadow: var(--iam-ads-toast-elevation);
}
html[data-iam-version="v4"] .edl-toast-content {
  gap: var(--iam-ads-toast-text-gap);
}
html[data-iam-version="v4"] .edl-toast-title {
  font-weight: 700;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0;
  color: var(--iam-ads-toast-text-info);
}
html[data-iam-version="v4"] .edl-toast-body {
  font-size: 14px;
  line-height: 20px;
  color: var(--iam-ads-toast-text-body);
}
/* Semantic left-border + headline color per variant. Message stays
   toast/text/primary (rule above) in every variant — status is never
   communicated by the accent color alone, since the icon shape and
   headline text always repeat it too. */
html[data-iam-version="v4"] .edl-toast--error {
  border-left-color: var(--iam-ads-toast-border-error);
}
html[data-iam-version="v4"] .edl-toast--error .edl-toast-title {
  color: var(--iam-ads-toast-text-error);
}
html[data-iam-version="v4"] .edl-toast--warning {
  border-left-color: var(--iam-ads-toast-border-warning);
}
html[data-iam-version="v4"] .edl-toast--warning .edl-toast-title {
  color: var(--iam-ads-toast-text-warning);
}
html[data-iam-version="v4"] .edl-toast--success {
  border-left-color: var(--iam-ads-toast-border-success);
}
html[data-iam-version="v4"] .edl-toast--success .edl-toast-title {
  color: var(--iam-ads-toast-text-success);
}
html[data-iam-version="v4"] .edl-toast--informative {
  border-left-color: var(--iam-ads-toast-border-info);
}
html[data-iam-version="v4"] .edl-toast--informative .edl-toast-title {
  color: var(--iam-ads-toast-text-info);
}
/* Icon AND close-glyph color always match the variant's headline
   color (all four are fill-based `fill="currentColor"` inline SVGs
   exported directly from the node 70:62 instances). The close button
   still inherits its 32×32 hit target and hover/active/focus-visible
   states from the shared `.flt-close`/`.edl-modal-close` rule below —
   only `color` (the glyph tint) is overridden here, per variant. */
html[data-iam-version="v4"] .edl-toast--error .edl-toast-icon,
html[data-iam-version="v4"] .edl-toast--error .edl-toast-close       { color: var(--iam-ads-toast-text-error); }
html[data-iam-version="v4"] .edl-toast--warning .edl-toast-icon,
html[data-iam-version="v4"] .edl-toast--warning .edl-toast-close     { color: var(--iam-ads-toast-text-warning); }
html[data-iam-version="v4"] .edl-toast--success .edl-toast-icon,
html[data-iam-version="v4"] .edl-toast--success .edl-toast-close     { color: var(--iam-ads-toast-text-success); }
html[data-iam-version="v4"] .edl-toast--informative .edl-toast-icon,
html[data-iam-version="v4"] .edl-toast--informative .edl-toast-close { color: var(--iam-ads-toast-text-info); }

/* Compact/narrow viewports: keep the ADS screen gutter, let the toast
   shrink to fit instead of the container overflowing horizontally,
   and let title/message wrap naturally (already the default — no
   nowrap/truncation is applied anywhere in this component). */
@media (max-width: 480px) {
  html[data-iam-version="v4"] .edl-toast-container {
    left: 16px;
    right: 16px;
    top: 80px;
    max-width: none;
  }
  html[data-iam-version="v4"] .edl-toast {
    width: 100%;
    max-width: 100%;
  }
}

/* Edit User grid: the "avoid the legacy fixed 296px tracks overflowing
   at 1024px" override that used to live here is gone. Its two jobs —
   giving the identity column a `minmax(240px, 296px)` range and letting
   the identity block/fields fill their own tracks — are now the base
   behavior of `#auBasicCard .au-section-body` for BOTH modes, and its
   `(min-width: 769px)` floor would have re-forced three columns
   underneath the shared 900px two-column stage. See the "Responsive
   stages" block next to that grid definition. */

@media (max-width: 768px) {
  html[data-iam-version="v4"] main.page > .hdr {
    padding-top: 20px;
    padding-bottom: 20px;
    margin-bottom: 16px;
  }
  html[data-iam-version="v4"] .hdr h1,
  html[data-iam-version="v4"] .au-title,
  html[data-iam-version="v4"] .cr-title,
  html[data-iam-version="v4"] .tm-title {
    font-size: 26px;
    line-height: 32px;
  }
  html[data-iam-version="v4"] .v4-card {
    border-radius: 12px;
  }
  html[data-iam-version="v4"] .v4-card .tbar {
    padding: 12px;
  }
  html[data-iam-version="v4"] .v4-card .pgn {
    height: auto;
    min-height: 52px;
    padding: 8px 12px;
  }
  /* The Edit-mode-only "collapse #auBasicCard to one column at 768px"
     override that used to live here is gone: collapsing at 768 in Edit
     mode while Add mode still showed two columns made the two flows
     reflow differently from identical markup. Both now follow the
     shared responsive stages beside the grid definition (two form
     columns down to 600px, one column below that). */
  html[data-iam-version="v4"] .flt-drawer {
    width: min(360px, 100vw);
  }
}

@media (max-width: 900px) {
  html[data-iam-version="v4"] .v4-card .pgn {
    height: auto;
    min-height: 96px;
    flex-wrap: wrap;
    align-content: center;
    row-gap: 8px;
  }
  html[data-iam-version="v4"] .v4-card .pgn-show,
  html[data-iam-version="v4"] .v4-card .pgn-jump {
    flex: 1 1 auto;
    flex-wrap: nowrap;
    white-space: nowrap;
  }
  html[data-iam-version="v4"] .v4-card .pgn-jump {
    justify-content: flex-end;
  }
  html[data-iam-version="v4"] .v4-card .pgn-pages {
    order: 3;
    width: 100%;
    justify-content: center;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   R53 — ADS Figma QA corrections (V4 presentation only)

   Official component evidence:
     • Primary Tab 57:2 / set 57:56 — Default Active is Open Sans
       SemiBold 18/24, 16px horizontal + 8px top padding, 4px internal
       gap and a 3px brand underline.
     • Accordion 2898:18 / Trigger 2899:2 — transparent root inside a
       Card, 24px x / 20px y trigger padding, 16px gap/caret, Open Sans
       SemiBold 15px title, neutral rest foreground, foreground-only
       brand hover and a 2px inside semantic focus stroke.
     • ads-components.json Pagination — digit items have min-width 36.
     • Existing ADS table reference — 32px header, 48px opaque rows.
   ═══════════════════════════════════════════════════════════════════ */

/* Primary Tabs — replace the compact 14px product approximation with
   the official ADS Default size used for page-level content views. */
html[data-iam-version="v4"] .v4-card .tabs-row {
  height: 56px;
  padding: 8px 0 9px;
  align-items: flex-start;
}
/* Final-QA correction, Figma node 1003:17823 ("Primary Tab"): the
   individual tab component itself carries a 16px horizontal padding
   (`tabs/size/default/padding-x`) around its label, and the row's
   "Frame 2134099783" wrapper (tabs + toolbar) sits a further 16px in
   from the table-header's content edge — the SAME 16px inset already
   used on `.tbar` below it. Restating that shared 16px here (instead
   of leaving `.tabs-row` at 0 and relying on the tab's OWN padding
   alone) is what makes "Users" land at the correct distance from the
   card's rounded left edge, and keeps the tab row, toolbar, and table
   on one consistent left content-edge — not a one-off margin on the
   word "Users". Applied on both sides so Roles/Teams and any trailing
   controls keep the same inset at the right edge too. */
html[data-iam-version="v4"] .v4-card .tabs-row {
  padding-left: 16px;
  padding-right: 16px;
}
html[data-iam-version="v4"] .v4-card .tabs-row nav {
  height: 39px;
  /* Figma "Frame 2134099687": Users (x0 w82), Roles (x90 w78) → an
     8px flex gap between each tab's own padded bounding box, on top
     of each tab's own 16px internal padding (not a 0-gap row that
     relies solely on that internal padding to separate labels). */
  gap: 8px;
  align-items: flex-start;
}
html[data-iam-version="v4"] .v4-card .tab-btn {
  box-sizing: border-box;
  height: 39px;
  padding: 8px 16px 7px;
  align-items: center;
  font-family: "Open Sans", sans-serif;
  font-size: 18px;
  line-height: 24px;
  font-weight: 600;
}
html[data-iam-version="v4"] .v4-card .tab-btn.on::after {
  /* Figma's underline (`I1003:17823;57:6`) is exactly as wide as the
     label frame (x16 w50, same x/width as the label above it) — inset
     by the tab's own 16px horizontal padding instead of stretching
     edge-to-edge (`left/right: 0`), so it hugs "Users" itself and
     stays aligned with the label after the card-padding fix above. */
  left: 16px;
  right: 16px;
  bottom: 0;
  height: 3px;
  border-radius: 0;
}

/* Table body density — R46's higher-specificity 56px cell rule was
   still winning over R52. Restore the verified 48px ADS row contract. */
html[data-iam-version="v4"] .v4-card .tbl tbody tr,
html[data-iam-version="v4"] .v4-card .tbl tbody td,
html[data-iam-version="v4"] .v4-card .tbl tbody .name-cell {
  height: 47px;
  min-height: 47px;
}
html[data-iam-version="v4"] .v4-card .tbl tbody td {
  padding-top: 0;
  padding-bottom: 0;
}

/* Accordion triggers — apply official geometry only to actual
   interactive disclosure headers. Static Team card headings retain
   their existing non-accordion section-header treatment. */
html[data-iam-version="v4"] .cr-section-header[role="button"] {
  box-sizing: border-box;
  width: 100%;
  min-height: 62px;
  padding: 20px 24px;
  gap: 16px;
  color: var(--iam-ads-text);
  background: transparent;
}
html[data-iam-version="v4"] .cr-section-header[role="button"] .cr-section-title {
  color: var(--iam-ads-text);
  font-family: "Open Sans", sans-serif;
  font-size: 15px;
  line-height: 22px;
  font-weight: 600;
  letter-spacing: 0;
}
html[data-iam-version="v4"] .cr-section-header[role="button"] .cr-section-chev {
  width: 16px;
  height: 16px;
  color: var(--iam-ads-text-secondary);
  flex: 0 0 16px;
}
html[data-iam-version="v4"] .cr-section-header[role="button"]:hover,
html[data-iam-version="v4"] .cr-section-header[role="button"]:hover .cr-section-title,
html[data-iam-version="v4"] .cr-section-header[role="button"]:hover .cr-section-chev {
  color: var(--iam-ads-brand);
  background: transparent;
}
html[data-iam-version="v4"] .cr-section-header[role="button"]:focus-visible {
  color: var(--iam-ads-text);
  background: transparent;
  outline: 0;
  box-shadow: inset 0 0 0 2px var(--iam-ads-brand);
}

/* Page-id selectors intentionally outrank historical per-page compact
   accordion overrides without changing their DOM or event hooks. */
html[data-iam-version="v4"] #addUsersPage .cr-section-header[role="button"],
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"],
html[data-iam-version="v4"] #pcDetailPage .cr-section-header[role="button"] {
  min-height: 62px;
  padding: 20px 24px;
  gap: 16px;
}
html[data-iam-version="v4"] #addUsersPage .cr-section-header[role="button"] .cr-section-title,
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"] .cr-section-title,
html[data-iam-version="v4"] #pcDetailPage .cr-section-header[role="button"] .cr-section-title {
  color: var(--iam-ads-text);
  font-size: 15px;
  line-height: 22px;
  font-weight: 600;
}
/* Round 31 (2026-08-11) — the `#auBasicCard`/`#auPermsCard`-scoped
   duplicate of the base rule above (identical values, just narrower +
   `.is-edit-mode`-gated) was removed: it was fully redundant for
   `#auPermsCard` (already matched by the un-scoped rule above, which
   targets all of `#addUsersPage`) and, worse, its extra `.is-edit-mode`
   class gave it higher specificity than the Round-2/26/30 title-color
   overrides further below — which, now that those are un-scoped for
   Add User parity, made THIS rule win over them for `#auBasicCard`
   specifically while Edit mode was active, silently reverting its
   title back to 15px gray. `#auPermsCard` (an edit-only, currently-
   unused legacy card, unaffected by this change either way) keeps
   getting the same 15px/gray styling it always had, from the un-scoped
   rule above. */

/* ═══ Final-QA round 2 — Edit User page (Figma node 1003:21681) ════
   Corrects a wrong token from the prior round. Dev Mode on the exact
   "Basic information" / "Access" heading nodes (1003:21681 / 1018:21842,
   nested inside 1003:20186) resolves to `heading/sm`, NOT `heading/lg`:
   MultiplaneTWDC Display Medium, 20px / 24px line-height, 0 letter-
   spacing. Color/chevron treatment were superseded by round 26 below
   (title/chevron now #2D2F8C, per an explicit updated spec). The
   previous round's 24/28 reading was too large — these headings were
   visually competing with the 28px `Edit user` page title, which is
   exactly the H1-vs-H2 hierarchy violation this correction fixes.
   Selector list must match/outrank the 15px rule above on specificity
   (2 ids + role attr + 3 classes) and wins on source order as well,
   since it is declared after it.

   Round 31 (2026-08-11) — Add User parity pass: un-scoped from
   `.is-edit-mode`. "Basic information" and "Role and Permission" are
   the exact same `#auBasicCard`/`#auRolesCard` DOM nodes in Add mode
   (see index.html — one shared markup, no separate Add-mode copy), so
   this same heading treatment now applies unconditionally in both
   modes per an explicit "match Edit User exactly, reuse shared styles"
   spec, instead of only rendering it for Edit mode. */
html[data-iam-version="v4"] #addUsersPage #auBasicCard .cr-section-header[role="button"] .cr-section-title,
html[data-iam-version="v4"] #addUsersPage #auRolesCard .cr-section-header[role="button"] .cr-section-title {
  font-family: "MultiplaneTWDC Display", "Open Sans", sans-serif;
  font-size: 20px;
  line-height: 24px;
  font-weight: 500;
  letter-spacing: 0;
}
html[data-iam-version="v4"] #addUsersPage #auBasicCard .cr-section-header[role="button"] .cr-section-chev,
html[data-iam-version="v4"] #addUsersPage #auRolesCard .cr-section-header[role="button"] .cr-section-chev {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
}

/* ═══ Round 26 (2026-08-11) — "Basic information" / "Access" header
   redesign: chevron moves to the right, indigo #2D2F8C title color,
   no more chevron-driven title indentation ═══

   Title color: explicit #2D2F8C per an updated spec, replacing
   whatever it previously resolved to (neutral gray --iam-ads-text).

   Round 31 (2026-08-11) — un-scoped from `.is-edit-mode` for the same
   Add User parity reason as the font rule above: same shared DOM,
   same title color in both modes now.

   Round 36 (2026-08-12) — Edit Team's "Team details" / "Members"
   headings join this same rule (rather than a second, separately
   hard-coded `#2D2F8C` elsewhere) so both pages' section titles are
   always guaranteed to share the exact same color value; see
   `#editTeamPage .cr-section-header .cr-section-title` above, which
   deliberately leaves `color` unset for this same reason. */
html[data-iam-version="v4"] #addUsersPage #auBasicCard .cr-section-header[role="button"] .cr-section-title,
html[data-iam-version="v4"] #addUsersPage #auRolesCard .cr-section-header[role="button"] .cr-section-title,
html[data-iam-version="v4"] #editTeamPage .cr-section-header .cr-section-title {
  color: #2D2F8C;
}
/* Round 30 (2026-08-11) — chevron color corrected to reuse the exact
   ADS/brand-link token (`--brand-text`) already used by the "Back to
   Users" link/icon on this same page (`.au-back`, `.au-back svg` via
   `stroke="currentColor"`), instead of the Round 26 hard-coded
   #2D2F8C. Title color is intentionally left untouched above — only
   the chevron changes. No separate :hover/:focus/:active override
   exists for this chevron, so it reads as this same token in every
   interaction state (hover, focus, expanded, collapsed) automatically;
   the collapsed-state rotation further below is a `transform`, not a
   color change, so it doesn't need touching either.

   Round 31 (2026-08-11) — un-scoped from `.is-edit-mode`; see above. */
html[data-iam-version="v4"] #addUsersPage #auBasicCard .cr-section-header[role="button"] .cr-section-chev,
html[data-iam-version="v4"] #addUsersPage #auRolesCard .cr-section-header[role="button"] .cr-section-chev {
  color: var(--brand-text);
}

/* Chevron to the far right: DOM order is left untouched on purpose
   (the chevron `<svg>` is still the FIRST child in index.html, before
   `.cr-section-title`), so nothing about Create Role / Edit Team /
   Add mode's identical shared `.cr-section-header` markup is
   disturbed by this change — only these two cards, only in Edit mode,
   are affected. `order: 1` (title/summary stay at the default `order:
   0`) plus `margin-left: auto` visually pushes the chevron past them
   to the header's own right edge, while the header itself now spans
   the row's full width so that edge lines up with the card's real
   right-padding guide — the same distance from the card's right edge
   that the title sits from the card's left edge (both are the card's
   own 24px padding; see `.au-card`/`.cr-card`). This also removes the
   old chevron-width + gap indentation the title used to carry when
   the chevron sat in front of it, so the title's left edge now lines
   up exactly with the section body below it.

   Round 31 (2026-08-11) — un-scoped from `.is-edit-mode`: with
   "Change user" removed from the Basic Information header row
   entirely (see index.html), `#auBasicCard`'s header row has no
   sibling left to make room for in either mode, so this can safely
   apply unconditionally. */
html[data-iam-version="v4"] #addUsersPage #auBasicCard .cr-section-header[role="button"],
html[data-iam-version="v4"] #addUsersPage #auRolesCard .cr-section-header[role="button"] {
  width: 100%;
  justify-content: flex-start;
}
/* `#auBasicCard`'s header used to share its row with the Add-mode-only
   "Change user" button via `flex: 0 1 auto` — see `.cr-section-header-
   row .cr-section-header` above — so it didn't claim the whole row by
   default. That button has been removed (Round 31, Add User parity
   pass) so the header can now always grow to fill the row in both
   modes; without this, the chevron's `margin-left: auto` would only
   push it to the edge of the header's own (content-sized) box, not
   the row's true right edge. `#auRolesCard` has no such wrapper row
   (its header is already a full-width block-level flex container),
   so it needs no equivalent override. */
html[data-iam-version="v4"] #addUsersPage #auBasicCard > .cr-section-header-row > .cr-section-header[role="button"] {
  flex: 1 1 auto;
}
html[data-iam-version="v4"] #addUsersPage #auBasicCard .cr-section-header[role="button"] .cr-section-chev,
html[data-iam-version="v4"] #addUsersPage #auRolesCard .cr-section-header[role="button"] .cr-section-chev {
  order: 1;
  margin-left: auto;
}

/* Collapsed-state chevron direction: expanded already shows the base
   SVG's natural down-chevron unrotated. The shared `.cr-card.collapsed
   .cr-section-chev` rule (used by every OTHER accordion in the app —
   Create Role, Edit Team, Permission Capability) rotates -90deg on
   collapse, which turns a down-chevron into a left/right-pointing one
   — explicitly disallowed for these two sections. 180deg instead
   flips it to an up-chevron (expanded=down / collapsed=up), reusing
   the same subtle animated transition already defined on
   `.cr-section-chev`. Scoped to these two cards only — every other
   accordion in the app keeps its original -90deg rotation, unchanged.
   Round 31 (2026-08-11) — un-scoped from `.is-edit-mode`; Add mode now
   gets the identical up/down chevron behavior as Edit mode. */
html[data-iam-version="v4"] #addUsersPage #auBasicCard.cr-card.collapsed .cr-section-chev,
html[data-iam-version="v4"] #addUsersPage #auRolesCard.cr-card.collapsed .cr-section-chev {
  transform: rotate(180deg);
}

/* ═══ Round 28 (2026-08-11) — Edit Role "Role Details" / "Functions"
   header rework: chevron reposition ONLY, no color change. Round 27's
   #2D2F8C title/chevron override (directly above, in prior source) has
   been fully reverted per an updated spec — "preserve all existing
   text colors, do not apply #2D2F8C or introduce any new text-color
   override". Both cards keep whatever color they already rendered
   before Round 27 (`.cr-section-title` → `--iam-ads-text`, `.cr-section-
   chev` → `--iam-ads-text-secondary`, both from the shared, un-scoped
   `#createRolePage`/`.cr-section-header[role="button"]` rules already
   defined above in this file — nothing new needed here to restore
   them).

   Scoped to `#createRolePage.is-edit-mode` (set/cleared in
   `showEditRole()`/`showCreateRole()`/`hideCreateRole()` in app.js) so
   Create Role keeps its original left-chevron header, at the chevron's
   original 16px size, completely untouched. The nested per-application
   "Core Planning" accordion inside Functions has its own, separately
   scoped Round 28 treatment further down this file. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crBasicCard .cr-section-header[role="button"] .cr-section-chev-btn,
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crFuncsCard .cr-section-header[role="button"] .cr-section-chev-btn {
  /* Chevron to the far right — DOM order is untouched (the chevron
     button stays the FIRST child before `.cr-section-title` in
     index.html, exactly as the bare `<svg>` did before); `order: 1`
     pushes it after the title, `margin-left: auto` then pushes it the
     rest of the way to the header's own right edge. Removing the
     chevron from the front also removes its former width + gap
     indentation, so the title's left edge now lines up with the
     section body below it, and the chevron's distance from the
     card's right edge matches the title's distance from the card's
     left edge (both the card's own 24px padding).
     32px clickable area (accessibility requirement: chevron controls
     need a ~32-36px hit target) — Create Role keeps the button at its
     default 16px (see the un-scoped `.cr-section-chev-btn` reset rule
     above), so this growth is Edit Role-only. */
  order: 1;
  margin-left: auto;
  width: 32px;
  height: 32px;
}
/* Collapsed-state chevron direction — 180deg (up), never -90deg
   (left/right). Scoped to Edit mode only: Create Role keeps the
   shared -90deg rotation, unchanged.

   Round 33 (2026-08-11): "Functions" is deliberately EXCLUDED from
   this rule now — its own state convention is the opposite (expanded
   = up / collapsed = down, matching the nested application chevrons
   introduced in this same round), see the dedicated `#crFuncsCard`
   rule further down. "Role Details" (`#crBasicCard`) keeps this
   original down/up convention, unchanged. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crBasicCard.cr-card.collapsed .cr-section-chev {
  transform: rotate(180deg);
}
/* Functions top-level chevron: expanded/open points UP (rotate
   180deg), collapsed/closed points DOWN (unrotated) — the OPPOSITE of
   Role Details directly above and every other top-level accordion in
   this app, per an explicit spec matching the nested application
   chevrons below it. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crFuncsCard.cr-card:not(.collapsed) .cr-section-chev {
  transform: rotate(180deg);
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crFuncsCard.cr-card.collapsed .cr-section-chev {
  transform: none;
}

/* ═══ Round 33 (2026-08-11) — Edit Role nested application headers
   ("Core Planning", "Identity and Access Management", etc.): reworked
   from Round 28's "Title ... [Remove application] [Chevron]" (chevron
   grouped with Remove on the far right) to "[Chevron] Title ...
   [Remove application]" — the chevron moves back in front of the
   application name, immediately signalling "this row expands/
   collapses" the way the un-scoped Create Role default already does,
   while Remove application keeps sole ownership of the row's far
   right edge with no chevron beside it.

   This is actually the SAME order Create Role's own un-scoped default
   already uses (`.cr-app-head-chev-btn` order 0 / `.cr-app-title`
   order 1, `flex: 1 1 auto` / `.cr-app-remove` order 2, set above) —
   Edit Role no longer needs its own reordering at all for these three,
   only its own clickable-hit-area growth on the chevron button and a
   tighter, spec'd 8px chevron-to-title gap (Create Role keeps the
   shared 12px `.cr-app-section-head` gap, unaffected). Whichever
   element ends up first in visual order still uses the same DOM
   order/click-handling from `buildAppSectionHtml()` in app.js — no
   markup change needed, this is CSS-only. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-section-head {
  gap: 8px;
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-head-chev-btn {
  /* Same ~32px clickable hit area as Role Details/Functions above —
     Create Role keeps this button at its default 16px. The chevron
     `<svg>` inside stays a 16px icon either way (only the button's own
     hit-box grows) — see `.cr-app-head-chev` width/height, untouched. */
  order: 0;
  width: 32px;
  height: 32px;
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-title {
  order: 1;
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-remove {
  order: 2;
}
/* Neutral (Gray/700, `--iam-ads-text-secondary`) nested-chevron color —
   deliberately NOT `#4045C2`/`--brand-text` (Create Role's own nested
   chevron color, unaffected) so the nested chevron reads as visually
   subordinate to the blue top-level Functions chevron, establishing a
   clear two-level hierarchy. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-head-chev {
  color: var(--iam-ads-text-secondary, #3b4347);
}
/* Expanded/open application: chevron points UP (rotate 180deg).
   Collapsed/closed application: chevron points DOWN (unrotated —
   the base SVG's natural resting direction). This is the OPPOSITE of
   every other accordion convention in this app (Role Details/Functions
   above included) — intentional, explicit spec for this nested level
   only. Create Role keeps its own unrelated -90deg collapsed rotation,
   unaffected. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix:not(.cr-app-section--collapsed) .cr-app-head-chev {
  transform: rotate(180deg);
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix.cr-app-section--collapsed .cr-app-head-chev {
  transform: none;
}

/* Header row split (Figma "Frame 2134099792") — the existing
   `.cr-section-header[data-au-toggle]` stays exactly as it was (own
   click/keydown listeners, own padding) but now shares its row with
   the Revoke access button via a plain space-between flex wrapper,
   instead of the header stretching edge-to-edge alone. Scoped to
   Edit User only: Create Role / Edit Team headers are untouched.

   Final layout pass (Figma 1003:20186 measured directly): removed the
   `padding-right: 24px` that used to live here — `#auBasicCard` already
   contributes 24px of its own right padding (see `.au-card`/`.cr-card`),
   so the old rule double-counted it and left Revoke access ~24px short
   of the card's true inner-right guide instead of flush with it. */
html[data-iam-version="v4"] #addUsersPage .cr-section-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
html[data-iam-version="v4"] #addUsersPage .cr-section-header-row .cr-section-header {
  flex: 0 1 auto;
  min-width: 0;
}

/* Basic Information / Role-and-Permission section-header height +
   inner-left guide (Figma "Frame 2134099792" / "Frame 2134099791"):
   the shared `.cr-section-header[role="button"]` accordion-trigger
   rule (used by Create Role and the Permission Card detail page)
   applies a 62px min-height + 20px/24px padding sized for a
   *standalone*, full-bleed accordion header. On Basic Information /
   Role-and-Permission that same padding silently added a second 24px
   left inset on top of the card's own 24px padding (pushing the
   chevron+title ~24px past the card's true inner-left guide) and
   inflated the row to ~68px tall instead of the 36px Figma measures
   (the height of the tallest sibling in the row — Revoke access in
   edit mode, Change user in add mode). Applies in BOTH modes now so
   Add User's card headers land on the exact same inner-left guide as
   Edit User's (same shared section-header pattern, Figma 1023:22053
   agrees with 847:16172 on this). */
html[data-iam-version="v4"] #addUsersPage #auBasicCard > .cr-section-header-row > .cr-section-header[role="button"],
html[data-iam-version="v4"] #addUsersPage #auRolesCard > .cr-section-header[role="button"] {
  min-height: 0;
  padding: 0;
  gap: 8px;
}

/* Back to Users / Back to teams — superseded by the shared
   back-navigation component (`.au-back`/`.cr-back`, defined once near
   the top of this file), which already ships `padding: 0 4px 0 0` so
   the back-chevron icon sits flush on every page's left content guide
   without a page-specific override. */

/* Shared ADS ghost/text-button component for page-header destructive
   actions — ADS Button component, tertiary/text variant, `default`
   size. Originally built for Edit User's "Revoke access"
   (header-simplification pass: moved from the Basic Information card
   header into the page-level header action group, replacing "Save as
   Draft" in that slot, and stripped of its former UserMinus leading
   icon per that pass's explicit "text-only, no icon" requirement —
   text-only ghost/tertiary buttons carry no `gap` since there is no
   icon to space from the label). Reused as-is (class list below) by
   Edit Team's "Delete Team" (Final-QA: "Update the V4 Edit Team page
   header" pass) rather than duplicating the contract — same slot in
   the same shared `.au-header-actions` pattern, same destructive
   ghost/text treatment. Still its OWN rule (not `.btn-std`/
   `.btn-ghost`) so it owns its full ghost-button contract end to end:
   transparent background, no border, 12px/8px padding-x/y, 6px
   radius, Open Sans SemiBold 14/20, rest color
   `button/variant/ghost/text` #51585b (`--iam-ads-text-muted`) — same
   contract as `.au-btn-save-draft` (Create Role's own Save as Draft),
   since all three are the same ADS ghost/text component.
   Round 27 (2026-08-11 — Edit Role header actions): `.cr-btn-remove`
   ("Remove Role") joins this group too, replacing its old bespoke
   26px/indigo "compact inline text-action" treatment (see the removed
   entry in the 26px "Compact ghost text buttons" group above). Stays
   muted-gray, not red — this app has an explicit, documented app-wide
   decision to never render a red "danger" button (ADS's own component
   inventory ships only primary/secondary/tertiary/ghost, no destructive
   variant — see the "Delete/Remove confirmation buttons" comment
   elsewhere in this file), and every other destructive ghost trigger
   here (Revoke access, Delete Team) already uses this same muted-gray
   ghost, not red, for consistency.

   Round 37 (2026-08-12 — Edit Team Members-table "Remove" QA):
   `.tm-row-remove` (per-row "Remove" in the Members table) joins the
   shape/color/interaction contract below too — same ghost variant as
   Delete Team, not a fourth bespoke treatment — but is deliberately
   left OUT of the size declarations right after (height/padding/font-
   size/line-height), which stay 36px/"default" size for the original
   three page-level actions only. `.tm-row-remove` gets its own
   compact-size rule immediately below instead (same rationale as
   Round 27 splitting size from color: a table row needs a smaller
   ADS button size than a page header, while still being unmistakably
   "the same ghost button"). */
html[data-iam-version="v4"] .au-revoke-btn,
html[data-iam-version="v4"] .tm-delete-btn,
html[data-iam-version="v4"] .cr-btn-remove,
html[data-iam-version="v4"] .tm-row-remove {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-weight: 600;
  color: var(--iam-ads-text-muted, #51585b);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
/* "Default" ADS Button size — page-level destructive actions only.
   `.tm-row-remove`'s compact size lives in its own rule right after. */
html[data-iam-version="v4"] .au-revoke-btn,
html[data-iam-version="v4"] .tm-delete-btn,
html[data-iam-version="v4"] .cr-btn-remove {
  height: 36px;
  padding: 8px 12px;
  font-size: 14px;
  line-height: 20px;
}
/* "Compact"/small ADS Button size — the same ghost component as
   above, sized for a table row: 26px, the identical compact height
   already used app-wide for inline row/header actions like "Remove
   application" (see the 26px "Compact ghost text buttons" group
   earlier in this file), so this doesn't invent a new size, just
   applies the existing compact size token to this component's color
   contract. Row height is untouched — 26px comfortably fits inside
   the Members table's existing 48px row height with room to spare,
   the same way it always has for every other compact-ghost action in
   this app. */
html[data-iam-version="v4"] .tm-row-remove {
  height: 26px;
  padding: 4px 8px;
  font-size: 12px;
  line-height: 18px;
}
html[data-iam-version="v4"] .au-revoke-btn:hover,
html[data-iam-version="v4"] .tm-delete-btn:hover,
html[data-iam-version="v4"] .cr-btn-remove:hover,
html[data-iam-version="v4"] .tm-row-remove:hover {
  background: rgba(15, 18, 20, 0.05);
  color: var(--iam-ads-text, #1e2528);
}
html[data-iam-version="v4"] .au-revoke-btn:active,
html[data-iam-version="v4"] .tm-delete-btn:active,
html[data-iam-version="v4"] .cr-btn-remove:active,
html[data-iam-version="v4"] .tm-row-remove:active {
  background: rgba(15, 18, 20, 0.08);
  color: var(--iam-ads-text, #1e2528);
}
html[data-iam-version="v4"] .au-revoke-btn:focus-visible,
html[data-iam-version="v4"] .tm-delete-btn:focus-visible,
html[data-iam-version="v4"] .cr-btn-remove:focus-visible,
html[data-iam-version="v4"] .tm-row-remove:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
html[data-iam-version="v4"] .cr-btn-remove:disabled,
html[data-iam-version="v4"] .tm-row-remove:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
/* Extra separation before Cancel/Save (Final-QA requirement: "a
   slightly larger gap between Delete Team and Cancel" than the
   standard ADS gap used between Cancel and Save) — this reads as
   clear separation between the destructive action and the editing
   actions without a visible divider, which neither the Figma
   reference nor the ADS pattern for this header includes. Extra
   margin on the control itself (not a change to the shared
   `.au-header-actions` gap) keeps Edit Team's own standard
   Cancel<->Save gap intact. Edit User's header no longer has a
   destructive action at all (Revoke access removed) so it needs no
   equivalent rule — Cancel/Save there just use the shared 12px
   `.au-header-actions` gap below, untouched. */
html[data-iam-version="v4"] #editTeamPage .tm-delete-btn {
  margin-right: 12px;
}

/* Save as Draft — same ADS Button `ghost`/`default` contract as Revoke
   access (Figma "Frame 627874" node 1003:21304): transparent background,
   text-only (no icon), 12px/8px padding-x/y, 6px radius, 36px height,
   Open Sans SemiBold 14/20, rest color `button/variant/ghost/text`
   #51585b. Given its own rule for the same reason as `.au-revoke-btn`
   (full self-contained ghost-button contract) rather than reusing
   `.btn-ghost`, which is scoped to indigo `--brand-text` styling for
   toolbar "+ Add" actions elsewhere in this app. */
html[data-iam-version="v4"] .au-btn-save-draft {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 8px 12px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--iam-ads-text-muted, #51585b);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
html[data-iam-version="v4"] .au-btn-save-draft:hover {
  background: rgba(15, 18, 20, 0.05);
  color: var(--iam-ads-text, #1e2528);
}
html[data-iam-version="v4"] .au-btn-save-draft:active {
  background: rgba(15, 18, 20, 0.08);
  color: var(--iam-ads-text, #1e2528);
}
html[data-iam-version="v4"] .au-btn-save-draft:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
}
/* Same `[hidden]` override `.cr-btn-remove[hidden]` already needed
   (R-above): the shared ADS button-anatomy rule sets `display:
   inline-flex` as an author style, which otherwise wins over the
   browser's UA-stylesheet `[hidden] { display: none }` default.
   Needed now that Edit Role hides Save as Draft (Create Role shows
   it, Edit Role shows Remove Role instead — see
   `setRemoveRoleVisible`). */
html[data-iam-version="v4"] .au-btn-save-draft[hidden] {
  display: none !important;
}

/* Header actions — Figma "Frame 627874" measures a fixed 12px gap
   between the action-group siblings, inside one action-group
   container, `.au-header-actions`) vs the 16px this app uses
   elsewhere for the same class (Edit Team keeps its own 16px,
   untouched). Height/padding/radius already resolve to the ADS
   36px/32px + 12-8px/6px contract via existing rules — only the gap
   needed correcting. Edit User's header action group is now just
   Cancel -> Save (Revoke access removed entirely), so this single
   12px gap is the only spacing rule this group needs. */
html[data-iam-version="v4"] #addUsersPage .au-header-actions {
  gap: 12px;
}

/* Identity block — status icon now sits beside the name (see the
   `.au-id-name-row` wrapper added in index.html); the email row below
   holds only the email text. Reuses the exact same 4px gap already
   established for the (now single-child) email row for visual
   consistency. `min-width: 0` on both the row and the name span keeps
   the existing text-overflow ellipsis working now that the name is a
   flex child of a new wrapper rather than a lone block.

   This rule used to be scoped to `.is-edit-mode`, which is what broke
   Add User: `.au-id-name-row` is shared markup, so in Add mode it
   stayed a plain block and `#auIdName` stayed `display: inline`.
   `overflow`, `text-overflow` and `white-space: nowrap` have no effect
   on a non-replaced inline box, so a long name laid itself out at full
   width — straight across the Preferred name field — and the status
   icon was pushed onto its own line after it. Blockifying the name as a
   flex item is what makes the ellipsis (and the truncation measurement
   that drives its tooltip) work at all, and both flows need it. */
html[data-iam-version="v4"] #addUsersPage .au-id-name-row {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  /* The name shrinks; the status icon beside it never does, so it can't
     be squeezed out of the identity column by a long name. */
  flex-wrap: nowrap;
}
html[data-iam-version="v4"] #addUsersPage .au-id-name-row .au-id-name {
  min-width: 0;
  flex: 0 1 auto;
}
html[data-iam-version="v4"] #addUsersPage .au-id-name-row .au-id-status {
  flex: 0 0 auto;
}

/* Truncated name/email become focusable (JS adds `tabindex` only while
   they're actually clipped) so keyboard users can reach the tooltip
   that reveals the full value. Give them the standard focus ring. */
html[data-iam-version="v4"] #addUsersPage .au-id-name[tabindex]:focus-visible,
html[data-iam-version="v4"] #addUsersPage .au-id-email[tabindex]:focus-visible {
  outline: 2px solid var(--brand-focus-ring, #3611C8);
  outline-offset: 2px;
  border-radius: 4px;
}

/* External Edit User renders Company as a read-only <div> rather than an
   <input>, so it needs the clipping an input does natively — otherwise a
   long organization name spills out of the field and across the column.
   Everything else about its box (32px height, padding, radius, border,
   read-only fill) comes from the shared `.au-input` + `.au-input-readonly`
   classes, which is what keeps it level with the Timezone control beside
   it. */
html[data-iam-version="v4"] #addUsersPage .au-field-team-readonly {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Avatar: the vector placeholder draws its own circle whose outer edge
   sits exactly on the container's boundary, so the container's circular
   clip was shaving that edge. Nothing about a self-contained circular
   drawing needs cropping — only a rectangular photo does. Keep
   `overflow: hidden` for the photo/initials cases and drop it for the
   placeholder, so the whole outer circle is guaranteed to paint. */
html[data-iam-version="v4"] #addUsersPage .au-id-avatar:has(> .au-id-avatar-svg) {
  overflow: visible;
}

/* Pagination digit width from the ADS component metadata. */
html[data-iam-version="v4"] .pgn .pg-nums .pg-n {
  width: auto;
  min-width: 36px;
}

/* Remaining repository-token corrections found during the terminal
   cascade audit. These supersede legacy high-specificity rules while
   preserving all markup and behavior.
   Background corrected to white (Figma node 1003:17844 final-QA —
   see the R38-6 comment above this rule used to win the cascade with
   a hardcoded #fafafb; this was the actual regression). */
html[data-iam-version="v4"] .v4-card .tbl thead th {
  background: var(--iam-ads-surface);
  color: var(--iam-ads-text-secondary);
  font-weight: 500;
  letter-spacing: 0.01em;
}
html[data-iam-version="v4"] .v4-card .pgn {
  height: 48px;
  min-height: 48px;
  padding-top: 6px;
  padding-bottom: 6px;
}
html[data-iam-version="v4"] .v4-card .pgn .pg-nav,
html[data-iam-version="v4"] .v4-card .pgn .pg-nums .pg-n {
  width: 36px;
  min-width: 36px;
  height: 36px;
  min-height: 36px;
  font-size: 14px;
  border-radius: 8px;
}
html[data-iam-version="v4"] .pgn-lbl {
  color: var(--iam-ads-text-muted);
  font-size: 12px;
  font-weight: 500;
}
html[data-iam-version="v4"] .au-label,
html[data-iam-version="v4"] .cr-label,
html[data-iam-version="v4"] .flt-label,
html[data-iam-version="v4"] .field-label {
  color: var(--iam-ads-text);
  font-size: 14px;
  line-height: 18px;
  font-weight: 600;
}
/* Final-QA (Edit User, Figma 1003:20186 / Input node 1018:21804): the
   ADS Input "Label and Required" slot renders at 12px/18px SemiBold
   500 in `--iam-ads-text-secondary` (#3b4347), not the 14px/600
   `--iam-ads-text` treatment above (that 14px/600 rule serves Create
   Role's `.cr-label` and the filter bar's `.flt-label`/`.field-label`,
   which have their own, separately-verified Figma specs — narrowing
   the selector list here instead of editing the shared rule keeps
   those pages byte-identical). Scoped to the Add/Edit User page only. */
html[data-iam-version="v4"] #addUsersPage .au-label {
  color: var(--iam-ads-text-secondary);
  font-size: 12px;
  line-height: 18px;
  font-weight: 500;
}
/* Final-QA (Figma 1003:20186): the required-field marker on the Input
   component uses `--ads-red-400` (#993b44), already the published Ads
   DS validation-text red used elsewhere in this file (`.cr-req` under
   ads-preview) — `.au-req` had never been migrated off the pre-ADS
   #e52f52 pink. Scoped to Add/Edit User only. */
html[data-iam-version="v4"] #addUsersPage .au-req {
  color: var(--ads-red-400);
}
html[data-iam-version="v4"] .search input:focus,
html[data-iam-version="v4"] .cr-input:focus,
html[data-iam-version="v4"] .cr-textarea:focus,
html[data-iam-version="v4"] .au-input:focus,
html[data-iam-version="v4"] .flt-input:focus {
  border-color: var(--iam-ads-brand);
  outline: 0;
  box-shadow: 0 0 0 2px rgba(64, 69, 194, 0.20);
}
html[data-iam-version="v4"] .edl-tooltip,
html[data-iam-version="v4"] .edl-status-tooltip {
  padding-left: 16px;
  padding-right: 16px;
  background: #21292d;
}

@media (max-width: 768px) {
  html[data-iam-version="v4"] .v4-card .tabs-row {
    height: 56px;
    padding: 8px 0 9px;
  }
  html[data-iam-version="v4"] .v4-card .tab-btn {
    height: 39px;
    padding: 8px 12px 7px;
    font-size: 18px;
    line-height: 24px;
  }
}

@media (max-width: 900px) {
  html[data-iam-version="v4"] .v4-card .pgn {
    height: auto;
    min-height: 96px;
    padding: 8px 12px;
  }
}

/* R57C — authoritative Tabs/Search/Button layer, intentionally last. */
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab {
  height: 32px !important;
  padding: 8px 16px 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #51585b !important;
  font: 400 18px/24px "Open Sans", sans-serif !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:hover:not(:disabled):not(.on) { color: #3b4347 !important; }
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on {
  height: 39px !important;
  padding: 8px 16px 7px !important;
  color: #4045c2 !important;
  font-weight: 600 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab.on::after {
  bottom: 0 !important;
  height: 3px !important;
  background: #4045c2 !important;
}
html[data-iam-version="v4"] .v4-card .ads-tabs .ads-tab:focus-visible {
  height: 40px !important;
  padding: 8px 16px !important;
  border-radius: 3px !important;
  color: #4045c2 !important;
  outline: 0 !important;
  box-shadow: inset 0 0 0 2px #4045c2 !important;
}
html[data-iam-version="v4"] .ads-search > input,
html[data-iam-version="v4"] .tm-add-search.ads-search > input {
  width: auto !important;
  height: 20px !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  color: #1e2528 !important;
  font: 400 14px/20px "Open Sans", sans-serif !important;
}
html[data-iam-version="v4"] .ads-search > input:focus,
html[data-iam-version="v4"] .tm-add-search.ads-search > input:focus {
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-ico {
  position: static !important;
  left: auto !important;
  right: auto !important;
  width: 20px !important;
  height: 20px !important;
  transform: none !important;
  color: #51585b !important;
}
html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-clear {
  position: static !important;
  left: auto !important;
  right: auto !important;
  /* Round 23 (2026-08-11): 16px -> 24px clickable area, matching the
     canonical `.ads-search .search-clear` rule below — this is one of
     three byte-identical duplicate blocks in this file (all `!important`,
     so all three had to move together or the lowest-value one would
     keep winning the cascade). */
  width: 24px !important;
  min-width: 24px !important;
  height: 24px !important;
  min-height: 24px !important;
  padding: 0 !important;
}
html[data-iam-version="v4"] .ads-search:focus-within {
  border-color: rgba(15, 18, 20, 0.50) !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .btn-ghost, .au-btn-save, .cr-btn-save, .au-btn-add, .cr-btn-add, .flt-btn-cancel, .flt-btn-apply, .cr-btn-danger-solid) {
  box-sizing: border-box !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 36px !important;
  height: 36px !important;
  padding: 8px 12px !important;
  gap: 4px !important;
  border-radius: 6px !important;
  font: 600 14px/20px "Open Sans", sans-serif !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost,
html[data-iam-version="v4"] button.au-btn-save,
html[data-iam-version="v4"] button.cr-btn-save,
html[data-iam-version="v4"] button.flt-btn-apply {
  border: 0 !important;
  background: #4045c2 !important;
  color: #fff !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:hover:not(:disabled),
html[data-iam-version="v4"] button.au-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] button.cr-btn-save:hover:not(:disabled),
html[data-iam-version="v4"] button.flt-btn-apply:hover:not(:disabled) { background: #6567ce !important; }
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:active:not(:disabled),
html[data-iam-version="v4"] button.au-btn-save:active:not(:disabled),
html[data-iam-version="v4"] button.cr-btn-save:active:not(:disabled),
html[data-iam-version="v4"] button.flt-btn-apply:active:not(:disabled) { background: #4045c2 !important; }
html[data-iam-version="v4"] .v4-card .tbar > button.btn-ghost:disabled,
html[data-iam-version="v4"] button.au-btn-save:disabled,
html[data-iam-version="v4"] button.cr-btn-save:disabled,
html[data-iam-version="v4"] button.flt-btn-apply:disabled {
  border-color: transparent !important;
  background: #e2e3f2 !important;
  color: rgba(255, 255, 255, 0.50) !important;
  opacity: 1 !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel) {
  border: 1px solid #4045c2 !important;
  background: transparent !important;
  color: #4045c2 !important;
  box-shadow: none !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel):hover:not(:disabled) {
  background: rgba(15, 18, 20, 0.05) !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel):active:not(:disabled) {
  background: rgba(15, 18, 20, 0.10) !important;
}
html[data-iam-version="v4"] button:is(.btn-std, .au-btn-add, .cr-btn-add, .flt-btn-cancel):disabled {
  border-color: #e2e3f2 !important;
  background: rgba(15, 18, 20, 0.05) !important;
  color: #e2e3f2 !important;
  opacity: 1 !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   PROTOTYPE-ONLY — Select Users → Export to Excel simulation
   ═══════════════════════════════════════════════════════════════════════
   Everything below styles #simDesktopOverlay / #simExcelOverlay
   (index.html) — a purely visual, in-page simulation of "export
   completed → a file appears on the Desktop → the file opens in
   Excel". None of it is a real Finder/macOS/Excel surface; it is
   scoped entirely to these two ids so it can never bleed into or
   restyle any real ADS/EDL component elsewhere in the app. Per the
   spec, this presentation layer is allowed its own
   "external-simulation" styling rather than ADS tokens (it represents
   third-party OS/app chrome, not an Atlas surface) — the ADS
   components living *inside* the User List itself (checkboxes, the
   Export ghost button, toasts) are untouched by anything here. */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

body.sim-overlay-open { overflow: hidden; }

.sim-desktop,
.sim-excel {
  position: fixed;
  inset: 0;
  z-index: 9500; /* above the whole app (nav is 100, dialogs 90-1000) but
                    below the EDL toast layer (10000+) so "Export
                    created." can float visibly on top of the Desktop. */
  display: flex;
  flex-direction: column;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", "Open Sans", sans-serif;
  animation: simFadeIn 0.22s ease both;
}
.sim-desktop[hidden],
.sim-excel[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .sim-desktop, .sim-excel { animation: none; }
}
@keyframes simFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ─── Simulated Desktop ─── */
.sim-desktop {
  background:
    radial-gradient(circle at 20% 15%, rgba(255, 255, 255, 0.18), transparent 45%),
    linear-gradient(160deg, #6a8dd6 0%, #7d6bc9 42%, #4b3f8f 78%, #2c2560 100%);
}
.sim-menubar {
  flex: 0 0 auto;
  height: 26px;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 16px;
  background: rgba(20, 20, 26, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: rgba(255, 255, 255, 0.92);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  user-select: none;
}
.sim-menubar-apple { font-size: 15px; line-height: 1; }
.sim-menubar-app { font-weight: 700; }
.sim-menubar-items { display: flex; gap: 16px; color: rgba(255, 255, 255, 0.78); }
.sim-menubar-status {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  color: rgba(255, 255, 255, 0.85);
}
.sim-menubar-clock { font-weight: 500; white-space: nowrap; }

.sim-desktop-surface {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.sim-desktop-return {
  position: absolute;
  top: 20px;
  left: 20px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 8px;
  background: rgba(20, 20, 26, 0.35);
  backdrop-filter: blur(6px);
  color: #ffffff;
  font-family: "Open Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.sim-desktop-return:hover { background: rgba(20, 20, 26, 0.55); }
.sim-desktop-return:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
}

.sim-desktop-icons {
  position: absolute;
  /* Pushed below the EDL toast stack's top-right corner (top:80px,
     up to ~2 stacked 400px-wide toasts) so the "Export created."
     toast never covers the newly-created file it's describing. */
  top: 300px;
  right: 28px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
}
.sim-file-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 92px;
  padding: 10px 6px 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  font-family: "Open Sans", sans-serif;
}
.sim-file-glyph { filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.35)); }
.sim-file-name {
  max-width: 100%;
  padding: 1px 6px;
  border-radius: 4px;
  color: #ffffff;
  font-size: 12px;
  font-weight: 500;
  line-height: 15px;
  text-align: center;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  word-break: break-word;
}
.sim-file-icon:hover .sim-file-name,
.sim-file-icon:focus-visible .sim-file-name { background: rgba(255, 255, 255, 0.14); }
.sim-file-icon:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
  border-radius: 10px;
}
/* Selected state (macOS Finder convention: translucent blue wash behind
   icon + name) once the file has been opened at least once this cycle. */
.sim-file-icon.is-selected .sim-file-glyph { filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.35)) brightness(1.02); }
.sim-file-icon.is-selected .sim-file-name {
  background: rgba(64, 133, 255, 0.55);
}
/* One-shot "just created" pulse — a soft glow ring that fades out over
   ~1s, drawing the eye to the new file without looping indefinitely.
   The class is only ever added by JS when motion is not reduced (see
   openSimulatedDesktop() in app.js); this media query is a second line
   of defense in case the class is present regardless. */
.sim-file-icon.is-new .sim-file-glyph {
  animation: simFileArrive 0.9s ease-out 1;
}
@keyframes simFileArrive {
  0% { transform: scale(0.85); filter: drop-shadow(0 0 0 rgba(255, 255, 255, 0)); }
  35% { transform: scale(1.06); filter: drop-shadow(0 0 14px rgba(255, 255, 255, 0.85)); }
  100% { transform: scale(1); filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.35)); }
}
@media (prefers-reduced-motion: reduce) {
  .sim-file-icon.is-new .sim-file-glyph { animation: none; }
}

.sim-desktop-hint {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  margin: 0;
  padding: 8px 16px;
  border-radius: 8px;
  background: rgba(20, 20, 26, 0.45);
  backdrop-filter: blur(6px);
  color: rgba(255, 255, 255, 0.92);
  font-family: "Open Sans", sans-serif;
  font-size: 13px;
  text-align: center;
  max-width: min(420px, calc(100vw - 48px));
}

/* ─── Simulated Excel window ─── */
.sim-excel {
  background: rgba(15, 18, 20, 0.45);
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.sim-excel-window {
  display: flex;
  flex-direction: column;
  width: min(1120px, 100%);
  height: min(720px, 100%);
  background: #ffffff;
  border-radius: 10px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.sim-excel-titlebar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 40px;
  padding: 0 12px;
  background: #f3f3f3;
  border-bottom: 1px solid #d9dcde;
}
.sim-excel-traffic { display: flex; align-items: center; gap: 8px; }
.sim-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }
.sim-dot-red { background: #ff5f57; }
.sim-dot-yellow { background: #febc2e; }
.sim-dot-green { background: #28c840; }
.sim-excel-titletext {
  flex: 1 1 auto;
  text-align: center;
  font-family: "Open Sans", sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #3b4347;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sim-excel-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  height: 28px;
  padding: 0 12px;
  border: 1px solid #c7ccce;
  border-radius: 6px;
  background: #ffffff;
  color: #1e2528;
  font-family: "Open Sans", sans-serif;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.sim-excel-back-btn:hover { background: #f0f1f2; }
.sim-excel-back-btn:focus-visible {
  outline: 2px solid var(--brand-focus-ring, #4045c2);
  outline-offset: 2px;
}

.sim-excel-ribbon {
  flex: 0 0 auto;
  background: #ffffff;
  border-bottom: 1px solid #e3e5e6;
}
.sim-excel-ribbon-tabs {
  display: flex;
  gap: 18px;
  padding: 6px 16px 0;
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: #51585b;
}
.sim-excel-ribbon-tabs .on {
  color: #1D6F42;
  padding-bottom: 6px;
  border-bottom: 2px solid #1D6F42;
}
.sim-excel-ribbon-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 16px;
}
.sim-ribbon-swatch {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 4px;
  background: #f3f3f3;
  color: #3b4347;
  font-size: 12px;
  font-weight: 700;
}
.sim-ribbon-swatch-b { font-style: normal; }
.sim-ribbon-swatch-i { font-style: italic; }
.sim-ribbon-swatch-u { text-decoration: underline; }
.sim-ribbon-fill { border: 1px solid #d9dcde; }
.sim-ribbon-divider { width: 1px; height: 20px; background: #e3e5e6; margin: 0 4px; }

.sim-excel-formula-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 30px;
  padding: 0 12px;
  background: #ffffff;
  border-bottom: 1px solid #e3e5e6;
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  color: #3b4347;
}
.sim-excel-namebox {
  min-width: 48px;
  padding: 2px 8px;
  border: 1px solid #d9dcde;
  border-radius: 3px;
  font-weight: 600;
}
.sim-excel-fx { font-style: italic; color: #1D6F42; font-weight: 700; }
.sim-excel-formula-value { color: #51585b; }

.sim-excel-grid-wrap {
  flex: 1 1 auto;
  overflow: auto;
  background: #ffffff;
}
.sim-excel-grid-wrap:focus-visible {
  outline: 2px solid var(--brand-focus-ring, #4045c2);
  outline-offset: -2px;
}
.sim-excel-grid {
  border-collapse: collapse;
  min-width: 100%;
  font-family: "Open Sans", sans-serif;
  font-size: 13px;
  color: #1e2528;
}
.sim-excel-grid th,
.sim-excel-grid td {
  border: 1px solid #e3e5e6;
  padding: 6px 10px;
  text-align: left;
  white-space: nowrap;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sim-excel-colrow th {
  position: sticky;
  top: 0;
  z-index: 3;
  height: 28px;
  background: #f3f3f3;
  color: #51585b;
  font-weight: 600;
  text-align: center;
  min-width: 120px;
}
.sim-excel-colrow .sim-excel-corner {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 4;
  min-width: 40px;
  background: #f3f3f3;
}
.sim-excel-rownum {
  position: sticky;
  left: 0;
  z-index: 1;
  background: #f3f3f3;
  color: #51585b;
  font-weight: 600;
  text-align: center;
  min-width: 40px;
}
.sim-excel-headcell {
  background: #eef1fb;
  color: #1e2528;
  font-weight: 700;
}
/* Row 1 ("Name, Email, Role(s)…") is the header row that actually
   explains each column — it must stay readable while scrolling
   through many exported rows, not just the decorative A/B/C column
   letters above it. Pin it directly beneath the sticky colrow (same
   28px height) so both header layers stay visible together, same as
   a frozen header row in real Excel. */
.sim-excel-grid tbody tr:first-child > .sim-excel-headcell {
  position: sticky;
  top: 28px;
  z-index: 2;
}
.sim-excel-grid tbody tr:first-child > .sim-excel-rownum {
  position: sticky;
  top: 28px;
  left: 0;
  z-index: 3;
}
.sim-excel-cell { background: #ffffff; }
.sim-excel-status-active { color: #056C07; font-weight: 600; }
.sim-excel-status-inactive { color: #b3261e; font-weight: 600; }

.sim-excel-statusbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 30px;
  padding: 0 14px;
  background: #f3f3f3;
  border-top: 1px solid #e3e5e6;
  font-family: "Open Sans", sans-serif;
  font-size: 12px;
  color: #51585b;
}
.sim-excel-tab {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  border-radius: 4px 4px 0 0;
  font-weight: 600;
}
.sim-excel-tab.on {
  background: #ffffff;
  border: 1px solid #e3e5e6;
  border-bottom: 2px solid #1D6F42;
  color: #1D6F42;
}
.sim-excel-statusbar-count { margin-left: auto; color: #7a8286; }

/* ═══ Final-QA: Create/Edit Role page (Figma 1025:23238 complete
   layout + 1025:23278 Role Details/Functions headings + ADS Button
   node 7722:252 for Remove application) ═══════════════════════════
   Dev-Mode measurements on 1025:23238 that differ from the page's
   pre-existing shared accordion/card rules:
     - Card radius is 8px (Ads DS "radius/8"), not the 6px
       `--iam-ads-control-radius` the shared `.cr-card` rule uses.
     - "Role Details" / "Functions" are `heading/sm` — MultiplaneTWDC
       Display Medium 20px/24px, NOT the 15px Open Sans SemiBold the
       shared `.cr-section-header[role="button"]` accordion-trigger
       rule applies (that rule is correct for the *other* consumers
       of the same shared class — Add User, Permission Capability —
       so it's narrowed here exactly like the Edit-User heading/sm
       correction narrowed it for `#auBasicCard`/`#auRolesCard`).
     - The chevron is a 24×24 icon box (not 16×16), and both the
       chevron and title render in Gray/800 (`--iam-ads-text`) at
       rest — pixel-sampling the Figma export confirms this (RGB
       22,28,30 ≈ #161c1e at both the "Role Details" chevron and the
       "Core Planning" app-group chevron), not the brand-indigo this
       page previously used for either heading. Hover keeps the
       existing brand-indigo affordance since Figma only captures the
       resting state and this app already uses "hover → brand" as its
       universal accordion-trigger convention (R33-8 above). */
html[data-iam-version="v4"] #createRolePage .cr-card {
  border-radius: 8px;
}
/* "Back to Roles" now inherits its 14px/20px SemiBold styling from
   the shared back-navigation component (`.cr-back`, defined once near
   the top of this file) — no page-specific override needed. */
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"] {
  min-height: 0;
  padding: 0;
  gap: 8px;
  margin-bottom: 16px;
}
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"] .cr-section-title {
  font-family: "MultiplaneTWDC Display", "Open Sans", sans-serif;
  font-size: 20px;
  line-height: 24px;
  font-weight: 500;
  color: var(--iam-ads-text);
  letter-spacing: 0;
}
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"] .cr-section-chev {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  color: var(--iam-ads-text);
}
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"]:hover .cr-section-title,
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"]:hover .cr-section-chev,
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"]:focus-visible .cr-section-title,
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"]:focus-visible .cr-section-chev {
  color: var(--iam-ads-brand);
}
html[data-iam-version="v4"] #createRolePage .cr-section-header[role="button"]:focus-visible {
  outline: 0;
  box-shadow: none;
}
/* Collapsed state loses the 16px margin the expanded heading uses to
   separate itself from the fields below it — nothing to separate
   from once the card body is hidden. */
html[data-iam-version="v4"] #crBasicCard.collapsed .cr-section-header[role="button"],
html[data-iam-version="v4"] #crFuncsCard.collapsed .cr-section-header[role="button"] {
  margin-bottom: 0;
}

/* ═══ Round 32 (2026-08-11) — Edit Role "Role Details" / "Functions"
   headers now match Edit User's "Basic information" / "Access"
   headers exactly in color: title `#2D2F8C`, chevron `--brand-text`
   (the same token the "Back to Users"/"Back to Roles" link already
   uses), reusing the exact literal values Round 26/30 established for
   `#auBasicCard`/`#auRolesCard` rather than approximating them.

   Round 28 had reverted an earlier color pass per an explicit
   "preserve all existing text colors" spec; this is a deliberate,
   later, more specific request that supersedes that reversion — see
   the task's "match Edit User exactly" requirement. Scoped to
   `#createRolePage.is-edit-mode` only (set/cleared in
   `showEditRole()`/`showCreateRole()`/`hideCreateRole()` in app.js) so
   Create Role's own header keeps the Gray/800 resting color from the
   un-scoped rule above, untouched — this pass is Edit-Role-only. The
   nested per-application "Core Planning" header uses its own separate
   `.cr-app-title`/`.cr-app-head-chev` classes (not `.cr-section-
   title`/`.cr-section-chev`), so it is structurally unreachable by
   these selectors and needs no exclusion. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crBasicCard .cr-section-header[role="button"] .cr-section-title,
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crFuncsCard .cr-section-header[role="button"] .cr-section-title {
  color: #2D2F8C;
}
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crBasicCard .cr-section-header[role="button"] .cr-section-chev,
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crFuncsCard .cr-section-header[role="button"] .cr-section-chev {
  color: var(--brand-text);
}
/* Round 33 (2026-08-11): Functions' own chevron pinned to the exact
   literal `#4045C2` (which `--brand-text` already resolves to above —
   this makes it explicit/guaranteed rather than incidental, per a
   spec asking for this exact hex on this specific chevron). Higher
   specificity than the shared rule directly above via the repeated
   `#crFuncsCard`, so it wins for Functions only; Role Details keeps
   the token-based color, unaffected. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode #crFuncsCard .cr-section-header[role="button"] .cr-section-chev {
  color: #4045C2;
}
/* Edit User's equivalent header keeps its default visible keyboard-
   focus outline (the shared `[data-cr-toggle]:focus-visible` /
   `[data-au-toggle]:focus-visible` rule near the top of this file) —
   restore that same visible affordance here, undoing the
   `outline: 0` the un-scoped `#createRolePage` rule above applies for
   Create Role. Higher specificity (`.is-edit-mode` added) wins over
   that rule without needing to touch Create Role's. */
html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-section-header[role="button"]:focus-visible {
  outline: 2px solid var(--indigo-50);
  outline-offset: 2px;
  box-shadow: none;
}

/* Field labels ("Role Name", "Description", "Select applications") —
   Figma's Input component "Label and Required" slot is Open Sans
   SemiBold 12px/18px in `field-description/state/default/text`
   (#3b4347 ≈ `--iam-ads-text-secondary`), the exact same token this
   codebase already verified for Add/Edit User's `.au-label` — Create
   Role's `.cr-label` had never been migrated off the older 14px/600
   `--iam-ads-text` treatment that still correctly serves the filter
   drawer's unrelated `.flt-label`. Required marker matches the
   already-published Ads DS validation red (`--ads-red-400`). */
html[data-iam-version="v4"] #createRolePage .cr-label {
  color: var(--iam-ads-text-secondary);
  font-size: 12px;
  line-height: 18px;
  font-weight: 500;
}
html[data-iam-version="v4"] #createRolePage .cr-req {
  color: var(--ads-red-400);
}

/* Application-group headings ("Core Planning", "Identity and Access
   Management", …) and their chevrons — same Gray/800 resting-state
   correction as the card-level headings above (Figma's "Core
   Planning" instance is `text-color/gray/800`, and its chevron
   samples to the same RGB as the Role Details chevron). The prior
   "calmer visual weight" brand-indigo treatment is replaced with the
   Figma-verified neutral tone; hover still shifts to brand indigo so
   the row keeps an obvious interactive affordance. */
html[data-iam-version="v4"] #createRolePage .cr-app-section--matrix .cr-app-title,
html[data-iam-version="v4"] #createRolePage .cr-app-section--matrix .cr-app-head-chev {
  color: var(--iam-ads-text);
}
html[data-iam-version="v4"] #createRolePage .cr-app-section-head:hover .cr-app-title,
html[data-iam-version="v4"] #createRolePage .cr-app-section-head:hover .cr-app-head-chev,
html[data-iam-version="v4"] #createRolePage .cr-app-section-head:focus-visible .cr-app-title,
html[data-iam-version="v4"] #createRolePage .cr-app-section-head:focus-visible .cr-app-head-chev {
  color: var(--iam-ads-brand);
}

/* "Remove application" — final-QA pass (2026-08-11, Remove Application
   modal rebuild): reverted to the compact ADS ghost/text-only control
   this button is separately approved to use — no default border, no
   trash icon, right-aligned in its application header. A prior round
   had bordered/icon-ed this into a `variant=tertiary, type=text+icon`
   treatment (Figma 7722:252's demo cell — the same generic-icon
   showcase pattern documented on the "View access breakdown" button
   elsewhere in this file), which read as an oversized outline button
   and is exactly what this pass reverts. Removing this ID-scoped
   override lets `.cr-app-remove` fall through to the shared 26px
   compact-ghost contract (`html[data-iam-version="v4"] .cr-app-remove`
   further up this file, alongside "Remove Role" / "Remove" table
   actions): height 26px, padding 4/8, radius 6, transparent at rest,
   `rgba(15,18,20,.05)` hover / `.10` active — no border in any state.
   The trash icon was also removed from this button's markup in
   app.js (renderCrAppSection) so there is no icon left to size here.

   Round 28 (2026-08-11 — Edit Role nested-header QA): this 26px
   ghost contract still applies everywhere this button is used
   EXCEPT Edit Role's per-application "Remove application" (Create
   Role's own accordion + Add User's `.au-role-card` "Remove" both
   keep it as-is). In Edit Role only, `buildAppSectionHtml` (app.js)
   now also adds the `.btn-std` class to that one button, which — via
   the higher-specificity, `!important` `button:is(.btn-std, …)` rule
   above — reuses the existing ADS compact outlined/secondary button
   component (36px, bordered, 6px radius) instead. That rule's
   `color: #4045c2` is the exact same indigo `.cr-app-remove` already
   used, so the label's text color is unchanged; only the border/
   background/height/padding/radius are new. */

@media (max-width: 900px) {
  .sim-excel-window { width: 100%; height: 100%; border-radius: 0; }
  .sim-excel-ribbon-tools { display: none; }
}

/* Round 33 (2026-08-11) — Edit Role nested application headers on
   narrow screens: below 640px there usually isn't enough row width
   for "[chevron] Application name" plus "Remove application" without
   crushing the name down to 2-3 characters (`text-overflow: ellipsis`
   still prevents overlap, but an unreadable name isn't "preserving
   the application name and toggle relationship" per the brief). Wrap
   the row so "Remove application" drops to its own line, flush with
   the chevron+name line's left edge, while the chevron stays
   immediately before the name on the line above — the toggle target
   is still the whole `.cr-app-section-head` row (both lines), so
   clicking either line still expands/collapses. Create Role is
   unaffected (its own accordion never had this crowding issue at the
   same breakpoint threshold; scoping to `.is-edit-mode` keeps this
   change isolated to Edit Role's now-wider chevron hit area). */
@media (max-width: 640px) {
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-section-head {
    flex-wrap: wrap;
    row-gap: 8px;
  }
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-title {
    flex-basis: calc(100% - 40px);
  }
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-app-section--matrix .cr-app-remove {
    order: 3;
    margin-left: 40px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Round 39 (2026-08-12) — Access Management card: ONE shared content
   inset for every row of the card.

   Symptom: the Filter button visibly protruded to the left of both the
   "Users" tab label above it and the table content below it, on every
   tab.

   Cause: the tab row and the toolbar were each given a 16px inset (see
   the "Final-QA correction, Figma node 1003:17823" comment on
   `.tabs-row` earlier in this file, whose stated goal was exactly "one
   consistent left content-edge") — but the ADS Primary Tab component
   carries its own 16px `padding-x` around its label. So the tab's outer
   box started at 16px while its LABEL — the thing you actually see and
   align to — started at 32px, leaving the toolbar's controls 16px
   further left than everything else in the card. The Users table had
   independently arrived at the correct edge (its Select column's own
   32px padding), which is why the checkbox looked right while Filter
   looked wrong.

   Fix: name the content edge once, as a custom property on the card,
   and have every row derive its own start padding from it:

     ┌─ --iam-card-content-inset ─────────────────────────────────
     │ Users   Roles   Teams        ← tab LABEL, not its padded box
     │ [Filter] [Internal|External] [Search]
     │ [checkbox column] / [Role]
     │ Show 10 …                    ← pagination
     └────────────────────────────────────────────────────────────

   The tabs row is the one row that must subtract the tab component's
   own padding (`--iam-tab-inline-pad`) so the LABEL, not the tab's
   outer box, lands on the shared edge. That expression resolves to the
   16px the row already had, so the tabs themselves do not move a pixel.

   Only the START edge is governed here. The card's rows deliberately
   do NOT share a single `padding-inline`: the table is full-bleed to
   the card's right edge, while Users' Region column is anchored to
   "Add User"'s left edge (see `align()` in app.js). Making the right
   gutter symmetric would therefore drag Region, Create Date, Export,
   Add User and Create Role 16px inward — movement this pass is
   explicitly not meant to cause. Every existing right-hand gutter is
   left untouched.

   No negative margins, no transforms, no absolute positioning and no
   per-panel offsets are involved: Users, Roles and Teams all read the
   same property, so their toolbars cannot drift apart. This also
   replaces the JS-written per-panel margins that Rounds 34/35 used
   (removed in Round 38 — see `align()` in app.js).
   ═══════════════════════════════════════════════════════════════════ */
html[data-iam-version="v4"] .v4-card {
  /* Where the card's content starts, measured from the card's inner
     edge. 32px = the ADS 8pt-grid step the tab labels already sat on. */
  --iam-card-content-inset: 32px;
  /* The ADS Primary Tab component's own horizontal padding — held at
     16px for every viewport by the "R57C authoritative Tabs" layer
     above (`.ads-tabs .ads-tab { padding: 8px 16px 0 !important }`).
     Declared here only so the tabs row can subtract it below. */
  --iam-tab-inline-pad: 16px;
}

/* Tab row — subtracts the tab's own padding so the LABEL lands on the
   shared edge. Resolves to the row's existing 16px: tabs don't move. */
html[data-iam-version="v4"] .v4-card .tabs-row {
  padding-inline-start: calc(var(--iam-card-content-inset) - var(--iam-tab-inline-pad));
}

/* Toolbar row (all three tabs) + pagination footer. The toolbar's left
   group keeps its own internal 12px gaps and moves as one unit — the
   Filter button gets no offset of its own, so Filter → segmented
   control → search spacing is unchanged. */
html[data-iam-version="v4"] .v4-card .tbar,
html[data-iam-version="v4"] .v4-card .pgn {
  padding-inline-start: var(--iam-card-content-inset);
}

/* First table column. The table itself stays full-bleed (its rows,
   hover wash and hairlines still span the whole card, and column widths
   are untouched); it's the first column's own content padding — shared
   by its header and every body cell, so they can never drift apart —
   that puts the first interactive control on the shared edge. Users'
   Select column already used exactly this 32px; Roles/Teams' first
   column carried a legacy 28px, now 4px further right and on the line
   with everything else. `!important` only to beat those legacy rules'
   own `!important`; Teams' also needs `#teamsPanel` to out-specify the
   ID its legacy rule is scoped with. */
html[data-iam-version="v4"] .v4-card #usersTable th.c-sel,
html[data-iam-version="v4"] .v4-card #usersTable td.c-sel,
html[data-iam-version="v4"] .v4-card .rp-tbl th.rp-role,
html[data-iam-version="v4"] .v4-card .rp-tbl td.rp-role,
html[data-iam-version="v4"] .v4-card #teamsPanel .tm-tbl th.tm-th-name,
html[data-iam-version="v4"] .v4-card #teamsPanel .tm-tbl td.tm-cell-name {
  padding-left: var(--iam-card-content-inset) !important;
}

/* Narrow screens: the card's own gutters tighten, so the shared inset
   tightens with them and every row stays on one edge. 16px is the value
   the tab labels already render at here (the tabs row drops to 0 and the
   tab component's 16px padding provides the whole inset), so — as
   above — the tabs stay exactly where they are while the toolbar and
   footer come into line with them. */
@media (max-width: 768px) {
  html[data-iam-version="v4"] .v4-card {
    --iam-card-content-inset: 16px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Final-QA pass (2026-08-12) — tab row on very narrow viewports.

   The base stylesheet already handles a tab row too narrow to hold
   Users/Roles/Teams on one line: at <=767px it sets `.tabs-row` to
   `height: auto` and lets `.tabs-row nav` wrap. The ADS Primary Tabs
   rules further up this file then restate a fixed `height: 56px` on the
   row and `height: 39px` on the nav at a much higher specificity
   (`html[data-iam-version="v4"] .v4-card ...`), which wins everywhere —
   including inside that media query. The wrap still happened, but the
   row could not grow to contain the second line, so "Teams" rendered
   on top of the toolbar beneath it.

   Restating the intent at the same specificity: keep 56px/39px as the
   MINIMUM (so the single-line case is pixel-identical to before) and
   let the box grow when a second line appears. The query stops below
   430px — the narrowest viewport where the three tabs still fit on one
   line — so every wider viewport, including all supported breakpoints
   from 1024px up, resolves to exactly the same geometry as before. */
@media (max-width: 429px) {
  html[data-iam-version="v4"] .v4-card .tabs-row {
    height: auto;
    min-height: 56px;
  }
  html[data-iam-version="v4"] .v4-card .tabs-row nav {
    height: auto;
    min-height: 39px;
    flex-wrap: wrap;
    row-gap: 4px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Compact desktop toolbar (769–1100px viewport).

   This deliberately uses one shared viewport breakpoint rather than a
   card container query. V4.1's fixed/collapsible product sidebar means
   the list card is already narrower than 1100px at the 1280 Redline
   preset; a 1100px card query would therefore leave both 1024 and 1280
   in the compact state and make the named QA presets indistinguishable.
   The viewport query gives the live 1024px Redline document the compact
   treatment and restores the established full-label desktop controls
   immediately above 1100px, without any JavaScript width checks.

   Mobile behavior below 769px remains owned by the existing narrow-screen
   rules. Compact desktop itself is always one flex row: the search is the
   only shrinking control, while the left and right action groups retain
   ADS-sized hit targets and normal document/tab order. */
@media (min-width: 769px) and (max-width: 1100px) {
  html[data-iam-version="v4"] .v4-card #usersPanel .tbar,
  html[data-iam-version="v4"] .v4-card #rolesPanel .tbar,
  html[data-iam-version="v4"] .v4-card #teamsPanel .tbar {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    height: 68px;
    min-height: 68px;
    column-gap: 12px;
    row-gap: 0;
  }

  html[data-iam-version="v4"] .v4-card #usersPanel .tbar-l,
  html[data-iam-version="v4"] .v4-card #rolesPanel .tbar-l,
  html[data-iam-version="v4"] .v4-card #teamsPanel .tbar-l {
    flex: 1 1 auto;
    min-width: 0;
    max-width: none;
    flex-wrap: nowrap;
    gap: 8px;
  }

  html[data-iam-version="v4"] .v4-card #usersPanel .tbar-r,
  html[data-iam-version="v4"] .v4-card #rolesPanel .tbar-r {
    align-self: center;
    flex: 0 0 auto;
    gap: 8px;
  }

  html[data-iam-version="v4"] .v4-card .tbar .ads-search {
    width: auto;
    min-width: 140px;
    max-width: 280px;
    flex: 1 1 220px;
  }

  html[data-iam-version="v4"] .v4-card #rolesPanel .tbar .ads-search,
  html[data-iam-version="v4"] .v4-card #teamsPanel .tbar .ads-search {
    min-width: 180px;
    max-width: 320px;
    flex-basis: 280px;
  }

  /* The SVG is the existing ADS search glyph; compact mode makes its
     visible presence explicit while retaining the same input and logic. */
  html[data-iam-version="v4"] .v4-card .tbar .ads-search .search-ico {
    display: block;
  }

  html[data-iam-version="v4"] .v4-card .tbar .toolbar-action-label {
    display: none;
  }

  html[data-iam-version="v4"] .v4-card .tbar #usersExportBtn,
  html[data-iam-version="v4"] .v4-card .tbar #usersAddBtn,
  html[data-iam-version="v4"] .v4-card .tbar #rolesCreateBtn {
    box-sizing: border-box;
    width: 36px;
    min-width: 36px;
    height: 36px;
    min-height: 36px;
    padding: 0;
    gap: 0;
    flex: 0 0 36px;
    justify-content: center;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Compact desktop detail pages — Edit User / Edit Role / Edit Team.

   Compact desktop uses the same 769–1100px viewport contract as the list
   toolbar above. The same grid is also retained on wider supported desktop
   widths because it is geometrically equivalent to the established Figma
   row there and prevents the older <=1199px rule from creating a one-pixel
   discontinuity at 1101px. Mobile below 769px keeps its existing fallback.
   The markup already has the right semantic shape (back navigation,
   title/subtitle block, action group). */
@media (min-width: 769px) {
  html[data-iam-version="v4"] #addUsersPage .au-header,
  html[data-iam-version="v4"] #editTeamPage .au-header,
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content;
    align-items: start;
    column-gap: 24px;
    row-gap: 0;
    flex-wrap: nowrap;
  }

  html[data-iam-version="v4"] #addUsersPage .au-header-left,
  html[data-iam-version="v4"] #editTeamPage .au-header-left,
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-header-left {
    min-width: 0;
  }

  html[data-iam-version="v4"] #addUsersPage .au-header-actions,
  html[data-iam-version="v4"] #editTeamPage .au-header-actions,
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-header-actions {
    width: auto;
    min-width: max-content;
    margin-top: 1px;
    padding-top: 0;
    justify-self: end;
    align-self: start;
    justify-content: flex-end;
    flex-wrap: nowrap;
  }

  html[data-iam-version="v4"] #addUsersPage .au-header-actions > *,
  html[data-iam-version="v4"] #editTeamPage .au-header-actions > *,
  html[data-iam-version="v4"] #createRolePage.is-edit-mode .cr-header-actions > * {
    flex-shrink: 0;
  }
}

/* Edit Role Functions matrix containment. The page and section hierarchy
   stay fixed while only this region scrolls horizontally. Each table's
   minimum width is derived from its real action-column count (240px
   Functions + 136px per action), avoiding needless scrollbars for small
   matrices while preserving stable labels and checkbox columns. */
html[data-iam-version="v4"] .au-page,
html[data-iam-version="v4"] .cr-page {
  overflow-x: hidden;
}

html[data-iam-version="v4"] #createRolePage .cr-perms-content,
html[data-iam-version="v4"] #createRolePage .cr-app-section--matrix,
html[data-iam-version="v4"] #createRolePage .cr-app-section-body {
  min-width: 0;
  max-width: 100%;
}

html[data-iam-version="v4"] #createRolePage .cr-app-section--matrix,
html[data-iam-version="v4"] #createRolePage .cr-app-body {
  overflow-x: hidden;
}

html[data-iam-version="v4"] #createRolePage .cr-matrix-scroll {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 8px;
  overscroll-behavior-inline: contain;
  -webkit-overflow-scrolling: touch;
}

html[data-iam-version="v4"] #createRolePage .cr-matrix-scroll:focus-visible {
  outline: 2px solid var(--brand-focus-ring);
  outline-offset: 2px;
  border-radius: 4px;
}

html[data-iam-version="v4"] #createRolePage .cr-matrix {
  --cr-matrix-min-width: 376px;
  width: max(100%, var(--cr-matrix-min-width));
  min-width: var(--cr-matrix-min-width);
}
html[data-iam-version="v4"] #createRolePage .cr-matrix[data-action-count="2"] { --cr-matrix-min-width: 512px; }
html[data-iam-version="v4"] #createRolePage .cr-matrix[data-action-count="3"] { --cr-matrix-min-width: 648px; }
html[data-iam-version="v4"] #createRolePage .cr-matrix[data-action-count="4"] { --cr-matrix-min-width: 784px; }
html[data-iam-version="v4"] #createRolePage .cr-matrix[data-action-count="5"] { --cr-matrix-min-width: 920px; }

/* Compact-only sticky Functions column. It remains one real table cell
   (no duplicate assistive-technology content), paints an opaque surface,
   and carries a subtle divider over horizontally moving checkbox cells. */
@media (min-width: 769px) and (max-width: 1100px) {
  html[data-iam-version="v4"] #createRolePage .cr-matrix-scroll .cr-matrix-th-fn,
  html[data-iam-version="v4"] #createRolePage .cr-matrix-scroll .cr-matrix-fn {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bg-surface);
    box-shadow: 1px 0 0 var(--border-default);
  }

  html[data-iam-version="v4"] #createRolePage .cr-matrix-scroll .cr-matrix-th-fn {
    z-index: 3;
  }
}

/* IAM page offset next to the shared Finance `.vnav` rail.
   Rail chrome lives in vnav.css. These rules only keep IAM content
   (Users / Roles / Teams and the Add/Edit surfaces) clear of that
   rail — they do not restyle the navigation. */
html[data-iam-version="v4"] main.page {
  padding-left: calc(var(--sidebar-width) + 48px);
  padding-right: 48px;
  max-width: none;
  margin: 0;
  transition: padding-left 220ms ease-out;
}
html[data-iam-version="v4"] .au-page,
html[data-iam-version="v4"] .cr-page {
  top: 56px;
  left: var(--sidebar-width);
  padding-left: 0;
  padding-right: 0;
  transition: left 220ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
  html[data-iam-version="v4"] main.page,
  html[data-iam-version="v4"] .au-page,
  html[data-iam-version="v4"] .cr-page { transition: none; }
}
