/* =========================================================================================
   PHASE 4 -- application chrome.

   THIS FILE LOADS LAST (page_header.tpl, after stylesheets.css and styles.css), which is the
   whole point of it existing. The theme carries 233 !important declarations and no CSS
   variables; loading last means these rules win on equal specificity without joining that
   arms race, and it keeps every Phase 4 layout rule in one file instead of scattered through
   two 3000-line sheets where the next person would never find them.

   Three things are set here:
     1. the header stack's colours -- one continuous white surface instead of grey/white bands
     2. the tab-nav row, moved out of the top bar into the content area
     3. the identity row (breadcrumb + workspace/brand selectors)
   ========================================================================================= */

/* =========================================================================================
   0. DESIGN TOKENS

   Measured across m=dashboard, m=contacts, m=deals, m=organizations and m=support before
   these existed: 17 font sizes, 36 text colours, 24 backgrounds, 17 radii, 5 shadows and two
   font families. The scales below are what the product actually needs; everything above them
   was accumulation.

   Custom properties resolve at computed-value time, not parse time, so the sheets that load
   BEFORE this one (common_admintable.css, admin-buttons.css, common_adminform.css) can still
   reference these names. That is what makes a token layer possible in a theme whose own
   sheets cannot be reordered.

   TYPE. `html` is 10px (vendor/bootstrap/css/bootstrap.css:1080), so `rem` is unusable here
   and every value is px. The fractional sizes this replaces (13.5 / 12.5 / 11.5 / 10.5px on
   ~70 declarations) were not rem arithmetic -- they were authored literally -- so they are
   snapped down onto the ramp rather than recomputed. 13.5 -> 13 rather than 14: several
   tables are already clipping horizontally and must not get wider.
   ========================================================================================= */
:root {
	--font-ui: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

	--fs-xs:   11px;   /* micro labels, uppercase eyebrows */
	--fs-sm:   12px;   /* meta, chips, table sub-text */
	--fs-md:   13px;   /* table body, buttons, nav rows */
	--fs-base: 14px;   /* forms, prose */
	--fs-lg:   16px;   /* panel titles */
	--fs-xl:   20px;   /* page titles, figures */

	/* TEXT. One family: slate. #101A2B is the ink the sidebar is painted in, so headings and
	   the chrome agree. #47566A is body copy at 7.0:1 on white; the two lighter steps are for
	   supporting text and never for the only copy in a control. */
	--ink:         #101A2B;
	--ink-2:       #35435A;
	--text:        #47566A;
	--text-muted:  #6B7A90;
	--text-soft:   #7C8AA0;
	--text-faint:  #9FADC0;
	--text-invert: #FFFFFF;

	/* ACCENT. #17803D carries white text at only 3.37:1, so it is reserved for non-text uses
	   -- the sidebar active rail, chips, icon accents -- where WCAG asks for 3:1. Anything
	   with a label on it uses --accent-fill (4.62:1) or --accent-text on a light ground. */
	--accent:      #F05B3A;
	--accent-fill: #D8431F;
	--accent-hot:  #C0301C;   /* hover for a filled accent */
	--accent-text: #C9421F;
	--accent-tint: #FEEDE9;

	--danger:      #B3261E;
	--danger-tint: #FDECEA;
	--success:     #186B4E;
	--success-tint:#E8F3EC;
	--warning:     #8A5A18;
	--warning-tint:#FDF1E3;

	/* SURFACES */
	--surface:      #FFFFFF;
	--surface-sunk: #FAFBFC;
	--surface-alt:  #F7F9FB;
	--surface-mute: #F1F3F6;
	--surface-well: #EEF1F4;
	--surface-ink:  #101A2B;

	--line:        #E4E7EC;
	--line-strong: #DDE2E9;

	--r-sm:   4px;
	--r-md:   8px;
	--r-lg:  12px;
	--r-pill: 999px;

	--sh-1: 0 1px 2px rgba(16, 26, 43, .06);
	--sh-2: 0 4px 12px rgba(16, 26, 43, .08);
	--sh-3: 0 14px 32px rgba(16, 26, 43, .12);

	--focus-ring: 2px solid #101A2B;
}

/* The app's inherited text colour was #949BA2 (styles/style.css:946 on `body`) -- 2.87:1 on
   white, below the threshold for any text size, and the reason 567 elements measured in a
   grey that belongs to no scale. Setting it here fixes every element that never declared a
   colour of its own. */
body {
	color: var(--text);
	font-family: var(--font-ui);
}

/* -----------------------------------------------------------------------------------------
   1. HEADER SURFACE

   Before: aside #fff, navbar #F2F2F2, an ancestor .navbar-collapse.collapse #DEDCDB, then the
   white identity row, then #F2F2F2 content. Four different greys stacked in 120px, which is
   what reads as broken banding. Now: one white surface for the whole header, a single hairline
   under it, and the light-grey page beneath so white cards still separate from the ground.
   ----------------------------------------------------------------------------------------- */
.navbar-default,
.navbar-default .navbar-collapse,
.navbar-default .navbar-collapse.collapse,
.navbar-default .navbar-header {
	background: #FFFFFF;
	border: 0;
	box-shadow: none;
}

.navbar-default {
	margin-bottom: 0;
	border-bottom: 1px solid #E4E4E4;
	min-height: 56px;
	position: relative;
	z-index: 300;
}

/* The toggle glyphs are authored as fill="white" for the old grey bar. On white they would be
   invisible, so they are recoloured here rather than by editing three inline SVGs. */
.navbar-default .left-nav-toggle svg path,
.navbar-header #mobile-menu .left-nav-toggle svg path {
	fill: #5E6877;
}

.navbar-default .left-nav-toggle a:hover svg path {
	fill: #23506F;
}



/* -----------------------------------------------------------------------------------------
   2. TAB NAV -- level-2 navigation, moved out of the top bar.

   Freed from sharing a row with the icon cluster, the old `max-width: calc(100% - 340px)`
   reserve is gone and the list gets the full width. It scrolls horizontally on its own rather
   than wrapping, so a tab with many sub-items never pushes the page taller.
   ----------------------------------------------------------------------------------------- */
.tab-nav {
	background: #FFFFFF;
	border-bottom: 1px solid #E4E4E4;
	/* 15px, not 24px: this must match Bootstrap's .container-fluid gutter, which is what the
	   page body below uses. At 24px the chrome sat 9px inboard of the content on both edges,
	   so the breadcrumb, tabs and switchers never lined up with the page title or the table
	   beneath them. The theme has no CSS variables, so the number is repeated, not shared. */
	padding: 0 15px;
}

.tab-nav-inner {
	display: flex;
	align-items: center;
	min-height: 52px;
}

/* Reset the rules the old in-navbar version needed. The theme sheets still carry them and
   load before this file, so they are neutralised here rather than deleted there -- the white
   theme still renders that markup inside its own top bar. */
.tab-nav .secondary-nav {
	float: none;
	max-width: 100%;
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
	display: flex;
	align-items: center;
	gap: 4px;
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: thin;
}

.tab-nav .secondary-nav::-webkit-scrollbar { height: 4px; }
.tab-nav .secondary-nav::-webkit-scrollbar-thumb { background: #D6D6D6; border-radius: 2px; }

.tab-nav .secondary-nav > li {
	margin: 0;
	padding: 0;
	flex: none;
}

.tab-nav .secondary-nav > li > a {
	display: block;
	width: auto;
	padding: 7px 14px;
	border-radius: 100px;
	background: transparent;
	color: var(--text);
	font-size: 13px;
	font-weight: 500;
	white-space: nowrap;
	text-decoration: none;
	transition: background .12s ease, color .12s ease;
}

.tab-nav .secondary-nav > li > a:hover,
.tab-nav .secondary-nav > li > a:focus {
	background: #F0F2F5;
	color: #1A1A1A;
	text-decoration: none;
}

/* --accent-on-fill, NOT --text-invert.

   This rule used to say `color: var(--text-invert)` (#FFFFFF) and the comment above it argued
   from 3.37:1 -- a figure that belonged to the ORIGINAL orange `--accent-fill: #D8431F` at
   line 60. When section 24 redefined --accent-fill to the green #3FBF3C it never revisited
   this rule, so the pill has been white-on-green at 2.41:1 ever since: the exact pairing the
   measured table at line 7690 records as "white label on #3FBF3C ........ 2.41:1  rejected".
   Section 24 created --accent-on-fill (#0B1533) for precisely this label and this fill.

   #0B1533 on #3FBF3C is 7.47:1. The 500 weight also matched every unselected sibling, so
   "selected" was carried by colour alone; 600 gives it a second signal. */
.tab-nav .secondary-nav > li.active > a {
	background: var(--accent-fill);
	color: var(--accent-on-fill);
	font-weight: 600;
}

/* The group label that six tabs carry. Bootstrap 3 also defines a `.label` badge -- inline,
   padded, white text -- which is why this uses its own class name rather than fighting it. */
.tab-nav .secondary-nav > li.tabnav-label {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--text-soft);
	padding: 0 12px 0 2px;
	margin-right: 4px;
	border-right: 1px solid #E4E4E4;
	align-self: stretch;
	display: flex;
	align-items: center;
}

.tab-nav .secondary-nav > li.tabnav-label:first-child { padding-left: 0; }

@media (max-width: 767px) {
	.tab-nav { padding: 0 14px; }
	.tab-nav-inner { min-height: 46px; }
	.tab-nav .secondary-nav > li > a { padding: 6px 11px; font-size: 12px; }
	.tab-nav .secondary-nav > li.tabnav-label { display: none; }
}

/* -----------------------------------------------------------------------------------------
   3. IDENTITY ROW -- workspace / brand / breadcrumb / switchers.
   Bootstrap 3.4.1 only -- no BS4/5 utilities exist in this theme.
   ----------------------------------------------------------------------------------------- */
.identity-bar {
	background: #FFFFFF;
	border-bottom: 1px solid #E4E4E4;
	/* 15px, not 24px: this must match Bootstrap's .container-fluid gutter, which is what the
	   page body below uses. At 24px the chrome sat 9px inboard of the content on both edges,
	   so the breadcrumb, tabs and switchers never lined up with the page title or the table
	   beneath them. The theme has no CSS variables, so the number is repeated, not shared. */
	padding: 0 15px;
}

.identity-bar-inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	min-height: 48px;
	flex-wrap: wrap;
}

/* ---- breadcrumb ---- */
.identity-crumbs {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	min-width: 0;
	font-size: 13px;
	line-height: 1.4;
}

.identity-crumbs > li {
	display: flex;
	align-items: center;
	color: var(--text);
	max-width: 320px;
}

.identity-crumbs > li + li:before {
	content: '';
	display: inline-block;
	width: 6px;
	height: 6px;
	margin: 0 10px;
	border-top: 1.5px solid #B9B9B9;
	border-right: 1.5px solid #B9B9B9;
	transform: rotate(45deg);
	flex: none;
}

.identity-crumbs a {
	color: var(--text);
	text-decoration: none;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.identity-crumbs a:hover,
.identity-crumbs a:focus {
	color: #1F1F1F;
	text-decoration: underline;
}

/* The "Workspace"/"Brand" kind labels. Small caps so the trail reads as a hierarchy
   rather than as three equally-weighted links. */
.identity-crumbs .crumb-kind {
	font-size: 10px;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--text-soft);
	margin-right: 6px;
	flex: none;
}

.identity-crumbs .crumb-name,
.identity-crumbs .crumb-current {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.identity-crumbs .crumb-current {
	color: #1F1F1F;
	font-weight: 600;
}

/* ---- right-hand controls ---- */
.identity-actions {
	display: flex;
	align-items: center;
	gap: 10px;
	flex: none;
}

.impersonation-badge {
	display: inline-block;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	padding: 3px 9px;
	border-radius: 3px;
	color: #8A5A00;
	background: #FFF3DC;
	border: 1px solid #F0DCB0;
}

.impersonation-badge.impersonation-readonly {
	color: #7A2E33;
	background: #FCE9EA;
	border-color: #F0C7C9;
}

.btn-exit-impersonation {
	display: inline-block;
	font-size: 12px;
	font-weight: 600;
	padding: 4px 12px;
	border-radius: 3px;
	color: #FFFFFF;
	background: var(--text);
	border: 1px solid #3C3C3C;
	text-decoration: none;
}

.btn-exit-impersonation:hover,
.btn-exit-impersonation:focus {
	color: #FFFFFF;
	background: var(--ink-2);
	text-decoration: none;
}

/* ---- brand switcher ---- */
.brand-switcher .brand-switcher-toggle {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 5px 12px 5px 6px;
	border: 1px solid #DCDCDC;
	border-radius: 4px;
	background: #FFFFFF;
	color: var(--ink-2);
	font-size: 13px;
	font-weight: 500;
	text-decoration: none;
	max-width: 260px;
}

.brand-switcher .brand-switcher-toggle:hover,
.brand-switcher .brand-switcher-toggle:focus,
.brand-switcher.open .brand-switcher-toggle {
	border-color: #B9B9B9;
	background: #FAFAFA;
	text-decoration: none;
}

.brand-switcher .brand-current {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.brand-initials {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	border-radius: 3px;
	background: #E9EDF1;
	color: #40566B;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .02em;
	flex: none;
}

.brand-initials.small {
	width: 20px;
	height: 20px;
	font-size: 9px;
	margin-right: 8px;
}

.brand-switcher-menu {
	max-height: 420px;
	overflow-y: auto;
	min-width: 260px;
	padding: 6px 0;
	/* Opaque, lifted, and above every dashboard widget. Without an explicit background and a
	   z-index that clears page content (dashboard cards sit at z-index 99, the Bootstrap
	   default 1000 is trapped inside the identity bar's own z-index:200 stacking context),
	   the home page showed THROUGH the open menu. */
	background: #FFFFFF;
	border: 1px solid rgba(0, 0, 0, .14);
	box-shadow: 0 8px 28px rgba(17, 26, 43, .18);
	z-index: 1200;
}

.brand-switcher-menu > li > a {
	display: flex;
	align-items: center;
	padding: 7px 14px;
	font-size: 13px;
	color: var(--ink-2);
}

.brand-switcher-menu > li.active > a,
.brand-switcher-menu > li.active > a:hover,
.brand-switcher-menu > li.active > a:focus {
	background: #F0F4F8;
	color: #23506F;
	font-weight: 600;
}

/* ---- workspace selector: its own control, sitting left of the brand one ---- */
.ws-switcher .ws-switcher-toggle {
	display: flex;
	align-items: baseline;
	gap: 8px;
	padding: 5px 12px;
	border: 1px solid #DCDCDC;
	border-radius: 4px;
	background: #FFFFFF;
	color: var(--ink-2);
	font-size: 13px;
	font-weight: 500;
	text-decoration: none;
	max-width: 260px;
}

.ws-switcher .ws-switcher-toggle:hover,
.ws-switcher .ws-switcher-toggle:focus,
.ws-switcher.open .ws-switcher-toggle {
	border-color: #B9B9B9;
	background: #FAFAFA;
	text-decoration: none;
}

/* The kind label is what stops two visually identical pills from being ambiguous. */
.ws-switcher .switcher-kind {
	font-size: 9px;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--text-soft);
	font-weight: 600;
	flex: none;
}

.ws-switcher .switcher-value {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ws-switcher-menu {
	max-height: 420px;
	overflow-y: auto;
	min-width: 268px;
	padding: 6px 0;
	background: #FFFFFF;
	border: 1px solid rgba(0, 0, 0, .14);
	box-shadow: 0 8px 28px rgba(17, 26, 43, .18);
	z-index: 1200;
}

.ws-switcher-menu > li > a {
	display: flex;
	align-items: center;
	padding: 7px 14px;
	font-size: 13px;
	color: var(--ink-2);
}

.ws-switcher-menu > li.active > a,
.ws-switcher-menu > li.active > a:hover,
.ws-switcher-menu > li.active > a:focus {
	background: #F0F4F8;
	color: #23506F;
	font-weight: 600;
}

/* Shared note row, used for the read-only warning and for empty states. */
.ws-switcher-menu .switcher-note,
.brand-switcher-menu .switcher-note {
	padding: 8px 14px;
	font-size: 11px;
	line-height: 1.45;
	color: #8A8A8A;
	cursor: default;
	white-space: normal;
}

.ws-switcher-menu .switcher-note {
	color: #8A5A00;
	background: #FFF9EE;
	border-bottom: 1px solid #F0E4CC;
	margin-bottom: 4px;
}

/* Workspace rows have no initials chip, so a fixed-width tick keeps their labels aligned
   with the brand rows in the control beside them. */
.ws-switcher-menu .switcher-tick,
.brand-switcher-menu .switcher-tick {
	display: inline-block;
	width: 20px;
	margin-right: 8px;
	color: #23506F;
	font-weight: 700;
	flex: none;
}

.ws-switcher-menu .switcher-ws-hint,
.brand-switcher-menu .switcher-ws-hint {
	margin-left: auto;
	padding-left: 10px;
	font-size: 10px;
	color: var(--text-soft);
	white-space: nowrap;
}

.brand-switcher-menu .divider {
	margin: 5px 0;
}

.brand-switcher-menu .dropdown-header {
	font-size: 10px;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--text-soft);
	padding: 8px 14px 4px;
}

@media (max-width: 767px) {
	.identity-bar { padding: 0 14px; }
	.identity-bar-inner { min-height: 44px; padding: 6px 0; }
	.identity-crumbs { font-size: 12px; }
	.identity-crumbs .crumb-kind { display: none; }
	.brand-switcher .brand-switcher-toggle { max-width: 160px; }
	.ws-switcher .ws-switcher-toggle { max-width: 150px; }
	.ws-switcher .switcher-kind { display: none; }
}

/* -----------------------------------------------------------------------------------------
   4. FIXES FOR DEFECTS THE LAYOUT AUDIT MEASURED

   Everything below was found by rendering each tab in headless Chrome and measuring boxes,
   not by reading CSS. Each block says what was measured.
   ----------------------------------------------------------------------------------------- */

/* 4.1 CHROME SCROLLED AWAY WITH THE PAGE.
   section.content is the app's only scroll container (position:absolute, height:100vh,
   overflow-y:auto -- styles/style.css:950-969) and index.tpl renders the identity and tab
   rows INSIDE it, so both scrolled out of view and also consumed 162-184px of the 100vh the
   page body believed it had. Sticky pins them without restructuring the scroller: the rows
   stay in flow (so nothing below shifts) but stop at the top edge. */
.identity-bar {
	position: sticky;
	top: 0;
	/* Was 60 -- below dashboard widgets (z-index 99) and several route stylesheets (999),
	   so an open brand/workspace menu was painted over by page content. 200 clears all
	   ordinary page chrome while staying well under modal overlays (1040+). */
	z-index: 200;
}

.tab-nav {
	position: sticky;
	/* Exactly the identity row's height, so the two stack instead of overlapping. */
	top: 48px;
	z-index: 199;
}

@media (max-width: 767px) {
	.tab-nav { top: 44px; }
}

/* 4.2 IDENTITY ROW WRAPPED ONTO TWO LINES BELOW ~1400px.
   .identity-bar-inner had flex-wrap:wrap with a non-shrinking crumb list, so wrapping always
   beat truncating and the row grew instead of the text ellipsing. Measured headroom at
   1440px was ~15px, so most laptops wrapped on most routes. The crumbs now shrink and
   ellipse; the controls keep their width. */
.identity-bar-inner {
	flex-wrap: nowrap;
}

.identity-crumbs {
	flex: 1 1 auto;
	min-width: 0;
	flex-wrap: nowrap;
	overflow: hidden;
}

.identity-crumbs > li {
	min-width: 0;
}

/* The last crumb is the page name and the most useful one, so it gives up space last. */
.identity-crumbs > li.crumb-workspace,
.identity-crumbs > li.crumb-brand {
	flex: 0 1 auto;
}

.identity-crumbs > li.crumb-current {
	flex: 0 1 auto;
}

.identity-actions {
	flex: 0 0 auto;
}

/* 4.3 EVERY RIGHT-ALIGNED ACTION ROW FINISHED 10px SHORT OF THE CONTENT EDGE.
   .ab-button carries a blanket margin-right:10px (stylesheets.css:1661) and its row is
   flex/flex-end, so the trailing margin on the last item is never absorbed -- it becomes
   dead space. Buttons therefore never lined up with the table, the calendar grid or the
   brand switcher above them. */
.adminbuttons > .ab-button:last-child,
.adminbuttons > a.ab-button:last-child,
.adminbuttons > input[type="submit"]:last-child {
	margin-right: 0;
}

/* 4.4 CONTENT JUMPED BETWEEN SIBLING TABS.
   Measured: Calendar and Tasks started content at y=290, Booked Calls at y=222 -- the exact
   height of the action-toolbar row, which Booked Calls does not render. Before the -60px
   hoist was removed the toolbar occupied no space at all, so the gap was smaller but the
   buttons were painted over the chrome; fixing the overlap made the inconsistency bigger.

   So the band is RESERVED on every route instead of being contributed by the toolbar. The
   padding holds the space open whether or not a toolbar exists, and a toolbar that does exist
   is pulled up into it. This is not the old -60px trick: that had nothing reserving the space,
   which is exactly why `.buttons-section` collapsed to height 0 and the button escaped its
   container. Here the parent's padding cannot collapse, so the row stays inside its box.

   The lift is scoped to a FIRST-CHILD toolbar. Routes like Tasks render two button groups in
   one row; lifting a later one would drop it onto the page title. */
.block > .body-wrapper > .block-content-outer {
	padding-top: 58px;
}

/* The band is released for the FIRST toolbar wherever it sits. `:first-child` alone was wrong:
   several modules emit a hidden node -- a `div.modal.hidden`, a `.bulkactions`, a `<script>` --
   before the toolbar, so the selector did not match, the -58px was never applied, and the 58px
   of reserved padding became dead space above the toolbar. Measured on m=customers, the app's
   busiest list: toolbar 58px low, content 154px lower than the sibling Lists tab.
   The `~` rule keeps a SECOND toolbar in place, which is the case the reservation must not
   hoist (routes like Tasks render two button groups in one row). */
.block > .body-wrapper > .block-content-outer > .additional-buttons-section,
.block > .body-wrapper > .block-content-outer > .tablewrapper > .additional-buttons-section,
.block > .body-wrapper > .block-content-outer > form > .additional-buttons-section {
	margin-top: -58px;
	margin-bottom: 0;
	min-height: 58px;
	align-items: center;
}

/* Only the FIRST toolbar in a container is hoisted into the reserved band. Scoped by sibling
   order rather than by `:first-child`, which fails whenever a module emits a hidden node --
   a `div.modal.hidden`, a `<script>`, a hidden `<input>` -- ahead of the toolbar. m=support
   hit exactly that: its toolbar sits inside a <form> behind a hidden input. */
.block-content-outer .additional-buttons-section ~ .additional-buttons-section {
	margin-top: 0;
	min-height: 0;
}

.additional-buttons-section:empty {
	display: none;
	margin: 0;
	min-height: 0;
}

/* 4.7 FULLCALENDAR RENDERED IN ITS OWN STOCK THEME.
   Measured bg rgb(26,37,47) -- FullCalendar v5's default dark navy -- against a CRM whose
   primary is #17803D and whose buttons are 8px-radius outlines. Nothing in the theme styles
   .fc-* at all, so the calendar looked like a third-party widget dropped into the page. */
.fc .fc-button-primary {
	background: #FFFFFF;
	border: 1.5px solid #DCDCDC;
	color: var(--text);
	font-weight: 600;
	font-size: 13px;
	text-transform: capitalize;
	box-shadow: none;
	padding: 6px 14px;
}

.fc .fc-button-primary:hover {
	background: #F5F6F8;
	border-color: #B9B9B9;
	color: #1F1F1F;
}

.fc .fc-button-primary:not(:disabled):active,
.fc .fc-button-primary:not(:disabled).fc-button-active {
	background: #3FBF3C;
	border-color: #17803D;
	color: #0B1533;
}

.fc .fc-button-primary:focus,
.fc .fc-button-primary:not(:disabled):active:focus {
	box-shadow: 0 0 0 3px rgba(63, 191, 60,.22);
}

.fc .fc-button-primary:disabled {
	background: #F5F6F8;
	border-color: #E4E4E4;
	color: #A8A8A8;
}

.fc .fc-button-group > .fc-button:first-child { border-radius: 8px 0 0 8px; }
.fc .fc-button-group > .fc-button:last-child  { border-radius: 0 8px 8px 0; }
.fc .fc-button-group > .fc-button:only-child,
.fc .fc-toolbar > * > .fc-button:not(.fc-button-group .fc-button) { border-radius: 8px; }

.fc .fc-toolbar-title {
	/* px, not rem: this theme sets html{font-size:10px}, so 1.15rem rendered at 11.5px --
	   the calendar title was smaller than its own day numbers. Never use rem here. */
	font-size: 18px;
	font-weight: 600;
	color: #1F1F1F;
}

.fc .fc-toolbar.fc-header-toolbar { margin-bottom: 14px; }
.fc .fc-col-header-cell-cushion { color: #5E6877; font-weight: 600; font-size: 12px; }
.fc-theme-standard td, .fc-theme-standard th, .fc-theme-standard .fc-scrollgrid { border-color: #E4E4E4; }
.fc .fc-daygrid-day.fc-day-today { background: #FFF4F1; }

/* 4.5 THE PUSH-NOTIFICATION PROMPT SAT ON TOP OF THE PAGE.
   notifications.css:15-26 pins it at top:10px/left:100px, z-index:9999 -- coordinates from
   before this theme had a 250px sidebar, let alone an identity row -- so on every route it
   floated over the sidebar and the first content card. Moved to the bottom-right, out of the
   reading path, and below the sticky chrome.

   THE THREE SELECTORS BELOW #allow-push-notification-bar MATCH NOTHING. They were written
   against guessed class names and this rule never once applied: the live element is
   `#allow-push-notification-bar` (index.tpl:545), measured at x=100 y=10 w=288 h=105 with
   the brand logo at x=99 y=16 w=49 h=34 -- 100% covered -- on every route. They are kept
   only because themes/default emits the same prompt and may yet be renamed; the id is what
   does the work. Confirm a selector against the DOM before writing CSS against it. */
#allow-push-notification-bar,
.allow-push-notification-bar,
.notification-permission-prompt,
.browser-notification-prompt,
#notification-permission-bar {
	top: auto !important;
	left: auto !important;
	right: 20px !important;
	bottom: 20px !important;
	z-index: 55 !important;
	max-width: 340px;
	box-shadow: var(--sh-3);
	border-radius: var(--r-md);
}

/* The prompt owned the only filled primary button on Home -- a colour scan for filled orange
   returned exactly two hits, the sidebar active tint and this "Configure". The landing page
   of a sales CRM does not get to make browser notifications its call to action, so the
   button reverts to the neutral scale and the dismiss control beside it is the same weight. */
#allow-push-notification-bar .text {
	padding-right: 22px;
	font-size: var(--fs-md);
	color: var(--text);
	line-height: 1.45;
}

#allow-push-notification-bar .buttons-more {
	display: flex;
	gap: 8px;
	padding: 10px 0 0;
	margin: 0;
}

#allow-push-notification-bar .ok-button {
	min-height: 32px;
	padding: 5px 14px;
	border: 1px solid var(--line-strong);
	border-radius: 7px;
	background: var(--surface);
	color: var(--ink-2);
	font-size: var(--fs-md);
	font-weight: 600;
	cursor: pointer;
}

#allow-push-notification-bar .ok-button:hover {
	background: var(--surface-alt);
	border-color: #C7D0DB;
	color: var(--ink);
}

#close-push-notification {
	position: absolute;
	top: 6px;
	right: 6px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	padding: 0;
	border: 0;
	border-radius: var(--r-sm);
	background: transparent;
	color: var(--text-soft);
	font-size: var(--fs-lg);
	line-height: 1;
	cursor: pointer;
}

#close-push-notification:hover {
	background: var(--surface-mute);
	color: var(--ink);
}

/* 4.6 NO SCROLLBAR ANYWHERE.
   styles/style.css:1032-1036 sets ::-webkit-scrollbar{width:0} globally and unscoped, so the
   app's only scroll container gives no hint that there is more content. A thin one restores
   the affordance without reclaiming much width. */
.content::-webkit-scrollbar { width: 8px; }
.content::-webkit-scrollbar-track { background: transparent; }
.content::-webkit-scrollbar-thumb { background: #D0D4D9; border-radius: 4px; }
.content::-webkit-scrollbar-thumb:hover { background: #B4BAC2; }
.content { scrollbar-width: thin; scrollbar-color: #D0D4D9 transparent; }

/* =========================================================================================
   5. SIDEBAR

   The palette itself is admin-configurable (Control Panel > Themes > Customize Theme Colors)
   and its defaults live in themes/vertical/themeinit.php, which is what "Reset To Defaults"
   restores. What is NOT configurable, and deliberately so, is the ACTIVE row treatment: it is
   derived from the product's primary #17803D, so the selected item stays unmistakable no
   matter which navigation background an admin picks. A themeable active colour is how you end
   up with an invisible selected state, which is the defect this replaces.
   ========================================================================================= */

.navigation {
	width: 248px;
}

.luna-nav.nav {
	padding: 8px 10px;
}

.luna-nav.nav > li {
	margin-bottom: 2px;
}

.luna-nav.nav > li > a {
	position: relative;
	display: flex;
	align-items: center;
	min-height: 40px;
	padding: 8px 12px;
	border-radius: 7px;
	font-size: var(--fs-md);
	font-weight: 500;
	line-height: 1.3;
	letter-spacing: -.005em;
	transition: background-color .13s ease, color .13s ease;
}

.luna-nav.nav > li > a > div {
	display: flex;
	align-items: center;
	gap: 12px;
	min-width: 0;
	width: 100%;
}

.luna-nav.nav > li > a .main-menu-icon {
	flex: none;
	width: 20px;
	height: 20px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	opacity: .9;
}

.luna-nav.nav > li > a .main-menu-icon svg,
.luna-nav.nav > li > a .main-menu-icon img {
	width: 18px;
	height: 18px;
}

.luna-nav.nav > li > a .main-menu-text {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}

/* ACTIVE ROW.
   An orange rail plus a tint of the same colour. The rail is what the eye finds when scanning
   a vertical list; the tint alone was the old behaviour and was almost invisible against a
   dark navy. `!important` is required here and only here: customstyles.php emits the link
   colours as inline !important declarations at stylesheet index 0, so nothing else can win. */
.navigation .luna-nav.nav > li.active > a,
body.nav-toggle .navigation .luna-nav.nav > li.active > a {
	background-color: rgba(63, 191, 60, .15) !important;
	color: #FFFFFF !important;
	font-weight: 600;
}

.navigation .luna-nav.nav > li.active > a:before {
	content: '';
	position: absolute;
	left: 0;
	top: 50%;
	transform: translateY(-50%);
	width: 3px;
	height: 22px;
	border-radius: 0 3px 3px 0;
	background: #3FBF3C;
}

.navigation .luna-nav.nav > li.active > a .main-menu-icon {
	opacity: 1;
	color: #17803D;
}

.navigation .luna-nav.nav > li.active > a .main-menu-icon svg path {
	fill: #17803D;
	stroke: #17803D;
}

/* The old rule painted a lilac chip behind the active icon -- a colour that appears nowhere
   else in the product. */
body.nav-toggle .navigation .luna-nav.nav li.active a .main-menu-icon {
	background-color: transparent;
}

.navigation .luna-nav.nav > li:not(.active) > a:hover {
	color: #FFFFFF;
}

/* Section labels between groups of items. */
.luna-nav.nav .main-menu-label {
	display: block;
	padding: 14px 12px 6px;
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	opacity: .55;
}

/* ---- collapsed rail -------------------------------------------------------------------
   Two logos: the full lockup when open, a compact mark when collapsed. Both are uploaded in
   Control Panel; the collapsed one falls back to the theme's own mark if none is set. */
.navigation .tog-button-left,
.navigation .navbar-mibile-view {
	display: flex;
	align-items: center;
	min-height: 56px;
	padding: 8px 14px;
}

.navigation .navbar-brand img { max-height: 34px; width: auto; }
.navigation .navbar-mibile-view { display: none; }
.navigation .navbar-mibile-view img { max-height: 30px; width: auto; margin: 0 auto; }

body.nav-toggle .navigation { width: 68px; }
body.nav-toggle .navigation .tog-button-left { display: none; }
body.nav-toggle .navigation .navbar-mibile-view { display: flex; justify-content: center; }
body.nav-toggle .content { width: calc(100% - 68px); margin-left: 68px; }

body.nav-toggle .luna-nav.nav > li > a { justify-content: center; padding: 8px; }
body.nav-toggle .luna-nav.nav > li > a > div { gap: 0; justify-content: center; }
body.nav-toggle .luna-nav.nav > li > a .main-menu-text { display: none; }
body.nav-toggle .luna-nav.nav .main-menu-label { display: none; }
body.nav-toggle .navigation .luna-nav.nav > li.active > a:before { height: 26px; }

/* =========================================================================================
   6. DASHBOARD STAT CARDS

   The four cards are Bootstrap 3 `.col-md-3` floats, so each is only as tall as its own
   content. "Emails" wraps its second label onto two lines and therefore stood ~40px taller
   than its neighbours, and the row read as broken rather than as a set. A flex row with
   stretch alignment makes height a property of the ROW, so the tallest card sets all four and
   the labels can wrap freely without any of them needing a fixed height.
   ========================================================================================= */
.daylistats > div {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	margin: 0 -8px;
}

.daylistats > div > .statsbox {
	float: none;
	display: flex;
	padding: 0 8px 16px;
}

.daylistats > div > .statsbox > .wrapper {
	display: flex;
	flex-direction: column;
	width: 100%;
	background: #FFFFFF;
	border: 1px solid #EAECEF;
	border-radius: 10px;
	padding: 18px 20px;
	box-shadow: 0 1px 2px rgba(16,26,43,.04);
}

.daylistats > div > .statsbox > .wrapper > div { display: flex; flex-direction: column; flex: 1; }

.daylistats .panel-heading { padding: 0 0 14px; border: 0; background: none; }
.daylistats .panel-heading h4 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.01em; }
.daylistats .panel-heading h4 a { color: #101A2B; text-decoration: none; }

.daylistats .tab-content,
.daylistats .tab-pane.active { flex: 1; display: flex; }

/* The two halves of a card. Equal columns, top-aligned, so a label that wraps to two lines
   pushes nothing sideways and both metrics keep the same baseline. */
.daylistats .content-container {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	width: 100%;
}

.daylistats .content-container > [class*="col-md-"] {
	float: none;
	width: 50%;
	padding: 0;
	min-width: 0;
}

.daylistats .messages-stats > div > div { display: flex; align-items: flex-start; gap: 10px; }

.daylistats .icon {
	flex: none;
	width: 40px;
	height: 40px;
	border-radius: 9px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.daylistats .stats-info { min-width: 0; }
.daylistats .stats-info .text {
	font-size: var(--fs-sm);
	line-height: 1.35;
	color: #5E6877;
	/* Reserve two lines so "Emails Received" wrapping cannot make one card taller than the
	   rest even before the flex row equalises them. */
	min-height: 34px;
}
.daylistats .stats-info .text a { color: #5E6877; text-decoration: none; }
.daylistats .stats-info .numbers { font-size: 22px; font-weight: 700; color: #101A2B; line-height: 1.15; }

/* The three list cards below (Contacts / Opportunities / Leads) get the same treatment so the
   two rows read as one system. */
.dashboard-lists-row { display: flex; flex-wrap: wrap; align-items: stretch; margin: 0 -8px; }
.dashboard-lists-row > [class*="col-md-"] { float: none; display: flex; padding: 0 8px 16px; }

/* =========================================================================================
   7. RESPONSIVE

   The theme is desktop-only below the surface: a 250px absolutely-positioned sidebar, a
   100vh scroller offset by it, and chrome rows built for a wide viewport. These rules make
   the shell usable on a phone without rewriting the layout: the sidebar becomes an off-canvas
   drawer, the chrome collapses to essentials, and every wide element scrolls inside its own
   box instead of forcing the page sideways.
   ========================================================================================= */
@media (max-width: 991px) {
	.daylistats > div > .statsbox { width: 50%; }
}

@media (max-width: 767px) {
	/* Sidebar off-canvas. It is position:absolute in this theme, so it is translated rather
	   than reflowed -- reflowing it would push the whole app column sideways. */
	.navigation {
		position: fixed;
		top: 0;
		left: 0;
		bottom: 0;
		z-index: 1040;
		transform: translateX(-100%);
		transition: transform .25s ease;
		width: 264px;
	}
	body.nav-toggle .navigation { transform: translateX(0); width: 264px; }
	body.nav-toggle .navigation .tog-button-left { display: flex; }
	body.nav-toggle .navigation .navbar-mibile-view { display: none; }
	body.nav-toggle .luna-nav.nav > li > a { justify-content: flex-start; padding: 8px 12px; }
	body.nav-toggle .luna-nav.nav > li > a > div { gap: 12px; justify-content: flex-start; }
	body.nav-toggle .luna-nav.nav > li > a .main-menu-text { display: inline; }

	/* `section.content` -- element+class, to match the specificity of style.css:950, which sets
	   `width: calc(100% - 250px)`. A bare `.content` here lost that fight and left the page
	   140px wide on a 390px phone. */
	section.content,
	body.nav-toggle section.content {
		width: 100% !important;
		margin-left: 0 !important;
		left: 0 !important;
		position: relative !important;
		height: auto !important;
		min-height: 100vh;
	}

	/* Chrome: keep the brand switcher, drop the decoration. */
	.identity-bar { padding: 0 12px; position: static; }
	.tab-nav { padding: 0 12px; position: static; }
	.identity-bar-inner { min-height: 44px; gap: 8px; }
	.identity-crumbs .crumb-kind { display: none; }
	.identity-crumbs > li.crumb-workspace { display: none; }
	.ws-switcher { display: none; }

	.container-fluid { padding-left: 12px; padding-right: 12px; }

	/* Toolbars stack instead of overflowing. The reserved 58px band is a desktop concern. */
	.block > .body-wrapper > .block-content-outer { padding-top: 12px; }
	.block > .body-wrapper > .block-content-outer > .additional-buttons-section:first-child {
		margin-top: 0;
		min-height: 0;
		flex-wrap: wrap;
		gap: 8px;
	}
	.additional-buttons-section .adminbuttons { justify-content: flex-start; flex-wrap: wrap; gap: 8px; }
	.ab-button { margin-right: 0; }

	/* One card per row, and let wide content scroll inside its own box rather than the page. */
	.daylistats > div > .statsbox { width: 100%; }
	.table-responsive, .tablewrapper { overflow-x: auto; -webkit-overflow-scrolling: touch; }
	.fc .fc-toolbar.fc-header-toolbar { flex-wrap: wrap; gap: 8px; }
	.fc .fc-toolbar-title { font-size: 16px; }  /* px: html is 10px, 1rem would be 10px */
}

/* Nothing may force the whole page sideways at any width. */
body { overflow-x: hidden; }

/* =========================================================================================
   8. PADDING STANDARDISATION

   The plan called this a "long tail, one module stylesheet per PR". Measured across all 42
   routes it is not a tail at all -- it is four rules. Every deviation traces to a per-route
   sheet declaring a BARE APP-SHELL SELECTOR: `.content`, `.body-wrapper` and `.container-fluid`
   are structural elements of the shell, but `pb_add_cssfile()` lets one route redefine them for
   itself. identity.css loading last is what makes reclaiming them possible.
   ========================================================================================= */

/* 8.1 The app column owns its own padding, including the 30px of bottom scroll runway.
   themes/vertical/contacts/details.css:5 and companies/details.css:5 each declare a bare
   `.content { padding: 0 }`, which is section.content -- the ONLY scroll container in the app.
   Measured: the ~76 contact/company detail screens ended flush against the viewport with
   nothing under the last row. */
section.content {
	padding: 0 0 30px 0;
}

/* 8.2 The page gutter is Bootstrap's 15px, everywhere.
   themes/default/all_conversation.css:7 declares `.content .container-fluid { padding: 0 }`,
   which zeroed the gutter for the whole Inbox route: the card ran edge-to-edge while the
   identity and tab rows above it stayed at 15px, and it produced 9px of horizontal overflow. */
section.content > .container-fluid {
	padding-left: 15px;
	padding-right: 15px;
}

/* 8.3 Detail pages must not add a second horizontal inset on top of the gutter.
   contacts/details.css:12 and companies/details.css:12 add `padding: 24px 65px 24px 24px`
   INSIDE the 15px gutter, giving 39px left and 80px right -- a visibly lopsided page, on the
   two most-used modules in the CRM. The vertical 24px is kept; only the horizontal goes.
   The 65px was not reserving room for the slide-in panels: those are position:absolute, and
   absolute offsets resolve against the padding box, which padding does not move.

   CORRECTION (SS17). Half of that is right and half is wrong, and the wrong half cost the right
   edge of both record pages. `right: 0` does resolve against the padding box, so padding cannot
   MOVE the panel -- but the panel is 210px wide with `margin-right: -165px`, so 45px of it sits
   INSIDE the container, over the content. The 65px was keeping content out from under those
   45px. Removing it did not move the rail; it moved the content under the rail. SS17 puts a
   gutter back, sized to the rail rather than to the old arbitrary 65px. */
.customer-details-wrapper,
.company-details-wrapper {
	padding-left: 0;
	padding-right: 0;
}

/* 8.4 No 180px of dead space under a page.
   `.body-wrapper { padding-bottom: 180px }` is declared bare in three separate per-route
   sheets (triggers.css:174, searchconditions.css:195, marketingsequences.css:188). There is no
   fixed footer in any of them that would need the clearance. */
.block > .body-wrapper {
	padding-bottom: 0;
}

/* 8.5 Reserve the scrollbar gutter so the column width never changes.
   Routes whose content is short have no scrollbar and are 11px wider than routes that do, so
   every right-aligned element -- the action button, the table edge, the brand switcher in the
   sticky bar -- jumped 11px left the moment a page happened to be long enough to scroll. */
.content {
	scrollbar-gutter: stable;
}

/* =========================================================================================
   9. COMPONENT CONSISTENCY

   The same control was drawn differently depending on which route you were on. The cause is
   structural, not cosmetic: admin-buttons.css is OPT-IN -- 32 of 42 modules call
   pb_add_cssfile('admin-buttons.css'), and the other ten simply render unstyled buttons. A
   component definition that a route can forget to load is not a component. These are defined
   here instead, where every route gets them.
   ========================================================================================= */

/* 9.1 ONE BUTTON SCALE, and one accent.
   ------------------------------------------------------------------------------------------
   Measured before changing anything: three distinct button appearances across eleven screens,
   and the common one was 42px tall with 25px of horizontal padding, 14px type -- large enough
   that a row of three filled most of a toolbar.

   The size was the smaller problem. Every ordinary button was ALSO orange: outline, orange text,
   orange border. Nineteen of the twenty-four buttons measured were shouting exactly as loudly as
   the five that mattered, which is the same as none of them shouting. Colour is the hierarchy
   here, not size:

     default   white, hairline border, dark text   -- an action
     .primary  solid orange, white text            -- THE action on this screen
     danger    red, and only where something is destroyed

   36px with 13px type is the working size for a dense CRM: comfortably clickable, and three of
   them fit a toolbar without crowding it. */
input[type="submit"],
button[type="submit"],
.ab-button,
.adminform_savebutton input,
.create-button,
.searchbutton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	min-height: 36px;
	padding: 7px 16px;
	border-radius: 7px;
	border: 1px solid #DDE2E9;
	background: #FFFFFF;
	color: #35435A;
	font-size: 13px;
	font-weight: 600;
	line-height: 20px;
	text-align: center;
	vertical-align: middle;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}

input[type="submit"]:hover,
button[type="submit"]:hover,
.ab-button:hover,
.adminform_savebutton input:hover,
.create-button:hover,
.searchbutton:hover {
	background: #F7F9FB;
	border-color: #C7D0DB;
	color: #101A2B;
	text-decoration: none;
}

input[type="submit"]:focus-visible,
button[type="submit"]:focus-visible,
.ab-button:focus-visible {
	border-color: var(--accent);
	box-shadow: none;
}

/* 9.2 Solid orange means ONE thing: the primary action on this screen.
   The framework's own Save button qualifies -- it is the only action on a form -- so it is
   targeted by its wrapper rather than by `input[type=submit]`, which would also have filled
   every toolbar Search button and put us back where we started. */
/* The fill is --accent-fill (#17803D), NOT the product accent #17803D. White on #17803D
   measures 3.37:1 -- below AA -- and these buttons render at 13px/600 and 12px/500, neither
   of which qualifies as large text, so no exemption applies. #17803D carries white at
   4.62:1. #17803D is unchanged everywhere it is not behind text: the sidebar active rail,
   chips, icon accents, focus tints -- all of which only need 3:1. Raising the type instead
   was the other option and is not one: 18.66px buttons break every toolbar in the app. */
.ab-button.primary,
input[type="submit"].primary,
button[type="submit"].primary,
.adminform_savebutton input[type="submit"] {
	background: var(--accent-fill);
	color: var(--text-invert);
	border-color: var(--accent-fill);
}

.ab-button.primary:hover,
input[type="submit"].primary:hover,
button[type="submit"].primary:hover,
.adminform_savebutton input[type="submit"]:hover {
	background: var(--accent-hot);
	border-color: var(--accent-hot);
	color: var(--text-invert);
}

/* Destructive, and only that. */
.ab-button.danger {
	background: #B3261E;
	border-color: #17803D;
	color: #FFFFFF;
}
.ab-button.danger:hover {
	background: #A82818;
	border-color: #A82818;
	color: #FFFFFF;
}
.ab-button.quiet-danger {
	background: #FFFFFF;
	border-color: #DDE2E9;
	color: #9A2A18;
}
.ab-button.quiet-danger:hover {
	background: #FDECEA;
	border-color: #F0C4BD;
	color: #B3261E;
}

/* Segmented / current state: tinted, not filled, so the fill stays reserved for priority. */
.ab-button.active,
.current.ab-button {
	background: #FEEDE9;
	color: #17803D;
	border-color: #F7BCAA;
	font-weight: 600;
}

/* Bootstrap's own buttons sit beside these in dropdowns and modals. Metrics only -- their
   colours are left alone, because `.btn-danger` on a modal means what it says and recolouring
   third-party components is how a "standardisation" pass breaks a screen nobody opened. */
.btn,
.btn-secondary,
.btn-primary,
.btn-danger {
	box-sizing: border-box;   /* without it their border sat outside the 36px and they measured 37 */
	min-height: 36px;
	padding: 7px 16px;
	border-radius: 7px;
	font-size: 13px;
	font-weight: 600;
	line-height: 20px;
}

/* An <input> cannot lay its value out as a flex child, so the flex properties above are inert on
   one -- harmless, but the centring has to come from the input's own text-align. Stated rather
   than relied on, because `display:inline-flex` on an input is the sort of thing that renders
   correctly in one engine and collapses in another. */
input[type="submit"],
.adminform_savebutton input {
	display: inline-block;
	text-align: center;
}

/* 9.3 Action rows align right on every route.
   The old rule was scoped to one exact ancestor chain, so the button landed at four different
   right edges depending on which container the module happened to use. */
.adminbuttons {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 8px;
	margin-top: 0;
}

.adminbuttons > .ab-button:last-child,
.adminbuttons > a.ab-button:last-child,
.adminbuttons > input[type="submit"]:last-child {
	margin-right: 0;
}

/* 9.4 One text field. The list search was a 34px borderless grey pill on five routes and a
   45px white bordered box on the rest. Standardised on .form-control's values, which already
   cover every form in the app and whose 8px radius matches the button. */
.form-control,
.extended-buttons .field-search input.form-search,
input[type="text"].form-search,
textarea.form-control,
select.form-control {
	min-height: 45px;
	padding: 5px 12px;
	border: 1px solid #E5E5E5;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: 14px;
	color: var(--ink-2);
	box-shadow: none;
}

.form-control[disabled],
.form-control[readonly],
fieldset[disabled] .form-control {
	background-color: #F3F5F8;
	color: #5A6A80;
	opacity: 1;
	cursor: not-allowed;
}

/* A 16%-alpha orange halo on an off-white page is not a focus indicator -- see section 35.4.
   The border still darkens, but the ring comes from :focus-visible and is not suppressed here:
   `.extended-buttons .field-search input.form-search:focus` is (0,3,1) and would win. */
.form-control:focus,
.extended-buttons .field-search input.form-search:focus {
	border-color: var(--ink);
	box-shadow: none;
}

/* 9.5 One container. The same list markup rendered as a white card on one route and as bare
   text on another, because four different class names were used for the same idea. */
.block-content-outer > .card,
.block-content-outer > .box,
.block-content-outer > .panel,
.block-content-outer > .table-wrapper {
	background: #FFFFFF;
	border: 1px solid #E4E4E4;
	border-radius: 8px;
	box-shadow: none;
	padding: 16px;
}

/* 9.6 An empty state, which the product did not have -- only four accidents. The most common
   was a bare <td colspan> that made "Nothing found" look like an ordinary data row. */
/* `display: block` applies to the DIV forms only. On a <td> it drops the cell out of table
   layout, so it shrinks to the first column's track and `text-align: center` then centres
   within THAT -- which is why the Files empty state sat under the FILE column instead of across
   the table, despite carrying a correct colspan. */
.empty-state,
.nothing-found {
	display: block;
}
.empty-state,
.nothing-found,
td.is-empty,
tbody tr.is-empty td {
	text-align: center;
	padding: 40px 14px;
	color: #6B7280;
	font-size: 14px;
	font-weight: 400;
	background: #FFFFFF;
}

/* =========================================================================================
   10. MOBILE, CONTINUED

   A CORRECTION TO HOW THIS WAS VERIFIED THE FIRST TIME.

   Earlier the shell was declared mobile-ready on the strength of
   `document.documentElement.scrollWidth - clientWidth === 0` at 390px. That metric reads 0 on
   every route in this app -- including routes that are visibly amputated -- because
   `section.content` is `overflow-x: hidden`. Content wider than the column is CLIPPED, not
   overflowed, so the document never grows and the measurement can never see it. Eleven routes
   were losing content off the right edge the whole time.

   The correct measure is per-element: how far past the column's right edge does any descendant
   extend. Measured that way: organizations 2315px clipped, settings 1458px, dashboard 448px,
   conversation 561px in both directions.
   ========================================================================================= */
@media (max-width: 767px) {

	/* 10.1 Let the column scroll rather than amputate. On its own this is not enough -- it
	   turns clipping into a very wide scroller -- so it is paired with the stacking rules
	   below, which remove the width instead of just exposing it. */
	section.content {
		overflow-x: auto !important;
	}

	/* 10.2 Nothing may impose a width larger than the column. This one rule is what lets the
	   stacking below actually take effect: the wrappers were shrink-wrapping their content and
	   the min-width was propagating up an ancestor chain. */
	.block,
	.block-content-inner,
	.block-content-outer,
	.block-content-outer > div,
	.table-responsive,
	.tablewrapper {
		min-width: 0 !important;
		max-width: 100% !important;
	}

	/* 10.3 Two-column master/detail layouts stack. `settings` and `knowledgebase` kept a
	   category rail beside a detail pane that ran to x=1848 on a 390px screen. */
	.block-content-outer > div[style*="flex"] {
		display: block !important;
	}

	/* 10.4 Toolbars wrap instead of running off. Measured 784-2315px wide on five routes. */
	.additional-buttons-section > *,
	.extended-buttons > * {
		min-width: 0 !important;
		max-width: 100% !important;
	}

	.additional-buttons-section .flex,
	.additional-buttons-section .buttons,
	.adminbuttons {
		flex-wrap: wrap !important;
		justify-content: flex-start !important;
		gap: 8px;
	}

	/* 10.5 Dashboard and stats wrappers are blocks, not shrink-to-fit rows. */
	.dashboard_home .memberstats .campaignsstats .stats,
	.memberstats .campaignsstats .row .stats,
	.dash-nav-row,
	.daylistats,
	.rd-dash-conversation,
	.incoming_call {
		display: block !important;
	}

	.boxwrapper,
	.status-stats {
		min-width: 0 !important;
		max-width: 100% !important;
	}

	/* 10.6 The Inbox was the worst route in the app -- a centred shrink-to-fit three-pane table
	   that overflowed in BOTH directions. The panes become full-width blocks. */
	.rd-status-sidebar,
	.rd-dash-sidebar,
	.rd-dash-conversation,
	.rd-dash-conversation-view {
		display: block !important;
		width: 100% !important;
		min-width: 0 !important;
	}

	/* 10.7 The incoming-call modal is global chrome and was 81px wider than the viewport on
	   every route. */
	#callsmodal .incoming_call,
	.incoming_call .buttons {
		flex-wrap: wrap !important;
		max-width: 100% !important;
	}

	.incoming_call .buttons > div {
		min-width: 0 !important;
	}

	/* 10.8 Touch targets. The sidebar rail toggle measured 17x36 -- half the 32px floor -- and
	   the breadcrumb links were 20px tall. The desktop toggle is redundant on a phone, where
	   the sidebar is already an off-canvas drawer. */
	.left-nav-toggle.hide-toggle-side {
		display: none;
	}

	.identity-crumbs a,
	.tab-nav a,
	.brand-switcher-toggle,
	.ws-switcher-toggle {
		min-height: 32px;
		display: inline-flex;
		align-items: center;
	}

	/* 10.10 The Inbox's outer box is a flex row that never wraps, so its panes kept it 813px
	   wide however narrow the viewport got. `.rd-dash-customer-info` additionally carries a
	   hard `min-width: 250px`, which propagated up the chain. */
	.block-content-outer {
		flex-wrap: wrap !important;
	}

	.rd-dash-customer-info,
	.rd-dash-customer-info > .flex {
		min-width: 0 !important;
		max-width: 100% !important;
	}

	/* 10.11 A flex action row that collapses to width 0 lets its buttons escape sideways --
	   measured on contentdashboard, where `.adminbuttons` was 0px wide around a 145px button.
	   Giving the row the full column width makes wrapping possible at all. */
	.adminbuttons {
		width: 100%;
		min-width: 0;
	}

	.ab-button {
		max-width: 100%;
		white-space: normal;
	}

	/* 10.12 The message status strip in the Inbox is a nowrap row of pills. */
	.message-status-wrapper,
	.message-status-wrapper > * {
		flex-wrap: wrap !important;
		min-width: 0 !important;
		max-width: 100% !important;
	}

	/* 10.13 Last two nowrap rows: the Inbox's timestamp column and the platform stats row. */
	.rd-dash-conversation-time,
	.statsrow,
	.statsrow > * {
		flex-wrap: wrap !important;
		min-width: 0 !important;
		max-width: 100% !important;
		white-space: normal !important;
	}

	/* KNOWN RESIDUAL, deliberately not chased further:
	   `.status-dropdown-menu` on the Inbox (79px) and `.ldBar` on platformstats (11px) still
	   widen the column. Both size from their content rather than their box -- one is
	   display:table, the other a canvas-backed progress widget -- so max-width does not
	   constrain them; that was tried and verified ineffective, and the rule removed rather than
	   left in as dead CSS. Neither loses content: section.content scrolls (10.1), so both are
	   reachable. Fixing them properly means changing the widgets, not the stylesheet. */

	/* 10.9 Nothing below 12px. The brand avatar rendered at 10px and the whole switcher menu
	   sat between 9 and 11px. */
	.brand-initials,
	.brand-initials.small,
	.identity-crumbs .crumb-kind,
	.switcher-group-label,
	.switcher-ws-hint,
	.tab-nav .secondary-nav > li.tabnav-label {
		font-size: 12px !important;
	}
}

/* =========================================================================================
   11. USERS: the permission grid, and the form and list around it.

   The old form was a single unbroken stack of full-width inputs with no grouping, so a person
   creating a user had to read all of it to find anything. It is grouped and two-column here,
   and the permission grid is the one part deliberately given room -- it is the part that
   actually decides what the new person can do.
   ========================================================================================= */

/* ---- form ---- */
.usersmgmt .adminform_field,
body[class*="usersmgmt"] .adminform_field {
	margin-bottom: 14px;
}

.perm-grid {
	margin: 22px 0 6px;
	border: 1px solid #E4E4E4;
	border-radius: 10px;
	background: #FFFFFF;
	overflow: hidden;
}

.perm-head {
	padding: 15px 18px;
	border-bottom: 1px solid #E4E4E4;
	background: #F7F8FA;
}

.perm-title {
	font-size: 15px;
	font-weight: 700;
	color: #101A2B;
	letter-spacing: -.01em;
}

.perm-note {
	font-size: var(--fs-sm);
	color: #5E6877;
	margin-top: 3px;
	line-height: 1.45;
}

.perm-group + .perm-group { border-top: 1px solid #EEF1F4; }

.perm-group-name {
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: #8A97A8;
	padding: 13px 18px 5px;
}

.perm-row {
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 8px 18px 10px;
	flex-wrap: wrap;
}

.perm-mod {
	flex: 0 0 170px;
	font-size: var(--fs-md);
	font-weight: 600;
	color: #1F2937;
}

.perm-soon {
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #96601A;
	background: #FBF0DC;
	border: 1px solid #E8D3A8;
	border-radius: 99px;
	padding: 1px 6px;
	margin-left: 5px;
	vertical-align: middle;
}

.perm-actions { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; min-width: 0; }

.perm-chk {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 11px;
	border: 1px solid #DFE3E8;
	border-radius: 99px;
	font-size: var(--fs-sm);
	font-weight: 500;
	color: #4A5568;
	cursor: pointer;
	user-select: none;
	background: #FFFFFF;
	margin: 0;
	transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}

.perm-chk input { margin: 0; cursor: pointer; }

.perm-chk:hover { border-color: #B9C2CF; }

/* Checked reads as filled, so a scan of the grid shows what this person can do without
   reading a single label. :has() degrades to the plain state on browsers without it. */
.perm-chk:has(input:checked) {
	background: #FEEDE9;
	border-color: #F0A48F;
	color: #C2410C;
	font-weight: 600;
}

/* Something the CREATOR cannot grant. Shown disabled rather than hidden so the grid has the
   same shape for everyone -- a grid that silently loses rows leaves people wondering whether
   the permission exists at all. */
.perm-chk.is-locked {
	opacity: .45;
	cursor: not-allowed;
	background: #F5F6F8;
	border-style: dashed;
}

.perm-chk.is-locked input { cursor: not-allowed; }

@media (max-width: 767px) {
	.perm-mod { flex: 0 0 100%; }
	.perm-row { padding: 8px 14px 12px; }
	.perm-chk { font-size: 12px; padding: 6px 10px; }
}

/* =========================================================================================
   12. DEALS

   The list and the board reuse the .board / .col / .card rules already defined in section 6
   for the dashboard mock -- one board component, two places, rather than a second set that
   drifts.
   ========================================================================================= */

/* ---- list ---- */
.deal-list-wrap {
	background: #FFFFFF;
	border: 0;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	overflow: hidden;
}

.deal-list { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }

.deal-list th {
	text-align: left;
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: #7C8AA0;
	padding: 11px 16px;
	background: #F7F8FA;
	border-bottom: 1px solid #E4E4E4;
	white-space: nowrap;
}

.deal-list td { padding: 13px 16px; border-bottom: 1px solid #EEF1F4; color: #47566A; }
.deal-list tr:last-child td { border-bottom: 0; }
.deal-list td.nm { color: #101A2B; font-weight: 600; }
.deal-list tbody tr { cursor: pointer; transition: background-color .1s ease; }
.deal-list tbody tr:hover { background: #FAFBFC; }
.deal-list td.is-empty { text-align: center; padding: 44px 16px; color: #7C8AA0; cursor: default; }
.deal-list tbody tr:has(td.is-empty):hover { background: #FFFFFF; }
.deal-list .num-cell { font-variant-numeric: tabular-nums; }

/* ---- deal header ---- */
.deal-head { margin-bottom: 18px; }
.deal-kind {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: #B93A19;
	margin-bottom: 4px;
}
.deal-name { font-size: 22px; font-weight: 700; letter-spacing: -.02em; margin: 0 0 5px; color: #101A2B; }
.deal-meta { font-size: 13px; color: #5E6877; }

/* ---- the two-column picker on the new-deal form ---- */
.deal-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 18px 0 6px; }

.deal-pick-col {
	border: 1px solid #E4E4E4;
	border-radius: 10px;
	background: #FFFFFF;
	overflow: hidden;
	max-height: 340px;
	overflow-y: auto;
}

.deal-pick-head {
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: #7C8AA0;
	padding: 11px 15px;
	background: #F7F8FA;
	border-bottom: 1px solid #E4E4E4;
	position: sticky;
	top: 0;
}

.deal-pick-row {
	display: flex;
	align-items: center;
	gap: 9px;
	padding: 9px 15px;
	border-bottom: 1px solid #EEF1F4;
	font-size: 13px;
	cursor: pointer;
	margin: 0;
}

.deal-pick-row:last-child { border-bottom: 0; }
.deal-pick-row:hover { background: #FAFBFC; }
.deal-pick-row input { margin: 0; }
.deal-pick-row .dp-name { font-weight: 600; color: #1F2937; }
.deal-pick-row .dp-sub { color: #7C8AA0; font-size: 12px; }

/* A contact visible only because an Admin linked their company. Marked, because picking one
   is a cross-company act and the person doing it should know. */
.deal-pick-row .dp-linked {
	margin-left: auto;
	font-size: 9px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #186B4E;
	background: #E4F2EC;
	border: 1px solid #A9D3C1;
	border-radius: 99px;
	padding: 1px 7px;
}

.deal-pick-empty { padding: 24px 15px; text-align: center; color: #7C8AA0; font-size: var(--fs-sm); font-style: italic; }

@media (max-width: 767px) {
	.deal-pick { grid-template-columns: 1fr; }
	.deal-list th:nth-child(3), .deal-list td:nth-child(3),
	.deal-list th:nth-child(5), .deal-list td:nth-child(5) { display: none; }
}

/* ---- deal board: drag affordances ---- */
.deal-board .card { cursor: grab; transition: opacity .12s ease, box-shadow .12s ease; }
.deal-board .card:active { cursor: grabbing; }
.deal-board .card.is-dragging { opacity: .4; }

.deal-board .col.is-over {
	outline: 2px dashed #F0A48F;
	outline-offset: -3px;
	background: #FEEDE9;
}

/* A refused move snaps back. Without a signal the card would silently reappear where it
   started and read as a bug rather than a denial. */
@keyframes deal-move-failed {
	0%, 100% { box-shadow: 0 0 0 0 rgba(166,54,54,0); }
	30%      { box-shadow: 0 0 0 3px rgba(166,54,54,.35); }
}
.deal-board .card.move-failed { animation: deal-move-failed .6s ease 2; }

@media (prefers-reduced-motion: reduce) {
	.deal-board .card.move-failed { animation: none; outline: 2px solid #A63636; }
}

/* ---- company links ---- */
.link-arrow { color: #B9C2CF; text-align: center; font-size: 16px; width: 30px; }
.deal-list .kindchip.is-full { color: #186B4E; border-color: #A9D3C1; background: #E4F2EC; }
.link-hint { font-size: var(--fs-sm); color: #5E6877; margin-top: 14px; max-width: 74ch; line-height: 1.55; }
.link-hint strong { color: #101A2B; font-weight: 600; }

/* ---- brand access block on the user form ---- */
.brand-access {
	margin: 22px 0 6px;
	border: 1px solid #E4E4E4;
	border-radius: 10px;
	background: #FFFFFF;
	overflow: hidden;
}

.ba-modes { padding: 14px 18px 4px; display: flex; flex-direction: column; gap: 8px; }

.ba-mode {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 10px 13px;
	border: 1px solid #DFE3E8;
	border-radius: 8px;
	font-size: var(--fs-md);
	color: #47566A;
	cursor: pointer;
	margin: 0;
	transition: background-color .12s ease, border-color .12s ease;
}

.ba-mode:hover { border-color: #B9C2CF; }
.ba-mode input { margin: 0; }

.ba-mode.is-on,
.ba-mode:has(input:checked) {
	background: #FEEDE9;
	border-color: #F0A48F;
	color: #C2410C;
	font-weight: 600;
}

.ba-brands { border-top: 1px solid #EEF1F4; margin-top: 10px; max-height: 240px; overflow-y: auto; }

.ba-brands-head {
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: #7C8AA0;
	padding: 12px 18px 8px;
}

/* The brand list only means anything in `list` mode. Dimmed rather than hidden so the control
   does not appear and disappear as the radio changes -- a panel that vanishes reads as a bug. */
.brand-access:has(input[value="home"]:checked) .ba-brands,
.brand-access:has(input[value="all_in_workspace"]:checked) .ba-brands {
	opacity: .4;
	pointer-events: none;
}

/* =========================================================================================
   13. THE KANBAN BOARD

   These rules did not exist. Section 12's comment claimed the board "reuses the .board / .col /
   .card rules already defined in section 6" -- it does not: section 6 styles the DASHBOARD stat
   cards (.daylistats), and .board/.col/.card only ever existed in the client-facing artifact,
   which is a separate document. The deal board therefore rendered as a plain run of unstyled
   text: "Cold Outreach0 - No Response1 Buffy Gentry ...". Written properly here.
   ========================================================================================= */

.boardwrap {
	overflow-x: auto;
	padding-bottom: 8px;
	-webkit-overflow-scrolling: touch;
}

.board {
	display: flex;
	gap: 12px;
	min-width: min-content;
	align-items: flex-start;
}

.board .col {
	flex: 0 0 244px;
	width: 244px;
	background: #F2F4F7;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 12px;
	min-height: 130px;
}

.board .col .chead {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: #5E6877;
	margin-bottom: 11px;
	padding-bottom: 9px;
	border-bottom: 1px solid #E4E7EC;
}

/* The count sits in a pill so a column with 12 cards reads at a glance. */
.board .col .chead span:last-child {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 99px;
	padding: 1px 8px;
	font-size: 10px;
	color: #47566A;
	font-variant-numeric: tabular-nums;
	flex: none;
}

.board .col.first { background: #FEF3F0; border-color: #F5CBBD; }
.board .col.first .chead { color: #B93A19; border-bottom-color: #F5CBBD; }
.board .col.won   { background: #E9F5F0; border-color: #A9D3C1; }
.board .col.won .chead { color: #186B4E; border-bottom-color: #A9D3C1; }
.board .col.lost  { background: #FBEDED; border-color: #E5B9B9; }
.board .col.lost .chead { color: #A63636; border-bottom-color: #E5B9B9; }

.board .card {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 8px;
	padding: 11px 13px;
	margin-bottom: 8px;
	box-shadow: 0 1px 2px rgba(16,26,43,.05);
}

.board .card:last-child { margin-bottom: 0; }
.board .card .cname { font-size: var(--fs-md); font-weight: 600; color: #101A2B; line-height: 1.3; }
.board .card .crole { font-size: var(--fs-xs); color: #7C8AA0; margin-top: 3px; }

.board .col .empty {
	font-size: 12px;
	color: #98A2B3;
	font-style: italic;
	padding: 10px 2px;
	text-align: center;
}

@media (max-width: 767px) {
	.board .col { flex: 0 0 200px; width: 200px; }
}

/* ==========================================================================================
   14. DEAL EDIT AND DELETE
   The surfaces that came with deal CRUD: the action pair on the board header, the row actions
   on the list, and the confirmation panel. Destructive actions are deliberately NOT painted in
   the brand orange -- that colour already means "the primary thing to do here" on every other
   screen (.ab-button.primary), and reusing it for Delete would make the dangerous action look
   like the recommended one.
   ========================================================================================== */

.deal-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
}
.deal-head-main { min-width: 0; }
.deal-head-actions { display: flex; gap: 8px; flex-shrink: 0; }
/* The deal header used its own smaller button here. Removed: one scale, no per-screen sizes. */

/* danger / quiet-danger are defined once, with the button scale in section 9.2. */

.ab-button.danger {
	background: #B3261E;
	border-color: #17803D;
	color: #FFFFFF;
}
.ab-button.danger:hover { background: #A82818; border-color: #A82818; color: #FFFFFF; }

/* Row actions stay invisible until the row is hovered: six identical Edit/Delete pairs down a
   table are noise, and the row is already clickable, so they only need to appear once the
   pointer has committed to a row. Kept in the flow (opacity, not display) so the column does
   not change width as the pointer moves down the table.

   Shared with .ct-list (Contacts, Companies and User Management all render through it -- see
   §1 of ui-consistency-and-permission-coverage.md for why the shared hook is styled rather
   than each table) rather than restated per table. .us-list previously relied on this same
   selector list without being in it, so its row actions were unstyled text; adding it here is
   a fix, not just new coverage for Contacts. */
.deal-list td.row-actions,
.ct-list td.row-actions {
	text-align: right;
	white-space: nowrap;
	cursor: default;
	opacity: 0;
	transition: opacity .12s ease;
}
.deal-list tbody tr:hover td.row-actions,
.deal-list td.row-actions:focus-within,
.ct-list tbody tr:hover td.row-actions,
.ct-list td.row-actions:focus-within { opacity: 1; }
.deal-list td.row-actions a,
.ct-list td.row-actions a,
.deal-list td.row-actions button,
.ct-list td.row-actions button {
	display: inline-block;
	padding: 4px 10px;
	margin-left: 4px;
	border-radius: 6px;
	font-size: 12px;
	font-weight: 600;
	color: #47566A;
	text-decoration: none;
}
.ct-list td.row-actions form.ra-form {
	display: inline;
	margin: 0;
	padding: 0;
}
.ct-list td.row-actions button {
	border: 0;
	background: transparent;
	cursor: pointer;
	font-family: inherit;
	line-height: inherit;
}
.deal-list td.row-actions a:hover,
.ct-list td.row-actions a:hover,
.deal-list td.row-actions button:hover,
.ct-list td.row-actions button:hover { background: #F1F3F6; color: #101A2B; }
.deal-list td.row-actions a.ra-danger:hover,
.ct-list td.row-actions a.ra-danger:hover,
.deal-list td.row-actions button.ra-danger:hover,
.ct-list td.row-actions button.ra-danger:hover { background: #FDECEA; color: #B3261E; }

/* Touch has no hover, so on small screens the actions are simply always shown. */
@media (hover: none) {
	.deal-list td.row-actions,
	.ct-list td.row-actions { opacity: 1; }
}

.confirm-panel {
	max-width: 520px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 28px 30px;
}
.confirm-panel h2 {
	margin: 0 0 10px;
	font-size: 19px;
	line-height: 1.35;
	color: #101A2B;
}
.confirm-panel p { margin: 0 0 8px; font-size: var(--fs-md); color: #47566A; }
.confirm-panel .confirm-note {
	margin-top: 14px;
	padding: 11px 13px;
	background: #F6F8FA;
	border-radius: 8px;
	font-size: var(--fs-sm);
	color: #5A6A80;
}
.confirm-actions { display: flex; gap: 10px; margin-top: 22px; }

@media (max-width: 767px) {
	.deal-head { flex-direction: column; }
	.deal-head-actions { width: 100%; }
	.confirm-panel { padding: 20px 18px; }
	.confirm-actions { flex-direction: column; }
	.confirm-actions .ab-button { width: 100%; text-align: center; }
}

/* ==========================================================================================
   15. CONTACT DIRECTORY
   The searchable people list and the one-person view. Its job is to make MEMBERSHIP legible:
   a person can now belong to several companies and hold a different role at each, and the
   chips are how that reads at a glance without opening anyone.
   ========================================================================================== */

/* The search box and Add Contact are one row. `.ct-search` keeps its own flex layout for the
   input + property filters + Search button; `.ct-toolbar` is the row that also carries the
   primary action, pushed to the far edge. The margin moved up to the row so the two children
   cannot disagree about the gap below.

   align-items:flex-start, not center: when a brand defines enough property filters to wrap the
   search form onto a second line, centring would float the button down beside the filters. The
   matching min-height below keeps it level with the 42px input in the ordinary one-line case. */
.ct-toolbar {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	flex-wrap: wrap;
	margin-bottom: 16px;
}
.ct-toolbar > .ct-search {
	flex: 1 1 auto;
	margin-bottom: 0;
}
.ct-toolbar > .ct-add {
	flex: 0 0 auto;
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	min-height: 42px;
	white-space: nowrap;
}
.ct-search {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 16px;
}
.ct-search input[type="search"] {
	flex: 1 1 auto;
	max-width: 380px;
	min-height: 42px;
	padding: 8px 14px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	color: #101A2B;
}
.ct-search input[type="search"]:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.ct-clear { font-size: var(--fs-sm); color: #7C8AA0; text-decoration: none; }
.ct-clear:hover { color: #101A2B; }

.ct-list-wrap {
	background: #FFFFFF;
	border: 0;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	overflow: hidden;
	overflow-x: auto;
}
.ct-list { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
.ct-list th {
	padding: 12px 16px;
	background: #F7F9FB;
	border-bottom: 1px solid #E4E7EC;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
	text-align: left;
	white-space: nowrap;
}
.ct-list td { padding: 12px 16px; border-bottom: 1px solid #EEF1F4; color: #47566A; vertical-align: middle; }
.ct-list tr:last-child td { border-bottom: 0; }
.ct-list td.nm { color: #101A2B; font-weight: 600; white-space: nowrap; }
.ct-list td.num-cell { text-align: right; font-variant-numeric: tabular-nums; }
.ct-list tbody tr { cursor: pointer; transition: background-color .1s ease; }
.ct-list tbody tr:hover { background: #FAFBFC; }
.ct-list td.is-empty { text-align: center; padding: 44px 16px; color: #7C8AA0; cursor: default; }
.ct-list tbody tr:has(td.is-empty):hover { background: #FFFFFF; }

/* Directory totals and the counted pager (GS\Common\CursorPage::WithTotal). The summary above the
   list says how many records the brand holds; the pager below says where you are in them. Pages
   are keyset positions, so "page 900" costs one index read, not a 45,000-row OFFSET per click. */
.ct-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 16px;
	/* All companies lays its toolbar and grid out in a wrapping flex row; a full basis keeps the
	   line on its own row above the grid instead of beside Export / Add Company. */
	flex: 1 0 100%;
	width: 100%;
	margin: 0 0 12px;
	font-size: var(--fs-base);
	color: #6B7A90;
}
.ct-summary b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.ct-summary-match b { color: var(--accent-text); }

.ct-pager {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px 20px;
	margin-top: 16px;
	font-size: var(--fs-md);
	color: #6B7A90;
}
.ct-pager-count b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.ct-pager-asof { color: #9AA6B6; }
.ct-pager-nav,
.ct-pager-tools,
.ct-pager-size,
.ct-pager-jump { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ct-pager-tools { gap: 16px; }
.ct-pg {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 34px;
	height: 34px;
	padding: 0 10px;
	border: 1px solid var(--line);
	border-radius: 8px;
	background: #FFFFFF;
	color: #35435A;
	font-weight: 500;
	font-variant-numeric: tabular-nums;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
}
a.ct-pg:hover { background: #F1F3F6; color: var(--ink); border-color: var(--line-strong); text-decoration: none; }
a.ct-pg:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.ct-pg.is-current { background: var(--ink); border-color: var(--ink); color: #FFFFFF; font-weight: 600; cursor: default; }
.ct-pg.is-off { color: #B4BDC9; background: transparent; cursor: default; }
.ct-pg-gap { padding: 0 2px; color: #9AA6B6; }
.ct-pager-jump input[type="number"] {
	box-sizing: border-box;
	width: 72px;
	height: 34px;
	padding: 0 8px;
	border: 1px solid var(--line);
	border-radius: 8px;
	font: inherit;
	color: var(--ink);
	font-variant-numeric: tabular-nums;
}
.ct-pager-jump button.ct-pg { font: inherit; font-weight: 500; }
@media (max-width: 767px) {
	.ct-pager { justify-content: flex-start; }
	.ct-pager-nav .ct-pg-step { padding: 0 8px; }
}

/* The company chip carries the role as a second line rather than a separate column: the role
   is a property of THIS membership, and a column could only ever show one of them. */
.ct-chips { min-width: 200px; }
.ct-chip {
	display: inline-flex;
	flex-direction: column;
	padding: 3px 9px;
	margin: 2px 4px 2px 0;
	border: 1px solid #E4E7EC;
	border-radius: 6px;
	background: #F7F9FB;
	font-size: 12px;
	color: #35435A;
	line-height: 1.35;
}
.ct-chip i { font-style: normal; font-size: var(--fs-xs); color: #7C8AA0; }
.ct-none { color: #A8B3C2; }
.ct-capped { margin-top: 10px; font-size: 12px; color: #7C8AA0; }

/* --- one person --- */
.ct-detail { max-width: 780px; }
.ct-detail-head { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.ct-avatar {
	width: 46px;
	height: 46px;
	flex: 0 0 46px;
	border-radius: 50%;
	background: #FEEDE9;
	color: #17803D;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	font-weight: 600;
	letter-spacing: .02em;
}
.ct-name { margin: 0; font-size: 20px; line-height: 1.3; color: #101A2B; }
.ct-sub { font-size: 13px; color: #7C8AA0; margin-top: 2px; }

.ct-panel {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 18px 20px;
	margin-bottom: 16px;
}
.ct-panel-head {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #6B7A90;
	margin-bottom: 12px;
}
.ct-empty { font-size: 13px; color: #8B98AB; padding: 6px 0 2px; }

.ct-memberships, .ct-deals { list-style: none; margin: 0; padding: 0; }
.ct-memberships li, .ct-deals li {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	padding: 9px 0;
	border-bottom: 1px solid #F1F3F6;
	font-size: var(--fs-md);
}
.ct-memberships li:last-child, .ct-deals li:last-child { border-bottom: 0; }
.ct-org { font-weight: 600; color: #101A2B; }
.ct-role { color: #5A6A80; }
.ct-deals a { color: #101A2B; font-weight: 600; text-decoration: none; }
.ct-deals a:hover { color: #D9451F; }
.ct-stage { margin-left: auto; font-size: 12px; color: #7C8AA0; }

.ct-primary, .ct-legacy, .dp-linked {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	padding: 2px 7px;
	border-radius: 4px;
}
.ct-primary { background: #E8F3EC; color: #2C6B45; }
.ct-legacy  { background: #F1F3F6; color: #6B7A90; }

/* ------------------------------------------------------------------------------------------
   TICKET 1, AC3/AC4 -- per-membership controls.

   A membership row is now two lines: the statement (company, role, primary/secondary) and the
   controls that change it. Keeping the controls on their own line stops the badges reflowing
   as roles get longer, and makes the row readable when there are no controls at all (a viewer
   without contacts.edit sees only the statement).
   ------------------------------------------------------------------------------------------ */
.ct-secondary {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	padding: 2px 7px;
	border-radius: 4px;
	background: #F1F3F6;
	color: #8494A8;
}
.ct-memberships li.ct-membership { display: block; }
.ct-membership-main { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ct-membership-edit { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 7px; }
.ct-membership-edit form { display: flex; align-items: center; gap: 6px; margin: 0; }
.ct-roleinput {
	width: 190px;
	max-width: 100%;
	padding: 5px 8px;
	font-size: 12.5px;
	border: 1px solid #D7DCE3;
	border-radius: 6px;
}
.ct-makeprimary { white-space: nowrap; }

.ct-remove { margin-left: auto; font-size: 12px; color: #9A2A18; text-decoration: none; }
.ct-remove:hover { color: #B3261E; text-decoration: underline; }
/* Shown, not hidden. A control that vanishes reads as a missing feature; one that is visibly
   unavailable and says why reads as a rule. */
.ct-remove-off { margin-left: auto; font-size: 12px; color: #B8C1CE; cursor: not-allowed; }

/* The company list on the LEGACY contact record (customerdetails), where a person can now show
   more than one company and the role held at each. */
.customer-companies .cc-line {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 6px;
	margin-bottom: 4px;
}
.customer-companies .cc-org { color: #2F6BA8; text-decoration: none; }
.customer-companies .cc-org:hover { text-decoration: underline; }
.customer-companies .cc-role { font-size: 12px; color: #6B7A90; }
.cc-count {
	margin-left: 6px;
	font-size: 10.5px;
	padding: 1px 6px;
	border-radius: 999px;
	background: #F1F3F6;
	color: #6B7A90;
}
.cc-manage { display: inline-block; margin-top: 4px; font-size: 12px; color: #2F6BA8; text-decoration: none; }
.cc-manage:hover { text-decoration: underline; }

.ct-addform {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 14px;
	padding-top: 14px;
	border-top: 1px solid #F1F3F6;
}
.ct-addform select,
.ct-addform input[type="text"] {
	min-height: 38px;
	padding: 6px 11px;
	border: 1px solid #DDE2E9;
	border-radius: 7px;
	background: #FFFFFF;
	font-size: 13px;
	color: #101A2B;
}
.ct-addform select { min-width: 180px; }
.ct-addform input[type="text"] { flex: 1 1 160px; min-width: 140px; }
/* The add-company row used 38px. Removed for the same reason. */
.ct-primary-toggle {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-size: var(--fs-sm);
	color: #5A6A80;
	white-space: nowrap;
}

/* Brand segmentation — the sharing checklist and per-brand status (Ticket 7). */
.ct-hint { font-size: var(--fs-sm); color: #7C8AA0; margin: 0 0 12px; line-height: 1.5; }
.ct-brandform { display: block; }
.ct-brandopt {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 0;
	border-bottom: 1px solid #F1F3F6;
	font-size: var(--fs-md);
	color: #101A2B;
}
/* Was `.ct-brandform .ct-brandopt:last-of-type { border-bottom: 0 }` -- correct when the options
   were stacked rows and the last needed no divider under it. They are cards in a grid now, so
   that rule stripped the last card's bottom edge and left it looking unfinished. */
.ct-brandopt input[type="checkbox"] { width: 15px; height: 15px; }
.ct-brandopt i { font-style: normal; font-size: var(--fs-xs); color: #7C8AA0; text-transform: uppercase; letter-spacing: .04em; }
.ct-brandlink { display: block; text-decoration: none; color: inherit; }
.ct-brandlink:hover .ct-chip { border-color: #C6CEDA; }

@media (max-width: 767px) {
	.ct-search { flex-wrap: wrap; }
	.ct-search input[type="search"] { max-width: none; }
	.ct-addform select,
	.ct-addform input[type="text"],
	.ct-addform .ab-button { width: 100%; }
	.ct-stage { margin-left: 0; }
	.ct-remove { margin-left: 0; }
}

/* Companies directory. Shares .ct-list with the contact directory rather than restating it --
   they are the same table doing the same job, and a second copy would drift. */
.co-list td.nm { white-space: normal; min-width: 180px; }
.co-full {
	display: inline-block;
	margin-left: 5px;
	padding: 1px 6px;
	border-radius: 4px;
	background: var(--co-full-bg, #E8F3EC);
	color: #2C6B45;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .03em;
	text-transform: uppercase;
}

/* The "company on the contact record" row sits under the add-a-company row and must not read as
   a second Add form -- it edits one existing field. Given its own top rule and a label so the
   two are visibly different actions. */
.ct-mainform { border-top: 1px dashed #E4E7EC; }
.ct-mainlabel {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
	white-space: nowrap;
}

/* ==========================================================================================
   16. USERS LIST
   Shares .ct-list with the contact and company directories. Only what is specific to people
   is restated here: the role and status chips, and the brand-access column.
   ========================================================================================== */

.us-list td.nm { white-space: normal; line-height: 1.35; }
.us-login {
	display: block;
	margin-top: 1px;
	font-size: var(--fs-xs);
	font-weight: 400;
	color: #8B98AB;
}
/* Presence, moved out of its own column: a dot carries "online now" without spending a
   column heading on it, and the title attribute says which state it is for anyone who cannot
   distinguish the two colours. */
.us-dot {
	display: inline-block;
	width: 7px;
	height: 7px;
	margin-right: 7px;
	border-radius: 50%;
	background: #CBD3DD;
	vertical-align: 1px;
}
.us-dot.is-on { background: #35A06A; }

.us-role, .us-status {
	display: inline-block;
	padding: 2px 9px;
	border-radius: 11px;
	font-size: 11px;
	font-weight: 600;
	text-transform: capitalize;
	white-space: nowrap;
}
/* Role colour tracks how much the role can do, so the column can be read down rather than
   word by word. Anything unrecognised keeps the neutral base, which is the honest rendering
   for a role this stylesheet has never heard of. */
.us-role { background: #F1F3F6; color: #55637A; }
.us-role-admin   { background: #E7EEF8; color: #29527F; }
.us-role-manager { background: #E9F1EC; color: #2C6B45; }
.us-role-user    { background: #F1F3F6; color: #55637A; }
.us-role-superadmin { background: #FDF1E3; color: #8A5A18; }

.us-status { background: #F1F3F6; color: #55637A; }
.us-status-active   { background: #E8F3EC; color: #2C6B45; }
.us-status-disabled,
.us-status-inactive { background: #FDECEA; color: #9A2A18; }

.us-brands { color: #47566A; }
.us-allbrands { color: #29527F; font-weight: 600; }
.us-more { color: #8B98AB; font-size: var(--fs-xs); }
/* "none" is a real state and a dangerous one -- a user who can reach no brand sees an empty
   product and will report it as broken. It is coloured as a warning rather than left to read
   like a blank. */
.us-nobrands {
	padding: 1px 7px;
	border-radius: 4px;
	background: #FDECEA;
	color: #9A2A18;
	font-size: var(--fs-xs);
	font-weight: 600;
}

.us-list td.row-actions a { margin-left: 4px; }

@media (max-width: 767px) {
	.us-list td.row-actions { opacity: 1; }
}

/* ==========================================================================================
   17. CUSTOM PROPERTIES
   The settings screen where properties are defined, and the panels they produce on records.
   ========================================================================================== */

body.properties .third-row-wrap:not(:has(li)) {
	display: none;
}
body.properties .block-header .content-wrapper {
	padding-top: 16px;
	padding-bottom: 0;
}
body.properties .block-header h2 {
	margin: 0;
	line-height: 44px;
	font-size: 20px;
	font-weight: 600;
	color: #101A2B;
}
body.properties .block > .body-wrapper > .block-content-outer {
	padding-top: 58px;
}
body.properties .additional-buttons-section .ab-button.primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	box-sizing: border-box;
	min-height: 36px;
	padding: 7px 16px;
	line-height: 20px;
}
body.properties .additional-buttons-section .ab-button.primary svg {
	display: block;
	flex-shrink: 0;
	margin-right: 0; /* gap handles icon/label spacing; avoid gap+5px double space */
}

.pr-tabs { display: flex; gap: 4px; margin: 0 0 14px; border-bottom: 1px solid #E4E7EC; }
.pr-tab {
	padding: 9px 16px;
	font-size: 13px;
	font-weight: 600;
	color: #6B7A90;
	text-decoration: none;
	border-bottom: 2px solid transparent;
	margin-bottom: -1px;
}
.pr-tab:hover { color: #101A2B; }
.pr-tab.is-on { color: #17803D; border-bottom-color: #17803D; }

.pr-intro, .pr-foot { font-size: 13px; color: #7C8AA0; max-width: 70ch; }
.pr-intro { margin: 0 0 16px; }
.pr-foot { margin: 12px 0 0; }

.pr-core {
	border: 1px solid #E4E9F0;
	border-radius: 10px;
	padding: 16px 18px;
	margin: 0 0 20px;
	background: #fff;
}
.pr-core h4 { margin: 0 0 4px; font-size: 15px; color: #101A2B; }
.pr-core .pr-intro { margin-bottom: 12px; }
.pr-core-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
	gap: 8px 16px;
	margin: 0 0 14px;
}
.pr-core-opt { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #33415C; cursor: pointer; margin: 0; }
.pr-core-opt input { margin: 0; }
.pr-core-saved { margin-left: 12px; font-size: 13px; color: #17803D; font-weight: 600; }

.pr-list code {
	font-size: var(--fs-xs);
	padding: 1px 6px;
	border-radius: 4px;
	background: #F1F3F6;
	color: #55637A;
}
/* An archived property stays legible rather than being greyed into unreadability -- it is
   still a real definition holding real values, and someone is reading the row precisely to
   decide whether to restore it. */
.pr-list tr.is-archived td.nm { color: #6B7A90; }
.pr-req, .pr-arch {
	display: inline-block;
	margin-left: 7px;
	padding: 1px 6px;
	border-radius: 4px;
	font-size: 9.5px;
	font-weight: 700;
	letter-spacing: .05em;
	text-transform: uppercase;
	vertical-align: 1px;
}
.pr-req  { background: #FDECEA; color: #9A2A18; }
.pr-arch { background: #F1F3F6; color: #6B7A90; }
.pr-src {
	display: inline-block;
	margin-left: 6px;
	padding: 1px 7px;
	border-radius: var(--r-pill);
	font-size: var(--fs-xs);
	font-weight: 600;
	background: #FFF1EC;
	color: #B8431E;   /* HubSpot's orange, darkened to 4.9:1 on the tint */
}
.pr-list .pr-grouprow th {
	padding: 18px 12px 8px;
	background: var(--surface);
	border-bottom: 1px solid var(--line-strong);
	font-size: var(--fs-sm);
	font-weight: 700;
	letter-spacing: .03em;
	text-transform: uppercase;
	color: var(--ink-2);
}
.pr-list .pr-grouprow th span { margin-left: 6px; font-weight: 600; color: var(--text-soft); }

.pr-keynote {
	margin: 4px 0 0;
	padding: 11px 13px;
	background: #F6F8FA;
	border-radius: 8px;
	font-size: var(--fs-sm);
	color: #5A6A80;
}
.pr-keynote code { background: #FFFFFF; border: 1px solid #E4E7EC; padding: 1px 6px; border-radius: 4px; }
.pr-keynote span { display: block; margin-top: 5px; color: #7C8AA0; }

/* --- the panel on a record --- */
.pr-panel .pr-field { margin-bottom: 14px; }
.pr-panel .pr-field:last-child { margin-bottom: 0; }
.pr-panel label {
	display: block;
	margin-bottom: 5px;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: #35435A;
}
.pr-star { color: #17803D; font-style: normal; margin-left: 3px; }
.pr-panel input[type="text"],
.pr-panel input[type="number"],
.pr-panel input[type="date"],
.pr-panel input[type="datetime-local"],
.pr-panel input[type="url"],
.pr-panel input[type="email"],
.pr-panel select,
.pr-panel textarea {
	width: 100%;
	max-width: 420px;
	min-height: 38px;
	padding: 7px 11px;
	border: 1px solid #DDE2E9;
	border-radius: 7px;
	background: #FFFFFF;
	font-size: 13px;
	font-family: inherit;
	color: #101A2B;
}
.pr-panel textarea { min-height: 70px; resize: vertical; }
.pr-panel input:focus, .pr-panel select:focus, .pr-panel textarea:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.pr-check, .pr-multi label {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-weight: 400;
	font-size: 13px;
	color: #47566A;
	margin-bottom: 0;
}
.pr-multi { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.pr-help { display: block; margin-top: 4px; font-size: var(--fs-xs); color: #8B98AB; }
.pr-save { margin: -4px 0 16px; }

/* --- read-only rendering --- */
.pr-read { list-style: none; margin: 0; padding: 0; }
.pr-read li {
	display: flex;
	gap: 14px;
	padding: 7px 0;
	border-bottom: 1px solid #F1F3F6;
	font-size: var(--fs-md);
}
.pr-read li:last-child { border-bottom: 0; }
.pr-label { flex: 0 0 190px; color: #7C8AA0; }
.pr-value { color: #101A2B; overflow-wrap: anywhere; }
.pr-value a { color: var(--accent-text); }

/* --- sections: a panel with more than one property group (HubSpot import) ---
   One quiet row per section: name, a count, a one-line purpose. Closed sections cost one line,
   so a driver contact's ~70 values read as eight scannable headings rather than one long list.
   Fields sit in an auto-fill grid so wide screens use their width and phones get one column. */
.pr-sectioned .ct-panel-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	flex-wrap: wrap;
}
.pr-finder { margin: 0; font-weight: 400; }
.pr-finder input {
	width: 220px;
	max-width: 100%;
	min-height: 32px;
	padding: 5px 10px;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-md);
	font-size: var(--fs-md);
	background: var(--surface-sunk);
	color: var(--ink);
}
.pr-finder input:focus { outline: none; border-color: var(--ink-2); background: var(--surface); }
.pr-group { border-top: 1px solid var(--line); }
.pr-group:first-of-type { border-top: 0; }
.pr-group > summary {
	display: flex;
	align-items: baseline;
	gap: 10px;
	flex-wrap: wrap;
	padding: 11px 0;
	cursor: pointer;
	list-style: none;
}
.pr-group > summary::-webkit-details-marker { display: none; }
.pr-group > summary::before {
	content: '';
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	margin-right: 2px;
	border-right: 1.5px solid var(--text-soft);
	border-bottom: 1.5px solid var(--text-soft);
	transform: translateY(-2px) rotate(-45deg);
	transition: transform .15s ease;
}
.pr-group[open] > summary::before { transform: translateY(-4px) rotate(45deg); }
.pr-group > summary:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: var(--r-sm); }
.pr-group-name { font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.pr-group-count {
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .02em;
	padding: 2px 8px;
	border-radius: var(--r-pill);
	background: var(--surface-mute);
	color: var(--text-muted);
}
.pr-group-blurb { flex-basis: 100%; padding-left: 19px; font-size: var(--fs-sm); color: var(--text-soft); }
.pr-group-body { padding: 2px 0 16px 19px; }
.pr-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: 0 28px;
}
.pr-grid.pr-read li { border-bottom: 1px solid var(--surface-mute); }
.pr-grid .pr-field { margin-bottom: 14px; }
.pr-grid .pr-field:last-child { margin-bottom: 14px; }
.pr-grid .pr-label { flex-basis: 45%; }
.pr-panel [hidden] { display: none !important; }

/* --- where an imported record came from --- */
.hs-source { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px 28px; margin: 0; }
.hs-source dt { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--text-soft); }
.hs-source dd { margin: 3px 0 0; font-size: var(--fs-md); color: var(--ink); }
.hs-rule {
	display: inline-block;
	padding: 1px 8px;
	border-radius: var(--r-pill);
	font-size: var(--fs-xs);
	font-weight: 600;
	background: var(--success-tint);
	color: var(--success);
}
.hs-rule.is-fallback { background: var(--warning-tint); color: var(--warning); }
.hs-links { list-style: none; margin: 14px 0 0; padding: 12px 0 0; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 8px; }
.hs-links li { padding: 5px 10px; border-radius: var(--r-md); background: var(--surface-alt); font-size: var(--fs-sm); color: var(--text); }
.hs-links b { color: var(--ink); font-variant-numeric: tabular-nums; }
.hs-note { margin: 12px 0 0; font-size: var(--fs-sm); color: var(--text-soft); }

@media (max-width: 767px) {
	.pr-tabs { overflow-x: auto; }
	.pr-read li { flex-direction: column; gap: 2px; }
	.pr-label { flex: none; }
	.pr-panel input, .pr-panel select, .pr-panel textarea { max-width: none; }
	.pr-group-body, .pr-group-blurb { padding-left: 0; }
	.pr-finder, .pr-finder input { width: 100%; }
}

/* A save failure on a legacy page that has no notification area of its own. */
.pr-flash {
	margin: 14px 0;
	padding: 11px 14px;
	border-radius: 8px;
	background: #FDECEA;
	border: 1px solid #F3C9C3;
	color: #9A2A18;
	font-size: 13px;
}

/* Property filters live in the search bar rather than behind an "advanced" modal: a filter
   nobody can see is a filter nobody uses, and there are only ever as many as the brand chose
   to define. They wrap onto a second line rather than shrinking the search box. */
.ct-search { flex-wrap: wrap; }
.ct-search select {
	min-height: 42px;
	padding: 8px 11px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: 13px;
	color: #101A2B;
	max-width: 220px;
}
.ct-search select:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}

@media (max-width: 767px) {
	.ct-search select { max-width: none; width: 100%; }
}

.ct-stale {
	margin: -6px 0 14px;
	padding: 9px 13px;
	border-radius: 8px;
	background: #FDF6E7;
	border: 1px solid #F0DFB8;
	color: #7A5A15;
	font-size: var(--fs-sm);
}

/* Property columns sit next to the record's own identifying columns, not at the far right past
   Email and Phone: they were promoted because someone decided they matter, and a column you
   have to scroll to has not been promoted at all. */
.ct-list td.pr-cell { white-space: nowrap; }
.pr-col {
	display: inline-block;
	margin-left: 7px;
	padding: 1px 6px;
	border-radius: 4px;
	background: #E7EEF8;
	color: #29527F;
	font-size: 9.5px;
	font-weight: 700;
	letter-spacing: .05em;
	text-transform: uppercase;
}
.pr-col.is-over { background: #FDF6E7; color: #7A5A15; }

/* ==========================================================================================
   18. ACTIVITY
   Who did what. Shares .ct-list with the directories; only the chart, the bars and the
   caveat are specific to it.
   ========================================================================================== */

.ac-stats { display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 14px; }
.ac-stat {
	flex: 1 1 140px;
	padding: 14px 16px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
}
.ac-stat b {
	display: block;
	font-size: 24px;
	font-weight: 600;
	line-height: 1.1;
	color: #101A2B;
	font-variant-numeric: tabular-nums;
}
.ac-stat span {
	display: block;
	margin-top: 3px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #7C8AA0;
}

.ac-spark {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 14px 16px 10px;
	margin-bottom: 16px;
}
.ac-spark svg { display: block; width: 100%; height: 90px; }
.ac-sb { fill: #17803D; }
/* A zero day keeps a visible foot so the axis reads as a timeline rather than as a gap. */
.ac-sb.is-zero { fill: #E4E7EC; }
.ac-axis {
	display: flex;
	justify-content: space-between;
	margin-top: 7px;
	font-size: 11px;
	color: #8B98AB;
	font-variant-numeric: tabular-nums;
}

.ac-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.ac-head h2 { margin: 0; font-size: 19px; color: #101A2B; }
.ac-head span { font-size: 13px; color: #7C8AA0; }

.ac-list td.num-cell { white-space: nowrap; }
.ac-barcell { width: 34%; min-width: 110px; }
.ac-bar {
	display: block;
	height: 8px;
	border-radius: 4px;
	background: #F7A98F;
	min-width: 3px;
}
.ac-imp {
	display: inline-block;
	margin-left: 6px;
	padding: 1px 6px;
	border-radius: 4px;
	background: #FDF1E3;
	color: #8A5A18;
	font-size: 9.5px;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
}
.ac-fields code {
	display: inline-block;
	margin: 1px 3px 1px 0;
	padding: 1px 6px;
	border-radius: 4px;
	background: #F1F3F6;
	color: #55637A;
	font-size: var(--fs-xs);
}

.ac-types { list-style: none; margin: 0; padding: 0; }
.ac-types li { display: flex; align-items: center; gap: 12px; padding: 7px 0; font-size: 13px; }
.ac-tname { flex: 0 0 190px; color: #35435A; }
.ac-tn { color: #7C8AA0; font-variant-numeric: tabular-nums; min-width: 46px; text-align: right; }

.ac-caveat { margin-top: 14px; font-size: 12px; color: #8B98AB; max-width: 76ch; line-height: 1.6; }

@media (max-width: 767px) {
	.ac-barcell { display: none; }
	.ac-tname { flex: 1 1 auto; }
}

/* ==========================================================================================
   19. THE LEGACY GRID AND FORM, RESTYLED IN PLACE
   ------------------------------------------------------------------------------------------
   The brief was "make every listing look like the Users list, and lose no filter". There are
   68 modules rendering 155 grids, and `support.php` alone carries 378 filter references —
   rewriting them is 33 chances to break a filter the week of a client demo.

   They do not need rewriting. Every one of them renders through the same two components, so
   they emit the same markup:

       lists  <div class="tablewrapper"> <table class="admintable table table-striped ...">
       forms  <form class="adminform_form"> <div class="adminform_table"> <div class="form-group">

   Styling those two hooks reskins the entire application with ZERO PHP changed, which means
   zero risk to any filter, sort, pager or bulk action. It is also more complete than converting
   a shortlist would have been: screens nobody remembered are covered too.

   Deliberately matched to .ct-list rather than merged with it. The two share a look, not a
   stylesheet — .ct-list is written against markup we control and can keep tightening, while
   this has to survive whatever the legacy components emit.
   ========================================================================================== */

/* NO BORDER. The theme carries `.table-responsive { border-color: #484c5a !important }` in
   styles/style.css -- a dark slate that was invisible only because the element had no border
   WIDTH. Giving these wrappers `1px solid` made that colour visible, and no amount of setting
   `border-color` here can win against an `!important`.
   The white surface on the page's grey ground already reads as a card, so the border was doing
   nothing the background was not; a hairline shadow gives it an edge without inviting the
   argument back. */
.tablewrapper,
.table-responsive {
	background: #FFFFFF;
	border: 0;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	overflow: hidden;
	overflow-x: auto;
}
/* Nested wrappers are common in the older modules; only the outer one should draw a box. */
.tablewrapper .tablewrapper,
.tablewrapper .table-responsive,
.table-responsive .tablewrapper {
	border: 0;
	border-radius: 0;
	background: transparent;
}

table.admintable {
	width: 100%;
	margin: 0;
	border-collapse: collapse;
	font-size: var(--fs-md);
	background: #FFFFFF;
}
table.admintable > thead > tr > th,
table.admintable th {
	padding: 12px 16px;
	background: #F7F9FB;
	border-bottom: 1px solid #E4E7EC;
	border-top: 0;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
	text-align: left;
	white-space: nowrap;
	vertical-align: middle;
}
table.admintable > tbody > tr > td,
table.admintable td {
	padding: 12px 16px;
	border-top: 0;
	border-bottom: 1px solid #EEF1F4;
	color: #47566A;
	vertical-align: middle;
}
table.admintable > tbody > tr:last-child > td { border-bottom: 0; }

/* Bootstrap's zebra striping is switched off rather than restyled. Striping and a hover state
   fight each other -- on a striped row the hover is invisible on every second line -- and the
   hover is the one that tells you which row you are about to click. */
table.admintable.table-striped > tbody > tr:nth-of-type(odd),
table.admintable.table-striped > tbody > tr:nth-of-type(even) { background: transparent; }
table.admintable > tbody > tr { transition: background-color .1s ease; }
table.admintable.table-hover > tbody > tr:hover,
table.admintable > tbody > tr:hover { background: #FAFBFC; }

/* The first cell is the row's identity in every one of these grids. */
table.admintable > tbody > tr > td:first-child { color: #101A2B; font-weight: 500; }
table.admintable a { color: #101A2B; text-decoration: none; }
table.admintable a:hover { color: #D9451F; text-decoration: none; }

/* Numeric-looking columns line up. */
table.admintable td[class*="count"],
table.admintable td[class*="total"],
table.admintable td[class*="amount"],
table.admintable td[class*="price"] { font-variant-numeric: tabular-nums; }

/* The action column: the legacy grids emit .action_links with inline SVG buttons. */
table.admintable .action_links {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 2px;
}
table.admintable .action_links a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	border-radius: 6px;
	color: #7C8AA0;
}
table.admintable .action_links a:hover { background: #F1F3F6; color: #101A2B; }
table.admintable .action_links svg { width: 17px; height: 17px; }

/* "Nothing found" is emitted as a single spanning cell. */
table.admintable td[colspan]:not([colspan="1"]) { text-align: center; color: #7C8AA0; padding: 34px 16px; }

/* Labels and chips the older grids scatter through cells. */
table.admintable .label {
	display: inline-block;
	padding: 2px 8px;
	border-radius: 11px;
	font-size: 11px;
	font-weight: 600;
	background: #F1F3F6;
	color: #55637A;
}
table.admintable .label-info    { background: #E7EEF8; color: #29527F; }
table.admintable .label-success { background: #E8F3EC; color: #2C6B45; }
table.admintable .label-warning { background: #FDF1E3; color: #8A5A18; }
table.admintable .label-danger  { background: #FDECEA; color: #9A2A18; }

/* ---------------------------------------------------------------------------------------
   THE FORM. Same reasoning: one component, one set of rules, every form in the app.
   --------------------------------------------------------------------------------------- */

.adminform_form .adminform_table {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 22px 24px;
	max-width: 720px;
}
.adminform_form .form-group {
	display: grid;
	grid-template-columns: 210px minmax(0, 1fr);
	gap: 14px 18px;
	align-items: start;
	padding: 12px 0;
	margin: 0;
	border-bottom: 1px solid #F4F6F8;
}
.adminform_form .form-group:last-of-type { border-bottom: 0; }
.adminform_form .form-group > div:first-child { padding-top: 9px; }
.adminform_form .form-group label {
	margin: 0;
	font-size: 13px;
	font-weight: 600;
	color: #35435A;
	line-height: 1.4;
}
.adminform-required { color: #17803D; margin-left: 2px; }

.adminform_form input[type="text"],
.adminform_form input[type="password"],
.adminform_form input[type="email"],
.adminform_form input[type="number"],
.adminform_form input[type="date"],
.adminform_form input[type="tel"],
.adminform_form input[type="url"],
.adminform_form select,
.adminform_form textarea {
	width: 100%;
	min-height: 40px;
	padding: 8px 12px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	font-family: inherit;
	color: #101A2B;
	box-shadow: none;
}
.adminform_form textarea { min-height: 90px; resize: vertical; }
.adminform_form input:focus,
.adminform_form select:focus,
.adminform_form textarea:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.adminform_form input[type="file"] { font-size: 13px; color: #5A6A80; }
.adminform_form input[type="checkbox"],
.adminform_form input[type="radio"] { margin-right: 6px; vertical-align: -1px; }

.adminform_form .adminform_savebutton {
	max-width: 720px;
	margin-top: 16px;
	display: flex;
	gap: 10px;
}

body.companiesmgmt #admintablerow-cellphone_for_notifications {
	grid-column: 1 / -1;
	display: block;
	height: auto;
	overflow: visible;
}
body.companiesmgmt #admintablerow-cellphone_for_notifications > div:first-child {
	min-height: 0;
	padding-top: 0;
	display: block;
	margin-bottom: 6px;
}
body.companiesmgmt #admintablerow-cellphone_for_notifications input[type="text"] {
	width: 100%;
	max-width: none;
}

/* A separator row is a section heading, not another field, so it leaves the two-column grid. */
.adminform_form .form-group.adminform_separator,
.adminform_form .adminform_separator {
	display: block;
	padding-top: 22px;
	border-bottom: 0;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #6B7A90;
}

@media (max-width: 900px) {
	.adminform_form .form-group { grid-template-columns: 1fr; gap: 6px; }
	.adminform_form .form-group > div:first-child { padding-top: 0; }
	.adminform_form .adminform_table { padding: 16px 14px; }
	table.admintable > thead > tr > th,
	table.admintable > tbody > tr > td { padding: 10px 12px; }
}

/* Per-route sheets override the grid cells with two-class selectors -- `.campaignlist .table td`
   is (0,2,1) and beats `table.admintable td` at (0,1,2), because class count is compared first.
   Every legacy grid carries BOTH `admintable` and `table` on the same element, so chaining them
   reaches (0,2,4) and settles it without `!important`, which would win here and then lose the
   next argument to whoever reaches for it after us. */
table.admintable.table > thead > tr > th,
table.admintable.table > tbody > tr > th {
	padding: 12px 16px;
	background: #F7F9FB;
	border-bottom: 1px solid #E4E7EC;
	border-top: 0;
}
table.admintable.table > tbody > tr > td,
table.admintable.table > tfoot > tr > td {
	padding: 12px 16px;
	border-top: 0;
	border-bottom: 1px solid #EEF1F4;
}
table.admintable.table > tbody > tr > td[colspan]:not([colspan="1"]) { padding: 34px 16px; }

/* ==========================================================================================
   20. DEAL BOARD TOOLBAR AND SPACING
   The toolbar was first built inside `.additional-buttons-section`, which carries its own
   layout rules -- they stacked the three controls vertically and threw the button onto a line
   of its own. It is now a single grid row that owns its widths.
   ========================================================================================== */

.deal-toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 10px;
	margin: 0 0 14px;
}
.deal-toolbar-form {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	flex: 1 1 auto;
	min-width: 0;
}
/* Explicit widths, and `flex: none` on the select: without it the select claimed the whole row
   and pushed the button to a second line, which is what the first version did. */
.deal-toolbar-form input[type="search"] {
	flex: 0 1 300px;
	min-width: 180px;
	min-height: 40px;
	padding: 8px 13px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	color: #101A2B;
}
/* The theme replaces every <select> with a `.nice-select` div at runtime, so styling the
   <select> itself does nothing visible -- the element sitting in the row is the wrapper, and it
   was 45px against 40px for everything beside it. Both are given the same height so the row is
   flush rather than nearly flush. */
.deal-toolbar-form .nice-select {
	flex: 0 0 190px;
	width: 190px;
	height: 40px;
	line-height: 38px;
	padding: 0 32px 0 13px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	color: #101A2B;
}
.deal-toolbar-form select {
	flex: 0 0 190px;
	width: 190px;
	height: 40px;
	min-height: 40px;
	padding: 8px 11px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	color: #101A2B;
}
.deal-toolbar-form input:focus,
.deal-toolbar-form select:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
/* The deal toolbar used 40px. Removed for the same reason. */
.deal-toolbar-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.deal-toolbar-actions .ab-button { white-space: nowrap; }

/* The header block, the properties panel and the board were each carrying their own bottom
   margin, which stacked into the large empty bands between them. */
body.deals .deal-head { margin-bottom: 14px; }
body.deals .ct-panel { margin-bottom: 14px; }
body.deals .total_values_info { margin-bottom: 8px; }
body.deals .draggable-wrapper { margin-top: 4px; }

/* Drop target feedback. The pipeline has none because its own drag library paints the
   placeholder; this board uses native drag and drop, so the column has to say it will accept. */
.leadcontainer.is-over { background: #FEF3EF; border-radius: 10px; }
.leadcontainer > div[id].is-dragging { opacity: .45; }
.leadcontainer > div[id] { cursor: grab; }
.leadcontainer > div[id]:active { cursor: grabbing; }

@media (max-width: 767px) {
	.deal-toolbar { flex-direction: column; align-items: stretch; }
	.deal-toolbar-form { flex-wrap: wrap; }
	.deal-toolbar-form input[type="search"],
	.deal-toolbar-form select { flex: 1 1 100%; width: 100%; }
	.deal-toolbar-actions .ab-button { flex: 1 1 auto; text-align: center; }
}

/* ==========================================================================================
   21. THE USER FORM — TWO COLUMNS, AVATAR PICKER, SELECT-ALL
   ------------------------------------------------------------------------------------------
   Scoped to `body.user_management_section`. The two-column layout is NOT applied to every form
   in the app: some of them carry very wide inputs, editors and inserted blocks that were laid
   out on the assumption of one column, and rearranging all of them the day before a demo is a
   large blast radius for a change nobody asked for. This is the form that was asked about.
   ========================================================================================== */

body.user_management_section .adminform_form .adminform_table {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 0 24px;
	max-width: none;
	align-items: start;
}
/* Section 19 caps the save row at 720px to sit under a 720px form. This form is not 720px
   wide, so its Save button would have stopped a long way short of the card's right edge. */
body.user_management_section .adminform_form .adminform_savebutton { max-width: none; }

/* Label above field, not beside it. At half width a 210px label column would leave the input
   too narrow to read a long email in. */
body.user_management_section .adminform_form .form-group {
	display: block;
	padding: 11px 0;
	border-bottom: 1px solid #F4F6F8;
}
body.user_management_section .adminform_form .form-group > div:first-child { padding-top: 0; }
body.user_management_section .adminform_form .form-group label { margin-bottom: 6px; }

/* The blocks that must not be squeezed into half a row. Targeted by the row ids the form
   generates from the names given in usersmgmt.php, so no :has() and no guessing. */
body.user_management_section #admintablerow-permgrid,
body.user_management_section #admintablerow-brandaccess,
body.user_management_section #admintablerow-userfile,
body.user_management_section .adminform_form .adminform_separator {
	grid-column: 1 / -1;
}
body.user_management_section #admintablerow-permgrid,
body.user_management_section #admintablerow-brandaccess { border-bottom: 0; }

/* --- avatar picker --- */
.avatar-picker { display: flex; align-items: center; gap: 16px; }
.avatar-input {
	/* Kept in the DOM and focusable-by-proxy rather than display:none — the picker clicks it,
	   and a removed input would take the file with it. */
	position: absolute;
	width: 1px; height: 1px;
	opacity: 0;
	pointer-events: none;
}
.avatar-drop {
	position: relative;
	width: 84px; height: 84px;
	flex: 0 0 84px;
	border: 2px dashed #DDE2E9;
	border-radius: 50%;
	background: #F7F9FB;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	overflow: hidden;
	transition: border-color .12s ease, background-color .12s ease;
}
.avatar-drop:hover,
.avatar-drop:focus-visible { border-color: #17803D; background: #FEF3EF; outline: none; }
.avatar-drop.is-over { border-color: #17803D; background: #FEEDE9; }
.avatar-img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.avatar-ph { font-size: 11px; font-weight: 600; color: #8B98AB; text-align: center; padding: 0 8px; }
.avatar-side { min-width: 0; }
.avatar-hint { font-size: 12px; color: #8B98AB; }
.avatar-name {
	margin-top: 4px;
	font-size: var(--fs-sm);
	color: #35435A;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	max-width: 260px;
}
.avatar-name.is-bad { color: #B3261E; font-weight: 600; }
.avatar-remove {
	margin-top: 6px;
	padding: 0;
	border: 0;
	background: none;
	font-size: 12px;
	font-weight: 600;
	color: #9A2A18;
	cursor: pointer;
}
.avatar-remove:hover { text-decoration: underline; }

/* --- select-all --- */
.perm-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; }
.perm-head .perm-title { flex: 0 0 auto; }
.perm-head .perm-note { flex: 1 1 240px; }
.perm-all {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	margin: 0;
	padding: 5px 11px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: #35435A;
	cursor: pointer;
	white-space: nowrap;
}
.perm-all:hover { border-color: #17803D; color: #17803D; }

.perm-modall {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	margin: 0;
	font-weight: 600;
	cursor: pointer;
}
.perm-modall input { flex: none; }
/* An indeterminate box is a third state and should not read as either of the other two. */
.perm-modall input:indeterminate { accent-color: #F0A28A; }

/* THREE PER ROW, FULL WIDTH.
   The cap is gone: the card fills its content column, so nothing on this screen is left as
   empty wash. Three tracks rather than four, because the form has exactly nine half-width
   fields -- First/Last/Password, Email/Cellphone/Twilio, Business User Role/Receive
   Notifications/Brand -- and nine divides into three clean rows. Four tracks would give 4+4+1
   and leave Brand stranded on a line of its own.

   This is the third answer to the same question and the first one that is right, because the
   two panels below changed underneath it. While Brand access and Module access were tall stacks
   of full-width rows (before section 35), widening the card only made those stacks wider and
   the form no shorter -- which is why the 1320px version was reverted. Now that both run in two
   columns of their own, the extra width is what those columns are made of.

   The full-width blocks (permissions grid, brand access, avatar, separators) already carry
   `grid-column: 1 / -1`, so they span whatever the track count happens to be and needed no
   change for any of this.

   Two steps down, not one, because three readable columns need roughly a 1250px viewport once
   the sidebar and gutters are taken out. */
@media (max-width: 1200px) {
	body.user_management_section .adminform_form .adminform_table {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}
@media (max-width: 900px) {
	body.user_management_section .adminform_form .adminform_table {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}
	.avatar-picker { flex-wrap: wrap; }
}

/* The add-to-column dialog. Rendered bare into the modal the page already carries. */
.dlg { padding: 4px 2px; }
.dlg-title { margin: 0 0 14px; font-size: 18px; line-height: 1.3; color: #101A2B; }
.dlg-list { max-height: 340px; overflow-y: auto; border: 1px solid #E4E7EC; border-radius: 10px; }
.dlg-row {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	padding: 10px 14px;
	border-bottom: 1px solid #F1F3F6;
	font-size: var(--fs-md);
	cursor: pointer;
}
.dlg-row:last-child { border-bottom: 0; }
.dlg-row:hover { background: #FAFBFC; }
.dlg-name { color: #101A2B; font-weight: 500; }
.dlg-sub { color: #8B98AB; font-size: 12px; }
.dlg-empty { padding: 22px 4px; color: #7C8AA0; font-size: var(--fs-md); }
.dlg-actions { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; }

/* The column-foot button: full width so it reads as the end of the stack rather than a stray
   control floating under the last card. */
.leadcontainer .showmoreleads { margin-top: 4px; }
.leadcontainer .showmoreleads .ab-button {
	display: block;
	width: 100%;
	text-align: center;
	border-style: dashed;
	color: #6B7A90;
}
.leadcontainer .showmoreleads .ab-button:hover { color: #17803D; border-style: solid; }

.dlg-kind { margin: -8px 0 16px; font-size: 13px; color: #5A6A80; }
.dlg-sec { margin-bottom: 16px; }
.dlg-sec-head {
	display: flex;
	align-items: baseline;
	gap: 8px;
	margin-bottom: 7px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #6B7A90;
}
.dlg-sec-head span { font-size: 11px; font-weight: 400; letter-spacing: 0; text-transform: none; color: #8B98AB; }

/* ==========================================================================================
   22. FORMS THAT PUT TWO OR THREE FIELDS PER ROW
   ------------------------------------------------------------------------------------------
   The brand editor, brand settings, business settings and both setup wizards lay fields out by
   giving each `.form-group` the classes `pull-left w49` / `pull-right w49` (two per row) or
   `pull-left w30` (three per row).

   THREE THINGS HAD TO BE UNDONE, all of them consequences of section 19 -- which gave EVERY
   `.form-group` a `210px | 1fr` label-beside-field grid, a rule written for one form and applied
   to forms it had never been looked at against:

     1. A fixed 210px label column inside a 49% box left ~100px for the input; inside a `w30` box
        the field column computed to literally 0px, so checkboxes had nowhere to sit.
     2. Floats are not rows. `pull-left` / `pull-right` place each box wherever the previous float
        left space, so a tall pair pushed the next pair apart.
     3. Percentage widths fight a gap. `w49` carries a legacy `margin-right: 8px` that `w30` does
        not, so any flex/percentage scheme needs the two reconciled by hand.

   The container is therefore a SIX-COLUMN GRID: full width spans 6, a half spans 3, a third
   spans 2. The gap belongs to the grid rather than to anyone's width, so a stray margin cannot
   push an item onto the next line -- the line is defined by the tracks.

   Every selector below is written out in full. An earlier revision tried to extend the `w49`
   rules to `w30` with a bulk replace, which split multi-selector lists and left bare
   `.form-group.w49,` lines inside rules meant for inputs -- so a `height: 40px` intended for a
   select landed on the ROW, clamping it to 40px while its contents needed 76px, and every field
   on the brand editor overlapped the one below it. Verbosity is cheaper than that.
   ========================================================================================== */

/* --- the container ------------------------------------------------------------------ */

.adminform_form .adminform_table {
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	column-gap: 24px;
	align-items: start;
}
.adminform_form .adminform_table > .form-group { grid-column: span 6; }
.adminform_form .adminform_table > .form-group.w49 { grid-column: span 3; }
.adminform_form .adminform_table > .form-group.w30 { grid-column: span 2; }
.adminform_form .adminform_table > .form-group.adminform-separator { grid-column: span 6; }
.adminform_form .adminform_table::after { content: none; }

/* --- the row ------------------------------------------------------------------------- */

/* `width: auto` matters: these classes carry percentage widths from the float layout, and a
   percentage on a grid item resolves against its TRACK -- `w30`'s 30% became 30% of a 207px
   track, a cell the width of its own checkbox. `height: auto` is the guard against exactly the
   clamping described above. */
.adminform_form .form-group.w49,
.adminform_form .form-group.w30 {
	display: block;
	box-sizing: border-box;
	float: none !important;
	width: auto;
	height: auto;
	max-width: none;
	margin-right: 0;
}

/* Label above field. In a half- or third-width box there is no room for a label column, and a
   wrapped label must not push its input below the one beside it -- so the label block reserves
   two lines and every input in a row starts at the same y. */
.adminform_form .form-group.w49 > div:first-child,
.adminform_form .form-group.w30 > div:first-child {
	min-height: 36px;
	padding-top: 0;
	display: flex;
	align-items: flex-start;
}
.adminform_form .form-group.w49 > div:first-child label,
.adminform_form .form-group.w30 > div:first-child label {
	line-height: 1.35;
	margin-bottom: 0;
}
/* A separator is a heading, not a field, and must not reserve label height. */
.adminform_form .form-group.adminform-separator > div:first-child {
	min-height: 0;
	display: block;
}

/* --- the controls -------------------------------------------------------------------- */

.adminform_form .form-group.w49 input[type="text"],
.adminform_form .form-group.w49 input[type="password"],
.adminform_form .form-group.w49 input[type="email"],
.adminform_form .form-group.w49 input[type="number"],
.adminform_form .form-group.w49 select,
.adminform_form .form-group.w49 textarea,
.adminform_form .form-group.w30 input[type="text"],
.adminform_form .form-group.w30 input[type="password"],
.adminform_form .form-group.w30 input[type="email"],
.adminform_form .form-group.w30 input[type="number"],
.adminform_form .form-group.w30 select,
.adminform_form .form-group.w30 textarea {
	width: 100%;
}

/* The theme swaps every <select> for a `.nice-select` div at runtime, so the <select> is
   display:none and sizing it sizes something nobody sees. Scoped to the control, never to the
   row -- that mistake is what clamped the rows to 40px. */
.adminform_form .form-group .nice-select {
	width: 100%;
	height: 40px;
	line-height: 38px;
	padding: 0 32px 0 12px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	color: #101A2B;
}

/* Short, known-length values read better at the width of their own content. */
.adminform_form .form-group.w49 input[name$="_limit"],
.adminform_form .form-group.w49 input[name="zip"],
.adminform_form .form-group.w49 input[name="expiration"],
.adminform_form .form-group.w49 input[name$="_area"],
.adminform_form .form-group.w30 input[name$="_limit"],
.adminform_form .form-group.w30 input[name="zip"],
.adminform_form .form-group.w30 input[name="expiration"],
.adminform_form .form-group.w30 input[name$="_area"] {
	max-width: 180px;
}

/* The checkbox. `.checkbox-container` wraps the input and a decorative `.checkmark` span that no
   stylesheet in this theme styles, so the real input is what is on screen. */
.adminform_form .form-group .checkbox-container {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
	margin: 0;
	cursor: pointer;
}
.adminform_form .form-group .checkbox-container input[type="checkbox"] {
	width: 16px;
	height: 16px;
	margin: 0;
	accent-color: #17803D;
	cursor: pointer;
}
.adminform_form .form-group .checkbox-container .checkmark { display: none; }

/* --- the user form keeps its own two-column grid (section 21) ------------------------- */

body.user_management_section .adminform_form .adminform_table > .form-group { grid-column: auto; }
body.user_management_section .adminform_form #admintablerow-permgrid,
body.user_management_section .adminform_form #admintablerow-brandaccess,
body.user_management_section .adminform_form #admintablerow-userfile { grid-column: 1 / -1; }

@media (max-width: 900px) {
	.adminform_form .adminform_table { grid-template-columns: minmax(0, 1fr); }
	.adminform_form .adminform_table > .form-group,
	.adminform_form .adminform_table > .form-group.w49,
	.adminform_form .adminform_table > .form-group.w30 { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------------------------------------
   CHECKBOX ROWS: the control beside its label, not beneath it.
   ------------------------------------------------------------------------------------------
   Every other field in these forms is label-above-input, because an input needs the full width
   of its box. A checkbox is 16px and needs none of it, so stacking spent a whole line on empty
   space and pushed the tick away from the words it belongs to.

   DIRECTION IS THE THEME'S, NOT MINE. `stylesheets.css:1599` already sets
   `flex-direction: row` on `#admintablerow-pm_enabled` and four siblings -- by ID, so at (1,0,0)
   it beats anything class-based here. A first attempt used `row-reverse` to put the tick first
   and got a form where three rows out of eleven disagreed with the other eight. Matching the
   theme costs nothing, needs no `!important`, and those same IDs appear on the product forms,
   where overriding them would be a ripple in a place nobody was looking.

   So: label first, tick pushed to the right edge of its own column. The ticks then line up down
   one edge, which is what makes "which of these are on" answerable at a glance -- the thing the
   stacked layout lost.

   `:has()` selects only rows whose field cell actually holds a checkbox: no PHP change, no new
   class, and every other row keeps the layout it has. Without `:has()` support the rule is
   ignored and the row falls back to today's stacked version -- legible, just taller.
   ------------------------------------------------------------------------------------------ */

.adminform_form .form-group.w49:has(.checkbox-container),
.adminform_form .form-group.w30:has(.checkbox-container) {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 10px;
}

.adminform_form .form-group.w49:has(.checkbox-container) > div:first-child,
.adminform_form .form-group.w30:has(.checkbox-container) > div:first-child {
	min-height: 0;
	flex: 1 1 auto;
	align-items: center;
	order: 2;
}
.adminform_form .form-group.w49:has(.checkbox-container) > div:last-child,
.adminform_form .form-group.w30:has(.checkbox-container) > div:last-child {
	flex: 0 0 auto;
	margin-left: 0;
	display: flex;
	align-items: center;
	order: 1;
}

/* The words become part of the hit target, which a 16px box badly needs. */
.adminform_form .form-group.w49:has(.checkbox-container) > div:first-child label,
.adminform_form .form-group.w30:has(.checkbox-container) > div:first-child label {
	cursor: pointer;
	margin: 0;
}

/* ==========================================================================================
   25. WHAT IS COMING UP — the calendar strip and the dashboard widget
   ------------------------------------------------------------------------------------------
   Both read GS\Calendar\UpcomingService, so they share this styling as well as their data.
   Colour carries the SOURCE (appointment / call / deal / ticket); overdue overrides it in red,
   because "late" outranks "what kind" when you are scanning.
   ========================================================================================== */

.cal-glance,
.up-widget {
	background: #FFFFFF;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	padding: 16px 18px;
	margin-bottom: 14px;
}
.cal-glance {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 16px 28px;
	align-items: start;
}

.cal-stats,
.up-stats { display: flex; gap: 12px; flex: 0 0 auto; }
.cal-stat,
.up-stat {
	min-width: 92px;
	padding: 10px 14px;
	border-radius: 8px;
	background: #F7F9FB;
}
.cal-stat b,
.up-stat b {
	display: block;
	font-size: 22px;
	font-weight: 600;
	line-height: 1.1;
	color: #101A2B;
	font-variant-numeric: tabular-nums;
}
.cal-stat span,
.up-stat span {
	display: block;
	margin-top: 2px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .05em;
	text-transform: uppercase;
	color: #7C8AA0;
}
/* Overdue is the only number that should be able to stop someone, so it is the only one that
   gets colour. A dashboard where every tile is coloured has no emphasis left to spend. */
.cal-stat.is-over,
.up-stat.is-over { background: #FDECEA; }
.cal-stat.is-over b,
.up-stat.is-over b { color: #9A2A18; }
.cal-stat.is-today,
.up-stat.is-today { background: #FEF3EF; }
.cal-stat.is-today b,
.up-stat.is-today b { color: #17803D; }

.cal-next { flex: 1 1 320px; min-width: 0; }
.cal-next-head,
.up-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 8px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
}
.up-head a {
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
	color: #17803D;
	text-decoration: none;
}
.up-head a:hover { text-decoration: underline; }

.cal-next ul,
.up-list { list-style: none; margin: 0; padding: 0; }
.cal-next li,
.up-list li {
	display: flex;
	align-items: center;
	gap: 9px;
	padding: 7px 0;
	border-bottom: 1px solid #F1F3F6;
	font-size: 13px;
}
.cal-next li {
	display: grid;
	grid-template-columns: 8px minmax(0, 1fr) auto auto;
	column-gap: 10px;
	padding: 8px 0;
}
.cal-next li:last-child,
.up-list li:last-child { border-bottom: 0; }
.cal-dot,
.up-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.cal-next li a,
.up-list li a {
	color: #101A2B;
	font-weight: 500;
	text-decoration: none;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}
.cal-next li a:hover,
.up-list li a:hover { color: #17803D; }
.cal-kind {
	flex: none;
	font-size: 11px;
	color: #8B98AB;
	padding: 1px 7px;
	border-radius: 4px;
	background: #F1F3F6;
}
.cal-when,
.up-when { margin-left: auto; flex: none; font-size: 12px; color: #8B98AB; font-variant-numeric: tabular-nums; }
.cal-when { margin-left: 0; }
.cal-next li.is-overdue .cal-when,
.up-list li.is-overdue .up-when { color: #9A2A18; font-weight: 600; }
.cal-empty,
.up-empty { font-size: 13px; color: #8B98AB; padding: 6px 0; }

.cal-legend {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 20px;
	margin: 0 0 14px;
	font-size: 12px;
	color: #6B7A90;
}
.cal-legend span { display: inline-flex; align-items: center; gap: 6px; }
.cal-legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }

@media (max-width: 767px) {
	.cal-glance { grid-template-columns: 1fr; }
	.cal-stats, .up-stats { width: 100%; }
	.cal-stat, .up-stat { flex: 1 1 0; min-width: 0; }
	.cal-kind { display: none; }
	.cal-next li { grid-template-columns: 8px minmax(0, 1fr) auto; }
}

/* ==========================================================================================
   26. TWO SPACING FIXES
   ========================================================================================== */

/* 26.1 THE RESERVED BAND, WHEN NOTHING CLAIMS IT.
   `.block-content-outer` reserves 58px at the top for a toolbar, which is then hoisted into it
   with `margin-top: -58px` (section 8). A page with NO toolbar never claims the band, so the
   58px stays as dead space — measured on the deal view: the page title ends at y=141 and its
   content starts at y=209.

   Released only when none of the three shapes the hoist recognises is present. `:has()` is the
   right tool: the reservation exists *because of* a child, so the child is what should decide.
   Where `:has()` is unsupported the band stays, which is today's behaviour — the failure mode is
   the status quo, not a broken page. */
.block > .body-wrapper > .block-content-outer:not(:has(> .additional-buttons-section)):not(:has(> .tablewrapper > .additional-buttons-section)):not(:has(> form > .additional-buttons-section)):not(:has(> .dash-nav-row)) {
	padding-top: 0;
}

/* `.dash-nav-row` is in that list because the dashboard's Day / Week / Month filter row occupies
   the band WITHOUT carrying the toolbar class. Releasing the padding pulled it up into the page
   title -- measured: the row's top at y=111 against a title bottom of y=156. A reservation is
   claimed by whatever sits in it, not only by the thing that was expected to. */

/* 26.2 THE DEAL BOARD COLUMN.
   The pipeline's cards carry `margin-bottom: 25px`, which is the right rhythm between two cards
   and too much between the last card and the "+ Add" beneath it — the button reads as detached
   from the stack it belongs to.

   Scoped to `body.deals` so the customers pipeline, which shares `.leadcontainer`, is not
   touched. Its spacing was not what was reported, and re-rhythming a screen nobody complained
   about is how a spacing fix becomes a regression. */
body.deals .leadcontainer > div[id] { margin-bottom: 12px; }
body.deals .leadcontainer .showmoreleads { margin-top: 0; }

/* ==========================================================================================
   27. THE MONTH GRID
   ------------------------------------------------------------------------------------------
   Measured before: the grid was 899px tall, starting at y=460 on a 900px viewport — it ended at
   y=1359, so two thirds of the month sat below the fold. FullCalendar's aspect ratio was doing
   that; `height: 'auto'` in calendar.js hands sizing to the cells and this gives the cells a
   height. Six rows at 74px is a month you can take in at once.
   ========================================================================================== */

#calendar {
	background: #FFFFFF;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	/* 10px at the foot rather than 16: the grid landed 2px past a 900px viewport, and the last
	   row's own border already reads as an edge. */
	padding: 14px 16px 10px;
}

/* --- the grid's own toolbar --- */
.fc .fc-toolbar.fc-header-toolbar { margin-bottom: 12px; }
.fc .fc-toolbar-title { font-size: 16px; font-weight: 600; color: #101A2B; }
.fc .fc-button {
	min-height: 32px;
	padding: 5px 12px;
	border-radius: 7px;
	border: 1px solid #DDE2E9;
	background: #FFFFFF;
	color: #35435A;
	font-size: var(--fs-sm);
	font-weight: 600;
	box-shadow: none;
	text-transform: capitalize;
}
.fc .fc-button:hover { background: #F7F9FB; border-color: #C7D0DB; color: #101A2B; }
.fc .fc-button-primary:not(:disabled).fc-button-active,
.fc .fc-button-primary:not(:disabled):active {
	background: #3FBF3C;
	border-color: #17803D;
	color: #0B1533;
}
.fc .fc-button:focus { box-shadow: 0 0 0 3px rgba(63, 191, 60, .16); }
.fc .fc-button:disabled { opacity: .45; }

/* --- day-of-week header --- */
.fc .fc-col-header-cell {
	background: #F7F9FB;
	border-color: #E9EDF1;
	padding: 7px 0;
}
.fc .fc-col-header-cell-cushion {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
	padding: 0;
}

/* --- the cells --- */
/* 68px, chosen against the fold rather than by taste: the page's content starts at y=436, and
   at 68 a six-row month ends at ~896 on the shortest common laptop viewport (900). A cell still
   holds the date plus two event chips, which is what `dayMaxEvents: 2` allows before it collapses
   the rest into "+N more". */
.fc .fc-daygrid-day-frame { min-height: 68px; }
.fc .fc-scrollgrid,
.fc .fc-scrollgrid td,
.fc .fc-scrollgrid th { border-color: #E9EDF1; }
.fc .fc-daygrid-day-number {
	font-size: 12px;
	font-weight: 600;
	color: #6B7A90;
	padding: 5px 7px;
}
.fc .fc-day-other .fc-daygrid-day-number { color: #C0C8D4; }
.fc .fc-day-today { background: #FEF6F3; }
/* The date, not the whole cell, carries today's emphasis -- a fully tinted cell competes with
   the event chips inside it. */
.fc .fc-day-today .fc-daygrid-day-number {
	background: #3FBF3C;
	color: #0B1533;
	border-radius: 50%;
	width: 22px;
	height: 22px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	margin: 4px 5px 0 0;
}

/* --- events --- */
.fc .fc-daygrid-event {
	border-radius: 4px;
	padding: 2px 7px;
	margin: 2px 6px;
	font-size: var(--fs-xs);
	font-weight: 500;
	border: 0;
}
.fc .fc-daygrid-event:hover { filter: brightness(.94); }
.fc .fc-daygrid-more-link {
	font-size: 11px;
	font-weight: 600;
	color: #17803D;
	padding: 0 6px;
}

/* The fold-fit tightening (13/8/5px) is gone: it is what made the glance overlap
   itself — stats flush against Next up, dates flung to the far edge, chips kissing
   the cell border. The month can scroll a little; a strip you cannot read cannot. */

@media (max-width: 767px) {
	#calendar { padding: 10px; }
	.fc .fc-daygrid-day-frame { min-height: 56px; }
	.fc .fc-toolbar.fc-header-toolbar { flex-wrap: wrap; gap: 8px; }
}

/* ==========================================================================================
   27a. CALENDAR MODULE PAGE RHYTHM
   ------------------------------------------------------------------------------------------
   One stack for Calendar / Tasks / Booked Calls. The title-line hoist (-101px) pulled the
   following sibling up into the heading, which is the overlap in the screenshot: glance
   against the title, filter chips against "Tasks", Booked Calls table flush under the
   heading because it has no toolbar and §26.1 released the reserved band.

   Tokens stay the CRM's: ink #101A2B, wash #F7F9FB, accent #17803D. This is an instrument
   panel for a salesperson's week, not a new visual identity.
   ========================================================================================== */

body.appointments_section .block-header .content-wrapper {
	padding-top: 16px;
	padding-bottom: 0;
}
body.appointments_section .block-header h2 {
	margin: 0;
	line-height: 44px;
	font-size: 20px;
	font-weight: 600;
	color: #101A2B;
}

/* Booked Calls has no toolbar. Keep the same 58px title-line band as the siblings so the
   three tabs do not start at three different Y positions. */
body.appointments_section .block > .body-wrapper > .block-content-outer {
	padding-top: 58px;
}

/* The page body starts below the title + action, not under them. */
body.appointments_section .cal-page {
	padding-top: 8px;
}

body.appointments_section .cal-filters {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 16px;
}
body.appointments_section .cal-filters .adminbuttons {
	justify-content: flex-start;
	flex-wrap: wrap;
	gap: 8px;
}

@media (max-width: 767px) {
	body.appointments_section .block-header .content-wrapper { padding-top: 12px; }
	body.appointments_section .block-header h2 { line-height: 36px; }
}

/* Create Task — Assigned Owner + Assigned Contact: equal columns, same selectize chrome. */
#ai_modal .addtask-assign-row,
.addtask-assign-row {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	width: 100%;
	box-sizing: border-box;
}
#ai_modal .addtask-assign-row .customer-select,
.addtask-assign-row .customer-select {
	flex: 1 1 0;
	min-width: 0;
	width: 0;
	box-sizing: border-box;
}
#ai_modal .addtask-assign-row .customer-select > div:first-child,
.addtask-assign-row .customer-select > div:first-child {
	margin-bottom: 6px;
}
#ai_modal .addtask-assign-row .customer-select label,
.addtask-assign-row .customer-select label {
	font-weight: 600;
	font-size: 14px;
	line-height: 1.2;
	color: #171725;
	margin: 0;
	display: block;
}
#ai_modal .addtask-assign-row .customer-select .selectize-control,
#ai_modal .addtask-assign-row .customer-select .nice-select,
#ai_modal .addtask-assign-row .customer-select select,
.addtask-assign-row .customer-select .selectize-control,
.addtask-assign-row .customer-select .nice-select,
.addtask-assign-row .customer-select select {
	width: 100% !important;
	max-width: 100%;
	box-sizing: border-box;
}
#ai_modal .addtask-assign-row .customer-select .selectize-input,
.addtask-assign-row .customer-select .selectize-input {
	width: 100%;
	min-height: 38px;
	padding: 8px 12px;
	box-sizing: border-box;
	display: block;
}

/* Files → Upload (and Library) land in #ai_modal. An empty .load() used to leave only the
   close X on a 800px bar; with content, the sheet still inherited display:table and looked
   like a search pill. Size the dialog to the form. */
#ai_modal.showWindow {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px 16px;
	box-sizing: border-box;
}
#ai_modal .modal-dialog {
	width: 560px;
	max-width: calc(100vw - 32px);
	margin: 0 auto;
}
#ai_modal .modal-content {
	display: block;
	min-height: 0;
	padding: 22px 24px 18px;
	border-radius: 12px;
	box-shadow: 0 12px 40px rgba(16, 26, 43, .18);
}
#ai_modal .ai_modal_content {
	display: block;
	width: 100%;
}
#ai_modal .close-modal { top: 16px; right: 16px; }
#ai_modal .modal-content .row h1 {
	text-align: left;
	font-size: 18px;
	font-weight: 600;
	line-height: 1.3;
	margin: 0 0 14px;
	color: #101A2B;
}
/* The file input was opacity:0 + z-index:-1, which sits behind the modal overlay so a
   label[for=userfile] click never opens the picker. Cover the drop zone with the input. */
#ai_modal #drag_and_drop {
	position: relative;
	cursor: pointer;
}
#ai_modal #drag_and_drop input.inputfile {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	opacity: 0;
	z-index: 4;
	cursor: pointer;
	overflow: hidden;
}
#ai_modal .adminform_savebutton {
	display: flex;
	justify-content: flex-start;
	margin-top: 12px;
	padding: 0;
}
#ai_modal .adminform_savebutton input[type="submit"] {
	display: inline-block;
	width: auto;
	min-width: 96px;
	min-height: 38px;
	padding: 8px 22px;
	border-radius: 8px;
	border: 1px solid #17803D;
	background: #3FBF3C;
	color: #0B1533;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: 0;
	text-indent: 0;
}

/* ==========================================================================================
   27b. CAMPAIGNS LIST PAGE RHYTHM
   ------------------------------------------------------------------------------------------
   Same job as 27a on m=campaigns: tabs flush against "Campaigns", Name search glued to the
   All Campaigns dropdown at mismatched heights, metric cells pinched by the two-class
   `.campaignlist .table td { padding: 15px 8px }`, kebab kissing the card, Draft/Sent pills
   of uneven width.

   Filter PHP and row titles are untouched. Identity loads last, so these beat
   stylesheets.css and extended-buttons.css without !important.
   ========================================================================================== */

body.campaigns-list .block-header .content-wrapper {
	padding-top: 16px;
	padding-bottom: 0;
}
body.campaigns-list .block-header h2 {
	margin: 0;
	line-height: 44px;
	font-size: 20px;
	font-weight: 600;
	color: #101A2B;
}

/* The toolbar carries search + a status <select>, so §28 correctly refuses the title-line
   hoist. §8 still pulls it -58px into the reserved band, which is why the filter row sat
   against the heading. Release the band and leave the stack below the title. */
body.campaigns-list .block > .body-wrapper > .block-content-outer {
	padding-top: 12px;
}
body.campaigns-list .block > .body-wrapper > .block-content-outer > .tablewrapper > .additional-buttons-section {
	margin-top: 0;
	min-height: 0;
	padding-bottom: 16px;
	align-items: center;
}

/* `.campaigns-list .extended-buttons { padding: 0 }` deleted the 16px under the filter row. */
body.campaigns-list .extended-buttons {
	padding: 0 0 16px;
}

/* Search and the status select were different heights and glued by a 1px .vr with no flex
   gap. Shared: every extended-buttons toolbar that uses ajaxsearch.tpl + a dropdown. */
.extended-buttons .flex {
	display: flex;
	align-items: center;
	gap: 12px;
}
.extended-buttons .flex > .field-search,
.extended-buttons .flex .frmSearch,
.extended-buttons .flex > .filter-wrapper,
.extended-buttons .flex .campaigns-dropdowns {
	margin-left: 0;
	margin-right: 0;
}
.extended-buttons .vr {
	display: none;
}

/* Match the search field identity already set to 45px / 8px / #E5E5E5. */
.extended-buttons .nice-select,
.extended-buttons .small-height-dropdown {
	height: 45px;
	min-height: 45px;
	line-height: 43px;
	border: 1px solid #E5E5E5;
	border-radius: 8px;
	background: #FFFFFF;
	box-sizing: border-box;
}
.extended-buttons .nice-select .current {
	line-height: 33px;
	padding: 5px 16px;
	font-weight: 500;
}

/* Beat `.campaignlist .table td` (0,2,1) the same way §19 beats every other two-class grid. */
.campaignlist table.admintable.table > thead > tr > th,
.campaignlist table.admintable.table > tbody > tr > td {
	padding: 12px 16px;
}
.campaignlist table.admintable.table > tbody > tr > td.at-cell-contactsqty,
.campaignlist table.admintable.table > tbody > tr > td.at-cell-openers,
.campaignlist table.admintable.table > tbody > tr > td.at-cell-clickers,
.campaignlist table.admintable.table > tbody > tr > td.at-cell-unsubscr {
	font-variant-numeric: tabular-nums;
}
.campaignlist table.admintable.table > thead > tr > th.at-cell-action_links,
.campaignlist table.admintable.table > tbody > tr > td.at-cell-action_links {
	padding-right: 20px;
	text-align: right;
}
.campaignlist .campaign-label {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 76px;
	padding: 4px 12px;
	text-align: center;
	box-sizing: border-box;
}

@media (max-width: 767px) {
	body.campaigns-list .block-header .content-wrapper { padding-top: 12px; }
	body.campaigns-list .block-header h2 { line-height: 36px; }
}

/* ==========================================================================================
   27c. ONE PAGE TITLE, SAME PLACE ON EVERY MARKETING TAB
   ------------------------------------------------------------------------------------------
   The chrome heading in `.block-header` is the page title (Phase 4). Campaign wizard steps
   also printed `$m.page_title` inside `.stepssection`, so "Campaign Sequences" appeared twice
   and `.stepssection { margin-top: 60px }` opened a dead band under the first one.

   `campaigns-chrome` is on Campaigns / Create / Run / Broadcast / Content. Title metrics match
   Calendar and the Campaigns list (16px under the tabs, 44px heading, ink #101A2B). The
   stepper stays; the reprint does not.
   ========================================================================================== */

body.campaigns-chrome .block-header .content-wrapper {
	padding-top: 16px;
	padding-bottom: 0;
}
body.campaigns-chrome .block-header h2 {
	margin: 0;
	line-height: 44px;
	font-size: 20px;
	font-weight: 600;
	color: #101A2B;
}

/* Belt-and-suspenders: any leftover in-page reprint of the chrome title. */
body.campaigns-chrome .stepssection > h2,
body.campaigns-chrome .addcustomer > h2 {
	display: none;
}

/* stylesheets.css still sets `.stepssection { margin-top: 60px }`. Kill that gap. */
body.campaigns-chrome .stepssection {
	margin-top: 0;
	margin-bottom: 8px;
}

@media (max-width: 767px) {
	body.campaigns-chrome .block-header .content-wrapper { padding-top: 12px; }
	body.campaigns-chrome .block-header h2 { line-height: 36px; }
}

/* ==========================================================================================
   28. PAGE TITLE AND ITS ACTION ON ONE LINE
   ------------------------------------------------------------------------------------------
   The title sits in `.block-header`, its action in the reserved band below — two rows, with the
   button stranded under the heading. On one line, spaced apart, is both tidier and shorter.

   ONLY WHERE THE TOOLBAR IS JUST BUTTONS. Several toolbars carry a whole filter stack —
   `organizations` measures 391px tall, `customers` 149px — and lifting one of those onto the
   title line would bury the heading under a search form. `:has()` distinguishes them exactly:
   a toolbar containing no input, select or textarea is a button row and nothing else. Measured
   across eleven routes, that separates the six button-only toolbars from the five with filters
   with no false positives either way.

   ...AND ONLY WHERE IT IS A TOOLBAR AT ALL. `:not(:has(nav))` was added on 2026-09-08, when
   section 43 turned this same container into the settings rail on 24 routes. A rail holds no
   input, so the heuristic above claimed it: 320px of padding pushed an 11-item nav out of a
   236px card and `z-index: 2` painted it over the form beside it. The heuristic was not wrong
   about filters, it was wrong that everything left over is a button row.

   The argument is the ELEMENT `nav`, deliberately, not `.settings-rail`. `:not()` carries the
   specificity of its argument, so an element adds (0,0,1) where a class would add (0,1,0) --
   enough to lift this rule from (0,4,3) to (0,5,3), where it would start beating the
   `:first-child` reset in the 767px media query at (0,5,0) and re-hoist every toolbar on a
   phone. Nothing in this stylesheet sits between (0,4,3) and (0,4,4).

   The offset is the same on every page (90px from the un-hoisted position) whether or not the
   route has a sub-nav, because a sub-nav shifts the title and the band by the same amount.
   ========================================================================================== */

.block > .body-wrapper > .block-content-outer > .additional-buttons-section:not(:has(input)):not(:has(select)):not(:has(textarea)):not(:has(nav)),
.block > .body-wrapper > .block-content-outer > .tablewrapper > .additional-buttons-section:not(:has(input)):not(:has(select)):not(:has(textarea)):not(:has(nav)),
.block > .body-wrapper > .block-content-outer > form > .additional-buttons-section:not(:has(input)):not(:has(select)):not(:has(textarea)):not(:has(nav)) {
	margin-top: -101px;
	min-height: 44px;
	margin-bottom: 0;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	position: relative;
	z-index: 2;
	/* The title occupies the left of this line. Reserving room for it means a long heading and a
	   wide button cannot collide -- the button wraps under instead, which is ugly but readable,
	   where an overlap is neither. */
	padding-left: 320px;
	pointer-events: none;
}
/* An empty `.pipeline-dropdown` placeholder padded the Brands toolbar to 61px against everyone
   else's 44, putting its button 5px below the title's centre line. An empty div that changes
   nothing but the height is worth nothing. */
.block-content-outer .additional-buttons-section:not(:has(input)) > .pipeline-dropdown:empty {
	display: none;
}

/* The row is click-through so it cannot sit over the title; the controls themselves are not. */
.block > .body-wrapper > .block-content-outer > .additional-buttons-section:not(:has(input)) > *,
.block > .body-wrapper > .block-content-outer > .tablewrapper > .additional-buttons-section:not(:has(input)) > *,
.block > .body-wrapper > .block-content-outer > form > .additional-buttons-section:not(:has(input)) > * {
	pointer-events: auto;
}

/* ==========================================================================================
   29. THE DASHBOARD "COMING UP" CARD
   ------------------------------------------------------------------------------------------
   Vertical rather than the wide strip the calendar page uses. On the calendar the strip sits
   above a full-width grid and has the width to spend; on the dashboard it sits among column
   cards, and a card that reads top-to-bottom belongs there.
   ========================================================================================== */

.up-widget {
	max-width: 420px;
	padding: 14px 16px 12px;
}
.up-stats {
	flex-direction: column;
	gap: 6px;
	margin-bottom: 0;
}
/* Label left, figure right. Stacked full-width rows with the number at the left edge leave a
   third of the card empty and give the eye nothing to land on; reading label-then-figure also
   matches how every other stat block on this dashboard is read. */
.up-stat {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	min-width: 0;
	padding: 7px 12px 7px 11px;
	border-left: 3px solid #DDE3EB;
	border-radius: 0 8px 8px 0;
}
.up-stat b { order: 2; font-size: 17px; line-height: 1.15; }
.up-stat span { order: 1; margin-top: 0; }
.up-stat.is-over { border-left-color: #17803D; }
.up-stat.is-today { border-left-color: #E8A33D; }
/* A count of nothing is not an alert. Zero rows keep the rail but give up the colour, so the
   one number that does need attention is the only one wearing it. */
.up-stat.is-zero { border-left-color: #DDE3EB; background: #FAFBFC; }
.up-stat.is-zero b,
.up-stat.is-zero span { color: #9AA6B6; }

/* The list is a second section of the card, not three more tiles. */
.up-list,
.up-empty { margin-top: 12px; padding-top: 6px; border-top: 1px solid #EDF0F4; }
.up-list li { padding: 6px 0; }

@media (max-width: 900px) {
	.up-widget { max-width: none; }
	.block > .body-wrapper > .block-content-outer > .additional-buttons-section:not(:has(input)),
	.block > .body-wrapper > .block-content-outer > .tablewrapper > .additional-buttons-section:not(:has(input)),
	.block > .body-wrapper > .block-content-outer > form > .additional-buttons-section:not(:has(input)) {
		margin-top: 0;
		padding-left: 0;
	}
}

/* ==========================================================================================
   30. THE COMPANY DETAIL TAB BODY
   ------------------------------------------------------------------------------------------
   conversation.css:449 declares `.block-content-outer { display: flex }` with no scope at all.
   organizationdetails.php:212 loads that sheet for the whole detail screen, so on the Contacts
   tab the contacts table and the custom-property form -- siblings in that container -- became
   a two-column row. `.table-responsive { width: 100% !important }` (stylesheets.css:26) then
   claimed the entire row, and flex-shrink left the form ~125-153px. Measured: the identical
   component renders 780px on m=contacts. The panel was never clipped, only starved.

   Child combinators throughout, deliberately: a descendant selector would also match the
   `.block-content-outer` inside #messagemodal, which conversation.css:446 forces to
   `flex-direction: column !important`, and that modal body is AJAX-loaded and empty at
   measurement time -- i.e. it would be an untested target.
   ========================================================================================== */

.company-details-wrapper > .profile-active > .block > .block-content-outer {
	flex-wrap: wrap;
}
.company-details-wrapper > .profile-active > .block > .block-content-outer > .table-responsive {
	flex: 1 1 100%;
	min-width: 0;
}
.company-details-wrapper > .profile-active > .block > .block-content-outer > form {
	flex: 1 1 100%;
	min-width: 0;
	margin-top: 16px;
}
/* The panels above the contacts table -- "Imported from HubSpot" (SourcePanel), the read-only
   Details panel and the save notice -- are bare .ct-panel / .pr-flash children of the same flex
   row. Without a basis they shrank to their text, so a short HubSpot card and the Details form
   (then capped at 620px) fitted side by side, touching, the form 16px lower. Every block takes
   the full row; flex margins do not collapse, so a form after a panel drops its own top margin. */
.company-details-wrapper > .profile-active > .block > .block-content-outer > .ct-panel,
.company-details-wrapper > .profile-active > .block > .block-content-outer > .pr-flash {
	flex: 1 1 100%;
	min-width: 0;
}
.company-details-wrapper > .profile-active > .block > .block-content-outer > .ct-panel + form {
	margin-top: 0;
}

/* ==========================================================================================
   31. THE COMPANY ASSOCIATION STRIP
   ------------------------------------------------------------------------------------------
   Answers "does this company have relationships?" at a glance, which is the question the
   detail page could not answer at all: LinkedCompanies() existed and had no caller.

   Every colour here is declared on the chip itself rather than borrowed from `.dp-linked` or
   `.ct-legacy`. Those two get their fill only from scoped rules (`.deal-pick-row .dp-linked`
   at 1699), so reusing the bare class on this page would have rendered a shapeless chip with
   no background -- shape without colour.
   ========================================================================================== */

/* ==========================================================================================
   TICKET 1 -- the company hierarchy panel on the company record.

   Two columns, because the two halves answer different questions and are read at different
   times: the parent is a FIELD you set once, the children are a LIST you scan. Stacking them
   would put a form between the reader and the list they came for.

   Depth is expressed with indentation and a rule, not with nesting -- the tree arrives from
   the service already flattened and depth-annotated, so a franchise group renders in document
   order and needs no recursive template.
   ========================================================================================== */

.hier-panel {
	margin: 0 0 14px;
	padding: 14px 16px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
}
.hier-inherited-note {
	margin: -2px 0 12px;
	padding: 9px 12px;
	background: #FFF8E8;
	border: 1px solid #F0DCA8;
	border-radius: 8px;
	font-size: 12.5px;
	color: #7A5B12;
}
.hier-crumbs {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0 0 12px;
	padding-bottom: 10px;
	border-bottom: 1px solid #F0F2F5;
	font-size: 12.5px;
}
.hier-crumbs a { color: #2F6BA8; text-decoration: none; }
.hier-crumbs a:hover { text-decoration: underline; }
.hier-sep  { color: #C2CAD6; }
.hier-self { font-weight: 600; color: #1F2A37; }

.hier-cols { display: flex; flex-wrap: wrap; gap: 28px; }
.hier-parent   { flex: 1 1 260px; min-width: 0; }
.hier-children { flex: 2 1 380px; min-width: 0; }

.hier-panel h5 {
	margin: 0 0 8px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #8B98AB;
}
.hier-count { margin-left: 8px; text-transform: none; letter-spacing: 0; color: #A3AEBF; font-weight: 500; }

.hier-parent-current { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.hier-empty { font-size: 13px; color: #8B98AB; margin-bottom: 10px; }

.hier-name { font-size: 13.5px; font-weight: 600; color: #2F6BA8; text-decoration: none; }
.hier-name:hover { text-decoration: underline; }
/* A company the viewer cannot open is deliberately not a link and carries no brand name --
   a clickable name that 404s is both a dead end and a disclosure. */
.hier-unreachable { color: #98A2B3; font-style: italic; cursor: default; }
.hier-unreachable:hover { text-decoration: none; }

.hier-brand {
	font-size: 10.5px;
	padding: 2px 7px;
	border-radius: 999px;
	background: #F2F4F7;
	color: #667085;
	white-space: nowrap;
}
.hier-access {
	font-size: 10.5px;
	padding: 2px 7px;
	border-radius: 999px;
	background: #F2F4F7;
	color: #667085;
	white-space: nowrap;
}
.hier-access.is-full { background: #E8F3EC; color: #2C6B45; }
.hier-disabled {
	font-size: 10.5px;
	padding: 2px 7px;
	border-radius: 999px;
	background: #FDECEC;
	color: #9B2C2C;
}

.hier-tree { list-style: none; margin: 0; padding: 0; }
.hier-node {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	padding: 7px 0;
	border-bottom: 1px solid #F5F6F8;
}
.hier-node:last-child { border-bottom: 0; }
.hier-depth-1 { padding-left: 20px; border-left: 2px solid #EDEFF3; }
.hier-depth-2 { padding-left: 40px; border-left: 2px solid #EDEFF3; }
.hier-depth-3 { padding-left: 60px; border-left: 2px solid #EDEFF3; }
.hier-depth-4 { padding-left: 80px; border-left: 2px solid #EDEFF3; }
/* Past four levels the indent stops growing rather than pushing names off the panel. */
.hier-node[class*="hier-depth-"]:not(.hier-depth-0):not(.hier-depth-1):not(.hier-depth-2):not(.hier-depth-3):not(.hier-depth-4) {
	padding-left: 96px;
	border-left: 2px solid #EDEFF3;
}

.hier-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.hier-form select {
	max-width: 100%;
	padding: 6px 9px;
	font-size: 13px;
	border: 1px solid #D7DCE3;
	border-radius: 7px;
	background: #FFF;
}
.hier-hint { flex: 1 1 100%; margin: 4px 0 0; font-size: 11.5px; line-height: 1.5; color: #8B98AB; }
/* CF-5 follow-up -- the parent dropdown is a selectize search box: the company picker takes the row. */
.hier-form .selectize-control { flex: 1 1 100%; min-width: 0; margin: 0; }
.hier-form .selectize-input { min-height: 38px; padding: 8px 10px; font-size: 13px; border-color: #D7DCE3; border-radius: 7px; box-shadow: none; }
.hier-form .selectize-dropdown { font-size: 13px; }
.hier-form .selectize-dropdown .optgroup-header { font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: #6B778A; background: #F6F8FA; }
.hier-form .selectize-dropdown-content { max-height: 320px; }
.hier-pick-brand { color: #8B98AB; }
/* CF-6 -- Create Contact / Create Deal under the company name. Own classes, not the contact page's
   34px icon toolbar (text squeezed into those squares overlapped). */
.company-quick-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
/* Compact (2026-10-06): three text buttons in one row; 28px high, 12.5px text, 14px icons. */
.company-quick-actions .ab-button.cqa-btn {
	display: inline-flex !important; align-items: center; gap: 5px; width: auto !important; min-width: 0 !important;
	height: 28px !important; min-height: 28px !important; margin: 0 !important; padding: 0 10px !important; font-size: 12.5px !important; font-weight: 500;
	line-height: 1 !important; white-space: nowrap; text-decoration: none; border-radius: 7px !important;
	border: 1px solid #DDE3EB !important; background: #FFF !important; color: #374151 !important; box-shadow: none !important;
	transition: border-color .15s, background .15s, color .15s;
}
.company-quick-actions .ab-button.cqa-btn:hover { border-color: #3BB54A !important; background: #F3FBF4 !important; color: #1E7B34 !important; }
.company-quick-actions .ab-button.cqa-btn svg { flex: 0 0 auto; width: 14px; height: 14px; }
/* Social profiles under the company name: round 28px icons in each network's colour. */
.company-social { display: flex; gap: 6px; margin-top: 8px; }
.company-social-link { width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
	background: #F1F4F8; color: #4A5568 !important; text-decoration: none !important; font-size: 14px; transition: background .15s, color .15s, transform .15s; }
.company-social-link:hover { transform: translateY(-1px); color: #FFF !important; }
.company-social-link.is-linkedin:hover { background: #0A66C2; }
.company-social-link.is-facebook:hover { background: #1877F2; }
.company-social-link.is-twitter:hover { background: #111; }
.company-social-link.is-instagram:hover { background: #E1306C; }
/* CF-5 -- a saved parent shows Change / Remove instead of the picker. */
.hier-parent-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 10px; }
.hier-parent-actions[hidden], .hier-picker[hidden] { display: none; }
.hier-remove { display: inline; margin: 0; }
.hier-remove .ab-button.hier-remove-btn { color: #B42318; }
.hier-remove .ab-button.hier-remove-btn:hover { color: #912018; border-color: #F3B8B2; }
.hier-manage { display: inline-block; margin-top: 10px; font-size: 12.5px; color: #2F6BA8; text-decoration: none; }
.hier-manage:hover { text-decoration: underline; }

/* The role a person holds AT this company, on the company's own contact grid (AC4). */
.cc-role { font-size: 12.5px; color: #344054; }
.cc-primary {
	font-size: 10px;
	padding: 1px 6px;
	border-radius: 999px;
	background: #EEF4FF;
	color: #2F5AA8;
	text-transform: uppercase;
	letter-spacing: .04em;
}

@media (max-width: 900px) {
	.hier-cols { gap: 18px; }
}

.assoc-strip {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px 14px;
	margin: 0 0 14px;
	padding: 11px 14px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
}
.assoc-label {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
	flex: none;
}
.assoc-chips { display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; }
.assoc-chip {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	max-width: 100%;
	padding: 5px 11px 5px 9px;
	border: 1px solid #DDE3EB;
	border-left: 3px solid #8B98AB;
	border-radius: 7px;
	background: #F7F9FB;
	text-decoration: none;
	line-height: 1.3;
}
.assoc-chip:hover { border-color: #17803D; border-left-color: #17803D; background: #FEF3EF; }
/* A parent sits above this company; the rail leans on direction, not on severity. */
.assoc-chip.is-parent { border-left-color: #2F6BA8; }
.assoc-role {
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #6B7A90;
	flex: none;
}
.assoc-name {
	font-size: 13px;
	font-weight: 600;
	color: #101A2B;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}
.assoc-access {
	flex: none;
	padding: 1px 7px;
	border-radius: 4px;
	background: #ECEFF3;
	color: #66768C;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .03em;
}
/* `full` is the only level that actually shares contacts across the link, so it is the only
   one that earns a colour. */
.assoc-access.is-full { background: #E8F3EC; color: #2C6B45; }
.assoc-empty { font-size: 13px; color: #8B98AB; }
.assoc-manage {
	margin-left: auto;
	flex: none;
	font-size: 12px;
	font-weight: 600;
	color: #17803D;
	text-decoration: none;
}
.assoc-manage:hover { text-decoration: underline; }

@media (max-width: 900px) {
	.assoc-manage { margin-left: 0; }
}

/* ==========================================================================================
   32. THE COMPANIES / CONTACTS RESULTS TABLE MUST SCROLL, NOT PUSH
   ------------------------------------------------------------------------------------------
   `.extended-buttons { display: flex }` makes the results <form> a flex item, and a flex item
   defaults to `min-width: auto` -- i.e. it refuses to shrink below its content's min-content
   width. The companies table's min-content is 1641px against a 1190px content column, so the
   form inflated to 1641, `.table-responsive { width: 100% !important }` inherited that, and
   the wrapper's own `overflow-x: auto` never engaged. `section.content` then clipped the
   surplus with no scrollbar anywhere, leaving the trailing columns -- the per-row Edit and
   Delete actions among them -- with no way to reach them.

   Letting the form shrink is the whole fix: the table then overflows inside .table-responsive,
   which is exactly what that element exists to do.
   ========================================================================================== */

.additional-buttons-section.extended-buttons > form {
	min-width: 0;
	max-width: 100%;
}
.additional-buttons-section.extended-buttons > form > .table-responsive {
	min-width: 0;
	max-width: 100%;
	overflow-x: auto;
}

/* ==========================================================================================
   33. CAMPAIGN SEQUENCES, AI ASSISTANT, INITIAL MESSAGE
   ------------------------------------------------------------------------------------------
   Same identity as the rest of the chrome: ink #101A2B, wash #F7F9FB, accent #17803D.
   Sequence pages are `body.wizard_page` + `.emails_choose`. The Initial Message editor is
   `#add_customer_modal` loaded with `.campaign_sms_form`. The assistant is
   `#openai_assistant_modal`. All three were oversized sheets with empty gutters; they are
   now sized to their content.

   Campaigns list rhythm lives in §27b and is not restated here.
   ========================================================================================== */

/* 33.1 Sequence page: tabs-to-title air, stepper, notices, container.
   The page title lives in `.block-header` only (see §27c). Do not restyle a second h2. */
body.wizard_page .block > .body-wrapper > .block-content-outer {
	padding-top: 12px;
}
body.wizard_page .stepssection {
	margin-top: 0;
	margin-bottom: 8px;
}
body.wizard_page .stepssection .steps {
	margin: 0;
	padding: 0;
}
body.wizard_page .stepssection ul {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 12px;
	padding: 0;
}
body.wizard_page .stepssection ul li {
	width: 36px;
	height: 4px;
	padding: 0;
	margin: 0;
	border: 0;
	border-radius: 999px;
	background: #DDE3EB;
	font-size: 0;
	color: transparent;
	float: none;
}
body.wizard_page .stepssection ul li.active {
	background: #101A2B;
	border-color: transparent;
	color: transparent;
}
body.wizard_page .stepssection ul li.line,
body.wizard_page .stepssection ul li.line.active,
body.wizard_page .stepssection ul li.line:before,
body.wizard_page .stepssection ul li.line.active:before {
	display: none;
}
body.wizard_page .stepssection .wizard_hint {
	margin: 0;
	color: #6B7A90;
	font-size: 13px;
}

body.wizard_page .emails_choose.addcustomer,
body.wizard_page .addcustomer.emails_choose {
	padding: 16px 20px 12px;
	max-width: 880px;
	margin: 0 auto;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	display: block;
}
body.wizard_page .emails_choose .aui-message,
body.wizard_page > .block .aui-message-warning {
	padding: 8px 12px;
	margin: 0 0 12px;
	font-size: 13px;
	line-height: 1.4;
}
body.wizard_page .emails_choose .aui-message-error {
	padding: 8px 12px;
	margin: 0 0 12px;
}
body.wizard_page .block-content-outer > div[style*="max-width: 900px"] {
	max-width: 880px;
	margin: 0 auto 8px;
}

/* 33.2 Step cards and the Select Type control. */
body.wizard_page .emails_choose .email_row {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	margin: 0 0 12px;
	width: 100%;
}
body.wizard_page .emails_choose .email_row .numbers {
	float: none;
	width: 36px;
	flex: none;
}
body.wizard_page .emails_choose .email_row .numbers span {
	width: 32px;
	height: 32px;
	margin-top: 4px;
	padding-top: 4px;
	font-size: 14px;
	font-weight: 600;
	color: #101A2B;
	border-color: #DDE3EB;
}
body.wizard_page .emails_choose .email_container {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 10px;
	width: calc(100% - 48px);
	padding: 12px 14px;
	border-color: #E4E7EC;
	border-radius: 8px;
	background: #FFFFFF;
}
body.wizard_page .emails_choose .email_container:before,
body.wizard_page .emails_choose .email_container:after {
	display: none;
}
body.wizard_page .emails_choose .email_container label,
body.wizard_page .emails_choose .email_container label.capitalize {
	float: none !important;
	display: block !important;
	width: 100% !important;
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
	color: #101A2B;
}
body.wizard_page .emails_choose .email_container > select.form-control,
body.wizard_page .emails_choose .email_container > .nice-select {
	width: 280px;
	max-width: 100%;
	min-width: 0;
	margin: 0;
	height: 36px;
	line-height: 34px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	box-sizing: border-box;
}
body.wizard_page .emails_choose .nextsequence .email_container {
	width: 100%;
	float: none;
}

/* 33.3 ADD EMAIL / SMS / CALL — grouped, no orphan padding. */
body.wizard_page .emails_choose .add_sequence_item,
body.wizard_page .emails_choose .sequence-loader {
	margin: 4px 0 12px;
	width: 100%;
}
body.wizard_page .emails_choose .add_sequence_item > div {
	display: flex !important;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-start;
	gap: 8px;
	margin: 0;
	float: none;
}
body.wizard_page .emails_choose .add_sequence_item a.startnow {
	position: static;
	top: auto;
	float: none !important;
	display: inline-flex;
	align-items: center;
	margin: 0 !important;
	min-height: 36px;
	padding: 7px 14px;
	border-radius: 7px;
	background: #101A2B;
	color: #FFFFFF;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .02em;
	text-transform: uppercase;
	box-shadow: none;
	text-decoration: none;
}
body.wizard_page .emails_choose .add_sequence_item a.startnow:hover {
	background: #1B283C;
	color: #FFFFFF;
}

/* 33.4 day / hr / min on one baseline, equal chips, trailing phrase stays on the row. */
body.wizard_page .emails_choose .dayselect,
body.wizard_page .emails_choose .dayselect.nextsequence_dayselect {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: 8px;
	width: 100%;
	margin: 4px 0 0;
}
body.wizard_page .emails_choose .dayselect[style*="display: none"] {
	display: none;
}
body.wizard_page .emails_choose .dayselect .send_message_label,
body.wizard_page .emails_choose .dayselect .send_message_label2 {
	float: none !important;
	display: inline !important;
	width: auto !important;
	margin: 0;
	font-size: 13px;
	font-weight: 500;
	color: #5A6A80;
	white-space: nowrap;
	flex: none;
}
body.wizard_page .emails_choose .hrs-mns-wrapper {
	display: flex;
	align-items: center;
	flex: none;
	width: auto;
	clear: none;
	margin: 0;
	gap: 6px;
}
body.wizard_page .emails_choose .dayselect .nice-select,
body.wizard_page .emails_choose .dayselect .hrs-mns-wrapper .nice-select,
body.wizard_page .emails_choose .dayselect select.form-control {
	width: 64px !important;
	min-width: 64px !important;
	max-width: 64px;
	height: 36px;
	line-height: 34px;
	margin: 0 !important;
	flex: none;
	padding-left: 8px;
	padding-right: 22px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	box-sizing: border-box;
}
body.wizard_page .emails_choose .hrs-mns-wrapper > label {
	float: none !important;
	display: inline !important;
	width: auto !important;
	margin: 0;
	font-size: 13px;
	font-weight: 500;
	color: #5A6A80;
	white-space: nowrap;
}
body.wizard_page .emails_choose .sequence_select-wrapper,
body.wizard_page .emails_choose .sequence_select-wrapper .select_container,
body.wizard_page .emails_choose .sequence_select-wrapper .nice-select {
	width: 280px;
	max-width: 100%;
	min-width: 0;
	margin: 0;
}
body.wizard_page .emails_choose .schedule_buttons {
	margin-top: 8px;
	padding-top: 8px;
}

/* 33.5 AI Assistant FAB — clear the 250px sidebar and the footer. */
body.wizard_page .aiassistant-button,
.aiassistant-button {
	left: 266px;
	bottom: 24px;
	height: 36px;
	padding: 0 14px;
	gap: 8px;
	border-radius: 8px;
	background: #101A2B;
	color: #FFFFFF;
	font-size: 13px;
	font-weight: 600;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .12);
	z-index: 40;
}
.aiassistant-button:hover {
	background: #1B283C;
	color: #FFFFFF;
}

@media (max-width: 1024px) {
	.aiassistant-button {
		left: 16px;
		bottom: 16px;
	}
}

/* 33.6 AI Assistant modal — compact composer, not a full-viewport sheet. */
#openai_assistant_modal.showWindow {
	top: 88px;
	right: 28px;
	bottom: auto;
	left: auto;
	width: 420px;
	max-width: calc(100vw - 300px);
	height: auto;
	max-height: calc(100vh - 120px);
	overflow: auto;
	display: block;
	z-index: 999999;
}
#openai_assistant_modal .modal-dialog {
	width: 100%;
	max-width: 100%;
	margin: 0;
}
#openai_assistant_modal .modal-content {
	display: block;
	width: 100%;
	min-height: 0;
	padding: 16px 18px 12px;
	border-radius: 10px;
	background: #FFFFFF;
	box-shadow: 0 10px 28px rgba(16, 26, 43, .16);
}
#openai_assistant_modal .close-modal {
	top: 12px;
	right: 12px;
}
#openai_assistant_modal .modal-content .row h1 {
	margin: 0 0 10px;
	font-size: 18px;
	font-weight: 600;
	line-height: 24px;
	text-align: left;
	color: #101A2B;
}
#openai_assistant_modal .modal-content .row {
	display: block;
}
#openai_assistant_modal .modal-content .row > div {
	margin-bottom: 0;
}
#openai_assistant_modal .openai_assistant_modal_content {
	min-height: 0;
}
#openai_assistant_modal .rd-dash-conversation {
	margin: 0;
	padding: 0;
}
#openai_assistant_modal .rd-dash-conversation-answer {
	width: 100%;
	margin: 0;
	padding: 10px 10px 8px;
	background: #F7F9FB;
	border: 1px solid #E4E7EC;
	border-radius: 8px;
}
#openai_assistant_modal #dashboard-conversation-text {
	min-height: 88px;
	margin-bottom: 8px;
	background: transparent;
	color: #101A2B;
}
#openai_assistant_modal .rd-dash-conversation-answer button,
#openai_assistant_modal .conversation-buttons-group .btn {
	min-height: 32px;
	padding: 4px 10px;
	border-radius: 999px;
	background: #101A2B;
	border-color: #101A2B;
	color: #FFFFFF;
}
#openai_assistant_modal .history-container {
	margin-top: 8px;
	font-size: 13px;
}
#openai_assistant_modal.showWindow + #assign_company_shadow,
#openai_assistant_modal_shadow {
	opacity: .22;
	background: #101A2B;
}

@media (prefers-reduced-motion: reduce) {
	#openai_assistant_modal.showWindow,
	.aiassistant-button {
		transition: none;
	}
}

/* 33.7 Initial Message modal — full-width fields, paperclip on the message, Save in the footer. */
#add_customer_modal:has(.campaign_sms_form) .modal-dialog {
	width: 720px;
	max-width: calc(100vw - 48px);
}
#add_customer_modal:has(.campaign_sms_form) .modal-content {
	padding: 16px 20px 16px;
	border-radius: 10px;
}
#add_customer_modal:has(.campaign_sms_form) .modal-content .row h1 {
	margin: 0 0 12px;
	font-size: 18px;
	font-weight: 600;
	line-height: 24px;
	text-align: left;
	color: #101A2B;
}
#add_customer_modal:has(.campaign_sms_form) .modal-content .row {
	display: block;
	margin: 0;
}
#add_customer_modal:has(.campaign_sms_form) .modal-content .row > div {
	margin-bottom: 0;
}
#add_customer_modal:has(.campaign_sms_form) .modal-content .row label {
	position: static;
	top: auto;
	background: transparent;
	margin: 0 0 4px;
	padding: 0;
	font-size: 13px;
	font-weight: 600;
	color: #35435A;
}
#add_customer_modal:has(.campaign_sms_form) .close-modal {
	top: 12px;
	right: 12px;
}
#add_customer_modal:has(.campaign_sms_form) .add_customer_messagemodal_content {
	padding: 0;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .adminform_table {
	max-width: none;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .form-group {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 6px;
	padding: 8px 0;
	border-bottom: 0;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .form-group > div:first-child:has(label:empty) {
	display: none;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .form-group > div:first-child {
	padding-top: 0;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form input[type="text"],
#add_customer_modal:has(.campaign_sms_form) .adminform_form select,
#add_customer_modal:has(.campaign_sms_form) .adminform_form textarea,
#add_customer_modal:has(.campaign_sms_form) .adminform_form .form-control,
#add_customer_modal:has(.campaign_sms_form) .adminform_form .nice-select,
#add_customer_modal:has(.campaign_sms_form) .adminform_form .tox-tinymce {
	width: 100%;
	max-width: 100%;
	min-width: 0;
	box-sizing: border-box;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .nice-select {
	height: 36px;
	line-height: 34px;
}
#add_customer_modal:has(.campaign_sms_form) .form-group:has(.attachment-icon) {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	margin-top: -40px;
	padding: 0 8px 0 0;
	min-height: 0;
	border: 0;
	pointer-events: none;
	z-index: 3;
}
#add_customer_modal:has(.campaign_sms_form) .attachment-icon {
	pointer-events: auto;
	float: none;
	position: relative;
	top: 0;
	margin: 0;
	color: #35435A;
}
#add_customer_modal:has(.campaign_sms_form) .attachment-icon:hover {
	color: #17803D;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .adminform_savebutton {
	max-width: none;
	display: flex;
	justify-content: flex-end;
	margin: 12px 0 0;
	padding: 12px 0 0;
	border-top: 1px solid #E4E7EC;
}
#add_customer_modal:has(.campaign_sms_form) .adminform_form .adminform_savebutton input {
	float: none;
}

@media (max-width: 767px) {
	#openai_assistant_modal.showWindow {
		left: 12px;
		right: 12px;
		width: auto;
		max-width: none;
	}
	body.wizard_page .emails_choose .dayselect {
		flex-wrap: wrap;
	}
}

/* ==========================================================================================
   34. PAGE RHYTHM — Deals, catalog, identity admin, reports, Home coming-up
   ------------------------------------------------------------------------------------------
   Duplicate chrome buttons (Pipeline view / Configure pipelines) are gone; these rules keep
   the remaining title + primary action + filter bar on one metric. Reports were inheriting
   the dashboard grey slab. The Home coming-up card was a 420px stack inside a full-width
   panel, which left a blank field to the right of three zero rows.
   ========================================================================================== */

body.deals .additional-buttons-section,
body.lineitems .additional-buttons-section,
body.companiesmgmt .additional-buttons-section,
body.workspaces .additional-buttons-section,
body.ai .additional-buttons-section,
body.triggers .additional-buttons-section,
body.workflow .additional-buttons-section,
body.library .additional-buttons-section,
body.powerdialer .additional-buttons-section,
body.customers .additional-buttons-section,
body.customers_list_section .additional-buttons-section,
body.customers_pipeline_view .additional-buttons-section {
	margin-bottom: 12px;
}
body.deals .deal-toolbar-form,
body.deals .total_values_info {
	margin-top: 0;
	margin-bottom: 12px;
}
body.deals .deal-list-wrap,
body.lineitems .tablewrapper,
body.lineitems .ct-list-wrap,
body.lineitems .li-intro,
body.companiesmgmt .tablewrapper,
body.workspaces .tablewrapper {
	margin-top: 0;
}
body.lineitems .li-intro {
	margin-bottom: 12px;
}

body.dashboard_home.platformstats,
body.dashboard_home.platformstats section.content,
body.dashboard_home.platformstats .block,
body.dashboard_home.platformstats .body-wrapper,
body.dashboard_home.platformstats .block-content-outer,
body.dashboard_home.platformstats .panel,
body.dashboard_home.platformstats .panel-body,
body.dashboard_home.platformstats .daylistats,
body.activity,
body.activity section.content,
body.activity .block,
body.activity .body-wrapper,
body.activity .block-content-outer,
body.activity .panel,
body.activity .panel-body {
	background: #FFFFFF;
}

/* Compact strip: stats on the left, next/empty on the right. Height follows content so
   an empty calendar no longer leaves a blank field under three zero rows. */
body.dashboard_home:not(.platformstats) .up-widget {
	max-width: none;
	width: 100%;
	height: auto;
	min-height: 0;
	display: grid;
	grid-template-columns: minmax(220px, 280px) minmax(0, 1fr);
	gap: 10px 28px;
	align-items: start;
	align-content: start;
	padding: 12px 16px;
	margin: 0 0 16px;
	border: 1px solid #EAECEF;
}
body.dashboard_home:not(.platformstats) .up-head {
	grid-column: 1 / -1;
	margin: 0 0 2px;
}
body.dashboard_home:not(.platformstats) .up-stats {
	flex-direction: row;
	gap: 8px;
	margin: 0;
}
body.dashboard_home:not(.platformstats) .up-stat {
	flex: 1 1 0;
	min-width: 0;
	padding: 6px 10px;
}
body.dashboard_home:not(.platformstats) .up-stat b { font-size: 16px; }
body.dashboard_home:not(.platformstats) .up-list,
body.dashboard_home:not(.platformstats) .up-empty {
	margin: 0;
	padding: 4px 0 0;
	border: 0;
	align-self: center;
}
body.dashboard_home:not(.platformstats) .up-empty {
	line-height: 1.3;
	color: #7C8AA0;
	font-size: 13px;
}
body.dashboard_home:not(.platformstats) .up-list li { padding: 4px 0; }

@media (max-width: 767px) {
	body.dashboard_home:not(.platformstats) .up-widget {
		grid-template-columns: 1fr;
	}
}

/* ==========================================================================================
   35. UX AUDIT WAVE 1 — the CSS-side defects
   ------------------------------------------------------------------------------------------
   docs/UX-AUDIT-AND-IMPLEMENTATION-PLAN.md, findings D1, D5, D7, D9, D11, D12. Every selector
   below was read off the live DOM at 1440x900 before it was written, because the fix this
   file already carried for D4 had never applied: it was authored against class names that do
   not exist in the markup.
   ========================================================================================== */

/* 35.1 D1 — THE NAV RAIL GIVES NO SIGN THAT IT CONTINUES.
   ------------------------------------------------------------------------------------------
   A CORRECTION TO THE AUDIT. D1 reports Calendar, Support and Projects as UNREACHABLE at
   1440x720. They are below the fold -- measured, the last row's bottom is y=828 against a
   720px viewport -- but the rail does scroll: `.navigation` has carried
   `overflow-y:auto; height:100vh` since stylesheets.css:796, its scrollHeight is 838 against
   a clientHeight of 720, and driving scrollTop to 118 brings Projects fully into view and
   hit-testable. So `overflow-y:auto` is not the fix; it is already there.

   What is actually missing is the AFFORDANCE. styles/style.css:1032 sets
   `::-webkit-scrollbar{width:0}` globally and unscoped -- section 4.6 restored a scrollbar on
   `.content` and nowhere else -- so the rail's scrollbar measures 0px wide and the list looks
   finished at fourteen items. Nothing tells the user there are three more.

   `.h-100-100` (stylesheets.css:793) is the second half of it: `height: calc(100% - 100px)`
   is 620px at a 720 viewport while the list inside it is 772px tall, so the list paints
   outside its own container and the column's height describes nothing. */
aside.navigation {
	overscroll-behavior: contain;
	scrollbar-width: thin;
	scrollbar-color: #33415C transparent;
}

aside.navigation::-webkit-scrollbar { width: 8px; }
aside.navigation::-webkit-scrollbar-track { background: transparent; }
aside.navigation::-webkit-scrollbar-thumb { background: #33415C; border-radius: 4px; }
aside.navigation::-webkit-scrollbar-thumb:hover { background: #47587A; }

.navigation nav > .flex.flex-column.h-100-100 {
	/* A flex child refuses to shrink below its content without this, which is why the rule
	   is stated even though the container it lives in is a block. */
	min-height: 0;
	height: auto;
}

/* The rail is 17 rows of 40px and will outgrow any laptop. A runway under the last item
   means the final row is never flush against the viewport edge, which is what makes a
   scrollable list read as scrollable. */
.luna-nav.nav {
	padding-bottom: 20px;
}

/* 35.2 D5 — "NOTHING FOUND" PAINTED NOTHING, ON EVERY SELECTABLE LIST.
   ------------------------------------------------------------------------------------------
   Root cause and its fix are in admin-table.css, next to the shim that caused it. This is
   the second half: the message was never designed, only emitted. Grid::SingleLineLabel()
   (includes/PB/UI/Grid.php:266) writes it into the first column of all 68 grid modules, so
   there is exactly one place to style it and it covers the whole app.

   The Clear-filters action is appended by ui-affordances.js, and only when the URL actually
   carries a filter -- "no matches" and "nothing created yet" are different states and only
   one of them has something to clear. */
/* Specificity, not load order: section 19 already carries
   `table.admintable.table > tbody > tr > td[colspan] { padding: 34px 16px }`, which a bare
   `table.admintable td[colspan]` loses to however late this file loads. */
table.admintable.table > tbody > tr > td[colspan]:not([colspan="1"]),
table.admintable td[colspan]:not([colspan="1"]) {
	padding: 40px 24px 44px;
	text-align: center;
	vertical-align: middle;
	font-size: var(--fs-base);
	font-weight: 500;
	color: var(--text-muted);
	background: var(--surface);
}

table.admintable > tbody > tr > td[colspan]:not([colspan="1"]):first-child {
	color: var(--text-muted);
}

table.admintable td[colspan]:not([colspan="1"])::before {
	content: "";
	display: block;
	width: 40px;
	height: 40px;
	margin: 0 auto 14px;
	border-radius: 50%;
	background: var(--surface-mute) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%237C8AA0' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.35-4.35'/%3E%3C/svg%3E") center no-repeat;
}

/* flex + auto margins rather than inline-flex: the message is a bare text node and the two
   would otherwise share a line in a 1640px cell. */
table.admintable td[colspan]:not([colspan="1"]) .es-clear {
	display: flex;
	align-items: center;
	width: -moz-fit-content;
	width: fit-content;
	margin: 16px auto 0;
}

/* 35.3 D7 — STATUS AND ASSIGNED USER ARE OFF-SCREEN IN THE TICKET QUEUE.
   ------------------------------------------------------------------------------------------
   Measured: table.admintable scrollWidth 1888px inside .table-responsive clientWidth 1149px
   -- 739px of columns clipped. ASSIGNED USER runs 1325->1466 and STATUS 1466->1556, entirely
   past the right edge, and `document.documentElement` reports zero horizontal overflow
   because section.content is `overflow-x:hidden`, so the page gives no cue at all. The two
   fields an agent triages on are the two they cannot see, and Status is where the inline
   status editor lives.

   Column definitions are in support.php and are not touched. This is a width budget: CLIENT
   was given 200px and SUBJECT 99px, so "QA Test Email Subject" wrapped to three lines while
   a name sat in double the space it needed. Reversing that alone brings Assigned User and
   Status inside 1149px. */
body.support_list .admintable,
body.support_dashboard .admintable {
	/* Percentages against a fixed-layout table, which is what fixed layout is for. `width: auto`
	   was tried and does not work: Chrome still runs the automatic algorithm to SIZE a
	   fixed-layout table -- measured 1999px against a 1556px budget -- and then redistributes
	   the surplus, so the budget had no effect on anything but Subject.

	   min-width sets the table to 1360px inside a 1149px column. Sixteen columns squeezed into
	   1149 is legible to nobody: Subject came out at 40px and six headers ellipsised. At 1360
	   the eleven columns through STATUS occupy 1019px and sit inside the fold, and the four
	   trailing informational ones are 211px of visible scroll away. */
	table-layout: fixed;
	width: 100%;
	min-width: 1360px;
}

body.support_list .admintable th,
body.support_list .admintable td,
body.support_dashboard .admintable th,
body.support_dashboard .admintable td {
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Sixteen columns do not fit a laptop at a comfortable width, so this is a ranking, not a
   rescue: SUBJECT goes 99px -> ~157px with the width CLIENT was wasting on a name (200px ->
   ~83px), and ASSIGNED USER and STATUS -- the two fields an agent triages on, and both of
   which used to start past x=1325 -- come inside the fold. The four trailing informational
   columns take the squeeze. Every th already carries a `title`, so an ellipsis still names
   its column. */
body.support_list .admintable .table-chk1,
body.support_dashboard .admintable .table-chk1                      { width: 3.4%; }
body.support_list .admintable .table-id,
body.support_dashboard .admintable .table-id                        { width: 6.8%; }
body.support_list .admintable .table-subject,
body.support_dashboard .admintable .table-subject                   { width: 13.7%; }
body.support_list .admintable .table-priority,
body.support_dashboard .admintable .table-priority                  { width: 5.6%; }
body.support_list .admintable .table-client,
body.support_dashboard .admintable .table-client                    { width: 7.2%; }
body.support_list .admintable .table-organization,
body.support_dashboard .admintable .table-organization              { width: 6.4%; }
body.support_list .admintable .table-department,
body.support_dashboard .admintable .table-department                { width: 6.4%; }
body.support_list .admintable .table-date,
body.support_dashboard .admintable .table-date                      { width: 6.0%; }
body.support_list .admintable .table-duedate,
body.support_dashboard .admintable .table-duedate                   { width: 5.6%; }
body.support_list .admintable .table-user,
body.support_dashboard .admintable .table-user                      { width: 7.4%; }
body.support_list .admintable .table-status,
body.support_dashboard .admintable .table-status                    { width: 6.4%; }
body.support_list .admintable .table-tags,
body.support_dashboard .admintable .table-tags                      { width: 4.8%; }
body.support_list .admintable .table-time_spent,
body.support_dashboard .admintable .table-time_spent                { width: 4.2%; }
body.support_list .admintable .table-last_updated_at,
body.support_dashboard .admintable .table-last_updated_at           { width: 5.8%; }
body.support_list .admintable .table-updated_by,
body.support_dashboard .admintable .table-updated_by                { width: 4.8%; }
body.support_list .admintable .table-action_links,
body.support_dashboard .admintable .table-action_links              { width: 5.5%; }

/* Wrapping is what a subject needs and a date does not. Two lines, then an ellipsis: "QA Test
   Email Subject" used to take three in a 99px column. */
body.support_list .admintable .at-cell-subject,
body.support_dashboard .admintable .at-cell-subject {
	/* No -webkit-box line clamp here: it replaces `display: table-cell` and drops the cell out
	   of the table's column sizing entirely -- the subject rendered 40px wide inside a 186px
	   column. */
	white-space: normal;
	overflow: hidden;
}

/* Where the table still exceeds its column, the scroll must be visible -- the global
   `::-webkit-scrollbar{width:0}` is why 739px of clipped columns had no cue whatsoever. */
.table-responsive {
	scrollbar-width: thin;
	scrollbar-color: #C4CBD6 transparent;
}
.table-responsive::-webkit-scrollbar { height: 10px; }
.table-responsive::-webkit-scrollbar-track { background: var(--surface-mute); border-radius: 5px; }
.table-responsive::-webkit-scrollbar-thumb { background: #C4CBD6; border-radius: 5px; }
.table-responsive::-webkit-scrollbar-thumb:hover { background: #A9B3C2; }

/* The columns chooser is a genuinely good control -- drag to reorder, per-user persistence,
   Reset and Apply -- reached through a 34x34 div with no label, no title and no aria-label.
   It now says what it is. */
.table-columns-wrapper .icon-button.has-label {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	width: auto;
	min-height: 34px;
	padding: 0 12px;
	border: 1px solid var(--line-strong);
	border-radius: 7px;
	background: var(--surface);
	color: var(--ink-2);
	cursor: pointer;
}

.table-columns-wrapper .icon-button.has-label:hover {
	background: var(--surface-alt);
	border-color: #C7D0DB;
	color: var(--ink);
}

.icon-button-label {
	font-size: var(--fs-md);
	font-weight: 600;
	white-space: nowrap;
}

/* The panel's list is 350px tall over 500px of content and DOES scroll -- but with a 0px
   scrollbar it simply looked as though the product had ten columns rather than fourteen.
   Measured: Status, Tags, Time Spent, Last Updated At and Updated By were all below the fold
   of a control whose whole purpose is reaching them. */
.table-columns .sortable-list {
	scrollbar-width: thin;
	scrollbar-color: #C4CBD6 transparent;
	overscroll-behavior: contain;
	border-bottom: 1px solid var(--line);
	margin-bottom: 10px;
}
.table-columns .sortable-list::-webkit-scrollbar { width: 8px; }
.table-columns .sortable-list::-webkit-scrollbar-track { background: transparent; }
.table-columns .sortable-list::-webkit-scrollbar-thumb { background: #C4CBD6; border-radius: 4px; }
.table-columns .sortable-list::-webkit-scrollbar-thumb:hover { background: #A9B3C2; }

.table-columns .sortable-list .column-item {
	min-height: 26px;
	align-items: center;
	gap: 8px;
}

/* 35.4 D9 — CONTRAST, FOCUS, AND HIT AREA.
   ------------------------------------------------------------------------------------------
   The fill is dealt with in section 9.2 and in admin-buttons.css.

   FOCUS. Measured across the queue screens, EVERY focused element computes
   `outline-style:none` -- 108 tabbables on the Support list alone -- and the one substitute
   in the app is a 16%-alpha orange box-shadow on an off-white page. There is no keyboard path
   through the product. This is a single universal rule on purpose: an allowlist of components
   is how the next new control ends up invisible again. */
:is(a, button, input, select, textarea, summary,
    [tabindex], [role="button"],
    .ab-button, .btn, .icon-button, .dropdown-toggle):focus-visible,
:focus-visible {
	outline: var(--focus-ring);
	outline-offset: 2px;
}

/* Two exceptions, both because a 2px ring 2px outside the element would be clipped or would
   sit on the wrong ground. */
.navigation :is(a, [tabindex]):focus-visible,
.navigation :focus-visible {
	outline-color: var(--accent);
}

.admintable :is(a, input, [tabindex]):focus-visible,
.table-responsive :is(a, input, [tabindex]):focus-visible {
	outline: var(--focus-ring);
	outline-offset: -1px;
}

input[type="submit"]:focus-visible,
button[type="submit"]:focus-visible,
.ab-button:focus-visible {
	outline: var(--focus-ring);
	outline-offset: 2px;
	box-shadow: none;
}

.form-control:focus-visible,
textarea.form-control:focus-visible,
select.form-control:focus-visible {
	outline: var(--focus-ring);
	outline-offset: 0;
	border-color: var(--ink);
	box-shadow: none;
}

/* HIT AREA. WCAG 2.5.8 asks for 24x24. Measured: 67 targets under it on the Support list, 25
   on ticket detail. The glyph size is deliberately left alone -- these are dense tables and
   18px icons are the right size; it is the box around them that was missing. Padding, not
   width, so nothing reflows. */
td.at-cell-action_links a,
.action_links a,
.action_links div,
a.row-peek,
.customer-additional-info .flex-item > a,
.kb-search > a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 24px;
	min-height: 24px;
	padding: 3px;
	border-radius: var(--r-sm);
}

td.at-cell-action_links a:hover,
.action_links a:hover,
a.row-peek:hover {
	background: var(--surface-mute);
}

/* The grid's own checkboxes measured 13x13 with no padding to grow into; the cell has room. */
.admintable input[type="checkbox"],
.table-columns input[type="checkbox"] {
	width: 16px;
	height: 16px;
}

.admintable td.at-cell-chk1,
.admintable th.table-chk1 {
	padding-left: 14px;
	padding-right: 14px;
}

/* A control that is keyboard-focusable must also be keyboard-operable; the columns trigger is
   a div with role=button, and ui-affordances.js supplies Enter/Space. */
[role="button"][tabindex] {
	cursor: pointer;
}

/* 35.5 D11 — BOARDS AND RAILS CLIPPED WITH NO SCROLL AFFORDANCE.
   ------------------------------------------------------------------------------------------
   Measured at a 1440 viewport:
     .li-pipeline            scrollWidth 1630 / clientWidth 1149 -- 481px lost, and the two
                             columns off the end are `Lost` (where deals go to be reviewed)
                             and `Customstage` (which holds a live deal)
     .draggable-wrapper.flex scrollWidth 1874 / clientWidth 1169 -- 705px lost

   On macOS an `overflow-x:auto` scrollbar is invisible at rest, so the board looked finished
   at four columns. `scroll` rather than `auto`, plus an edge mask, plus columns that flex so
   all six stages fit inside 1149px instead of four.

   The third surface D11 lists, the m=customerdetails right rail, turned out to be something
   else -- see below. */
.li-pipeline {
	overflow-x: scroll;
	scrollbar-width: thin;
	scrollbar-color: #C4CBD6 transparent;
	overscroll-behavior-x: contain;
	/* The mask is the resting cue: content fading under the right edge reads as "there is
	   more" without waiting for a hover or a scroll event. It is removed once the board is
	   scrolled to its end. */
	-webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 44px), transparent 100%);
	mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 44px), transparent 100%);
}

.li-pipeline::-webkit-scrollbar { height: 10px; }
.li-pipeline::-webkit-scrollbar-track { background: var(--surface-mute); border-radius: 5px; }
.li-pipeline::-webkit-scrollbar-thumb { background: #C4CBD6; border-radius: 5px; }
.li-pipeline::-webkit-scrollbar-thumb:hover { background: #A9B3C2; }

.li-pipeline .li-pipe-col {
	flex: 1 1 200px;
	min-width: 200px;
	max-width: 260px;
}

.draggable-wrapper.flex {
	overflow-x: scroll;
	scrollbar-width: thin;
	scrollbar-color: #C4CBD6 transparent;
	overscroll-behavior-x: contain;
	-webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 44px), transparent 100%);
	mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 44px), transparent 100%);
}

.draggable-wrapper.flex::-webkit-scrollbar { height: 10px; }
.draggable-wrapper.flex::-webkit-scrollbar-track { background: var(--surface-mute); border-radius: 5px; }
.draggable-wrapper.flex::-webkit-scrollbar-thumb { background: #C4CBD6; border-radius: 5px; }

/* A CORRECTION TO THE AUDIT. D11 reports the m=customerdetails right rail as "clipped 319px
   past the viewport and not scrollable at all". It is neither. `.customerdetails_dropdown`
   (contacts/details.css:316) is a SLIDE-IN DRAWER: `position:absolute; right:45px;
   margin-right:-410px; width:410px; overflow-y:auto`, revealed by
   `.show { right: 395px }` from customerdetails_dropdown.js. Parked, it sits deliberately
   outside the content column with a 45px sliver on the column edge holding the chevron
   handle; opened, it lands at x=1019..1429 and fits a 1440 viewport with room to spare. It
   scrolls, and the 319px is where a closed drawer is supposed to be.

   The real defect is what renders in that 45px sliver. The accordion rows are inside the
   drawer and left-aligned, so the parked state showed the first letter of each of them --
   V, T, P, T against the screen edge, which is what the audit saw and reasonably read as an
   amputated panel. Only the handle belongs in the sliver. */
.customerdetails_dropdown:not(.show) .dropdown_item,
.customerdetails_dropdown:not(.show) .dropdown_content {
	visibility: hidden;
}

/* The sliver now needs to read as a drawer edge rather than as a panel that stops. */
.customerdetails_dropdown {
	border-left: 1px solid var(--line);
	box-shadow: var(--sh-2);
}

.customerdetails_dropdown .right_sidebar_toogle {
	position: relative;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: flex-start;
	min-height: 28px;
	cursor: pointer;
}

/* 35.6 D12 — DESTRUCTIVE ACTIONS LOOK EXACTLY LIKE ROUTINE ONES.
   ------------------------------------------------------------------------------------------
   `.deal-list td.row-actions { opacity: 0 }` (section 14) hid Delete entirely until the row
   was hovered, and `.ra-danger` carried only a `:hover` rule -- so at rest Delete computed to
   rgb(71,86,106), pixel-identical to Edit, and stayed that way until the pointer was on the
   link itself. Two steps of discovery to find out which one destroys the record.

   0.55 rather than 0: the actions are legible at rest and resolve on hover, so the column no
   longer appears empty, and the width still never changes as the pointer moves down.

   Extended to .ct-list (Contacts) alongside .deal-list -- same reasoning, same fix, added
   when Contacts gained its own row-level Delete. */
.deal-list td.row-actions,
.ct-list td.row-actions {
	opacity: .55;
}

.deal-list td.row-actions a.ra-danger,
.ct-list td.row-actions a.ra-danger,
.deal-list td.row-actions button.ra-danger,
.ct-list td.row-actions button.ra-danger {
	color: var(--danger);
}

.deal-list td.row-actions a.ra-danger:hover,
.ct-list td.row-actions a.ra-danger:hover,
.deal-list td.row-actions button.ra-danger:hover,
.ct-list td.row-actions button.ra-danger:hover {
	background: var(--danger-tint);
	color: var(--danger);
}

/* The same distinction in the shared grid, where Delete is a 30x30 trash icon sitting beside
   a 30x30 pencil in the same slate. Selected on the URL it posts to, which is what actually
   distinguishes them in the markup -- there is no class. */
td.at-cell-action_links a[onclick*="postdelete"],
.action_links a[onclick*="postdelete"],
.action_links a[href*="d=delete"] {
	color: var(--danger);
}

td.at-cell-action_links a[onclick*="postdelete"]:hover,
.action_links a[onclick*="postdelete"]:hover,
.action_links a[href*="d=delete"]:hover {
	background: var(--danger-tint);
	color: var(--danger);
}

/* Platform stats / dashboard period sentence (lifted from template inline blocks). */
.flex-important {
	display: flex !important;
}

.platformstats .stats-period,
.dashboard_home .dash-period {
	margin: 0 0 18px;
	color: var(--text-muted);
}

.platformstats .stats-period strong,
.dashboard_home .dash-period strong {
	color: var(--ink);
}

/* Reports > Overview header line: period sentence left, range right (owner 2026-10-07). */
.platformstats .stats-head {
	display: flex;
	width: 100%;
	box-sizing: border-box;
	align-items: center;
	justify-content: space-between;
	gap: 8px 16px;
	flex-wrap: wrap;
	margin: 0 0 16px;
}
.platformstats .stats-head .stats-period { margin: 0; }
.platformstats .stats-range { display: flex; align-items: center; gap: 2px; margin: 0; padding: 0; list-style: none; }
.platformstats .stats-range li { padding: 0; }
.platformstats .stats-range li > a,
.platformstats .stats-range .dropdown > a { display: inline-block; padding: 6px 10px; color: var(--ink); border-bottom: 2px solid transparent; text-decoration: none; }
.platformstats .stats-range li.active > a { border-bottom-color: var(--ink); font-weight: 600; }
.platformstats .stats-range li > a:hover { color: var(--ink); border-bottom-color: var(--line, #E3E8EF); }

.platformstats td.dash-empty {
	padding: 22px 16px;
	color: var(--text-muted);
}

/* Deal board / pipeline headings (lifted from template inline blocks). */
.board-head {
	margin: 0 0 10px;
}

.board-title {
	margin: 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--ink);
}

.board-sub {
	margin: 2px 0 0;
	color: var(--text-muted);
}

/* Inbox headings (lifted from template inline blocks). */
.inbox-head {
	margin: 0 0 12px;
}

.inbox-head h2 {
	margin: 0;
	font-size: 18px;
	font-weight: 600;
	line-height: 24px;
}

.inbox-head p {
	margin: 2px 0 0;
	color: var(--text-muted);
}

/* Organization / company heading (lifted from template inline blocks). */
.company-details-wrapper .company-name {
	font-size: 18px;
	font-weight: 600;
	line-height: 24px;
	margin: 0 0 10px;
}

/* ==========================================================================================
   36. CONTACT DETAIL PAGE (m=customerdetails) -- profile header redesign
   ------------------------------------------------------------------------------------------
   Owner brief 2026-09-03: "improve this page UI this is so outdated". Measured before
   touching anything: the whole header sat directly on the page's flat #F2F2F2 wash with no
   card boundary at all; the name printed at 18px, the same weight class as its own field
   labels; the key-facts block was `grid-auto-flow:column` (column-major reading order) inside
   `max-width:calc(100% - 408px)` -- a reserve for `.customerdetails_dropdown`, which is
   `position:absolute` and does not participate in flow, so the 408px was pure dead width and
   the Address cell wrapped to three lines in the space that was left. Stage and Status were
   plain text links indistinguishable from static facts like Location, though they are the two
   fields on the page an update actually changes. Three stat tiles (150x80 each) sat in an
   otherwise-empty row with ~675px of unused width to their right.

   Two class hooks were added to customerdetails.tpl for this pass, both additive (no Smarty
   logic touched): `fi-pill`/`fi-stage`/`fi-status` on the Stage and Status flex-items, and
   `fi-address` on Address. Everything else below targets markup that already existed.
   ========================================================================================== */

/* 36.1 The header becomes a real card instead of floating on the page wash. */
.customer-details-wrapper {
	padding: 28px 28px 32px 28px;
}

.profile-section {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-lg);
	box-shadow: var(--sh-1);
	padding: 28px 32px;
	white-space: normal;
}

/* 36.2 Avatar -- same navy mark, a hairline ring so it reads as a deliberate mark rather
   than a flat fill butting straight into the card's white background. */
.profile-section .customer-icon {
	box-shadow: 0 0 0 3px var(--surface-alt);
}

/* 36.3 The name was the same 18px/600 as a field label three lines below it. It is the
   record's own name -- give it the weight an h2 gets everywhere else in the app. */
.profile-section h4 {
	font-size: 22px;
	font-weight: 700;
	line-height: 1.25;
	color: var(--ink);
	letter-spacing: -.01em;
}

/* 36.4 Phone / email: the bare "|" (contacts/details.css:76-80) read as a stray character
   at this size. A middle dot at reduced opacity reads as a deliberate separator instead. */
.profile-section .customer-phone,
.profile-section .customer-email {
	color: var(--text);
	font-size: var(--fs-base);
}
.profile-section .customer-phone::after {
	content: '\00b7';
	color: var(--text-faint);
	padding: 0 .6rem;
	font-weight: 700;
}

/* 36.5 Action icons (Call / Email / Message / Campaign / Task / Edit) had no interactive
   affordance at rest -- a plain colored glyph with nothing to signal "button". A circular
   hover/focus tint, sized to the WCAG 24x24 floor, makes the row read as controls. */
.profile-section .main_buttons {
	margin-top: 14px;
}
.profile-section .main_buttons > div {
	display: flex;
	align-items: center;
	gap: 4px;
}
.profile-section .main_buttons a.profile-btn-follow {
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 36px;
	min-height: 36px;
	border-radius: var(--r-pill);
	transition: background-color .12s ease;
}
.profile-section .main_buttons a.profile-btn-follow:hover,
.profile-section .main_buttons a.profile-btn-follow:focus-visible {
	background: var(--surface-mute);
}
.profile-section .main_buttons a.profile-btn-follow:focus-visible {
	outline: var(--focus-ring);
	outline-offset: 1px;
}

/* 36.6 The 3-dot menu was a bare 20x17 svg with no hit-area padding and no hover state --
   the smallest target on the page guarding the row's only destructive action (Delete). */
.profile-section #menuEditCustomer {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--r-md);
	color: var(--text-muted);
	transition: background-color .12s ease;
}
.profile-section #menuEditCustomer:hover,
.profile-section #menuEditCustomer:focus-visible {
	background: var(--surface-mute);
	color: var(--ink);
}
.profile-section #menuEditCustomer:hover svg path,
.profile-section #menuEditCustomer:focus-visible svg path {
	fill: currentColor;
	stroke: currentColor;
}
.profile-section #menuEditCustomer:focus-visible {
	outline: var(--focus-ring);
	outline-offset: 1px;
}
.profile-section .dropdown-menu {
	border: 1px solid var(--line);
	border-radius: var(--r-md);
	box-shadow: var(--sh-2);
	padding: 6px;
	min-width: 220px;
}
.profile-section .dropdown-menu .dropdown-item {
	border-radius: var(--r-sm);
	padding: 8px 10px;
	font-size: var(--fs-base);
	color: var(--ink-2);
}
.profile-section .dropdown-menu .dropdown-item:hover {
	background: var(--surface-mute);
}
/* Delete sat in the same list, same weight, same color as "Schedule Video Call" -- the D12
   distinction (a destructive action should not look identical to a routine one) applied to
   this menu too. A hairline divider separates it from the routine actions above it. */
.profile-section .dropdown-menu .dropdown-item-danger {
	color: var(--danger);
	margin-top: 6px;
	border-top: 1px solid var(--line);
	border-radius: 0 0 var(--r-sm) var(--r-sm);
	padding-top: 10px;
}
.profile-section .dropdown-menu .dropdown-item-danger:hover {
	background: var(--danger-tint);
}

/* 36.7 Key facts -- the header's second-highest-impact fix. Was `grid-auto-flow:column`
   (column-major: Company/Title read top-to-bottom before Location/Stage even start) inside a
   `max-width:calc(100% - 408px)` reserve that bought nothing (the drawer it reserved space
   for is `position:absolute`, confirmed in section 35's own note on this same page). Row-major
   auto-fill reads left-to-right, top-to-bottom -- the order a person actually scans a form --
   and the freed width is what stops Address wrapping to three lines.

   `.customer-additional-info` is not `.profile-section`'s direct child -- it is a FLEX ITEM
   inside `.customer-info-section.flex`, alongside the avatar and the name/phone/buttons
   column. First pass fixed the grid itself but left it squeezed into whatever width that row
   had left over, which is how Stage/Status/Estimated Close Date ended up rendered 150-350px
   past the viewport edge rather than missing -- `auto-fill` had already claimed a correct
   5-column layout for the ~862px it was actually given. `flex-wrap:wrap` + `flex-basis:100%`
   drops it onto its own full-width row below the identity block instead. */
.profile-section .customer-info-section {
	flex-wrap: wrap;
}
.profile-section .customer-additional-info {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	grid-auto-flow: row;
	grid-template-rows: unset;
	column-gap: 28px;
	row-gap: 20px;
	flex: 1 1 100%;
	max-width: 100%;
	margin-top: 24px;
	padding-top: 24px;
	border-top: 1px solid var(--line);
}
.profile-section .flex-item {
	padding-left: 0;
}
.profile-section .flex-item div {
	white-space: normal;
}

/* Label demoted below the value it describes -- both rendered at the same 14px/600 before,
   so nothing on the page told a value from its own caption at a glance. */
.profile-section .flex-item h5 {
	font-size: var(--fs-xs);
	font-weight: 600;
	color: var(--text-muted);
	text-transform: uppercase;
	letter-spacing: .04em;
	margin-bottom: 6px;
}
.profile-section .flex-item > div,
.profile-section .flex-item > a {
	font-size: var(--fs-base);
	font-weight: 500;
	color: var(--ink-2);
}
.profile-section .flex-item > a[href]:not(.fi-pill-value):not(.fi-pill-chevron) {
	color: var(--ink-2);
	text-decoration: none;
}
.profile-section .flex-item > a[href]:not(.fi-pill-value):not(.fi-pill-chevron):hover {
	color: var(--accent-text);
}

/* Address is prose, not a fact -- give it room and a readable measure instead of forcing it
   into the same narrow column as "Title". */
.profile-section .fi-address {
	grid-column: span 2;
	max-width: 42ch;
}

/* 36.8 Stage and Status are the two fields a real edit changes; every other cell here is a
   static fact. A pill marks that difference instead of leaving all seven fields at one
   visual weight -- the chevron (already the changeStatus() trigger) sits inside it rather
   than floating as a second, disconnected control. */
.profile-section .fi-pill h5 { margin-bottom: 8px; }
/* Was flex-direction:column on the container: h5, the value link and the chevron link are
   three block-level siblings in source order, so a column flex stacked all three -- chevron
   under the pill, not beside it. h5 stays a normal block (its own line); the value and
   chevron are inline-flex, so they sit on the same line together right after it. */
.profile-section .fi-pill-value {
	display: inline-flex;
	align-items: center;
	vertical-align: middle;
	padding: 4px 12px;
	border-radius: var(--r-pill);
	background: var(--surface-mute);
	color: var(--ink-2) !important;
	font-size: var(--fs-sm);
	font-weight: 600;
	text-decoration: none !important;
	max-width: 100%;
}
.profile-section .fi-status .fi-pill-value {
	background: var(--accent-tint);
	color: var(--accent-text) !important;
}
.profile-section .fi-pill-value:hover {
	filter: brightness(.96);
}
.profile-section .fi-pill-chevron {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	vertical-align: middle;
	width: 22px;
	height: 22px;
	margin-left: 4px;
	border-radius: var(--r-sm);
}
.profile-section .fi-pill-chevron:hover,
.profile-section .fi-pill-chevron:focus-visible {
	background: var(--surface-mute);
}

/* 36.9 Stat tiles -- three 150x80 cards in an otherwise-empty row (measured: ~675px of
   1149px unused to their right at 1440). Grow to fill the row up to a sane cap instead of
   sitting fixed-width in dead space, and read as a small stat (value large, label small)
   rather than a list row (both 14px, per contacts/details.css:98-108). */
.customer-info {
	margin-top: 20px;
}
.customer-info .info-item {
	flex: 1 1 220px;
	max-width: 280px;
	height: auto;
	min-height: 84px;
	border: 1px solid var(--line);
	box-shadow: none;
	align-items: center;
}
.customer-info .info-item h5 {
	font-size: var(--fs-xs);
	font-weight: 600;
	color: var(--text-muted);
	text-transform: uppercase;
	letter-spacing: .04em;
	margin-bottom: 4px;
}
.customer-info .info-item .nowrap,
.customer-info .info-item > .pl-2 > div:not(h5) {
	font-size: 20px;
	font-weight: 700;
	color: var(--ink);
	line-height: 1.2;
}

/* 36.10 Tags -- old Bootstrap .label pills restyled to the app's own chip language rather
   than the framework default (sharp corners, saturated fill, no border). */
.customer-side-info-tags {
	margin-top: 20px;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.customer-side-info-tags .label {
	display: inline-flex;
	align-items: center;
	padding: 4px 12px;
	border-radius: var(--r-pill);
	font-size: var(--fs-sm);
	font-weight: 600;
	margin: 0 !important;
}
.customer-side-info-tags .label-info {
	background: var(--surface-mute);
	color: var(--ink-2);
}
.customer-side-info-tags .label-danger {
	background: var(--danger-tint);
	color: var(--danger);
}

/* 36.11 Breathing room between the header card and the tab strip below it -- previously
   these sat back to back with no gap at all. */
.profile-active {
	margin-top: 20px;
}

@media (max-width: 900px) {
	.customer-details-wrapper { padding: 16px; }
	.profile-section { padding: 20px; }
	.profile-section .customer-additional-info {
		grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
		column-gap: 16px;
	}
	.profile-section .fi-address { grid-column: 1 / -1; max-width: none; }
	.customer-info { flex-wrap: wrap; }
	.customer-info .info-item { max-width: none; flex: 1 1 45%; }
	/* The phone/email row kept `white-space:nowrap` from contacts/details.css:72-74 --
	   my rules above never declare that property, so cascade leaves the earlier value in
	   place, and at 390px it ran the row off the card edge instead of wrapping.

	   Flex items default to `min-width:auto`, which for a text-containing box resolves to
	   its unwrapped max-content width, so nothing below actually shrinks on its own --
	   every flex box in the chain from `.pl-2` down needs an explicit min-width:0 (not
	   just the leaf phone/email spans) or the browser keeps sizing each one to fit its
	   widest un-wrapped descendant and the card's own overflow clips the remainder. */
	.profile-section .customer-info-section > .pl-2 {
		min-width: 0;
	}
	.profile-section .customer-info-section > .pl-2 > .flex {
		flex-wrap: wrap;
		row-gap: 4px;
		min-width: 0;
	}
	.profile-section .customer-phone,
	.profile-section .customer-email {
		white-space: normal;
		min-width: 0;
	}
}


/* ==========================================================================================
   TICKET 1 -- helper text under a form control in the hand-written Add Contact / Add Company
   modals. Those templates print their own markup and the adminform renderer's bottom-text has
   no wrapper element, so there was no existing class to reuse.
   ========================================================================================== */
.field-hint {
	margin-top: 4px;
	font-size: 12px;
	line-height: 1.45;
	color: #7C899B;
}
.row.role-at-company { margin-bottom: 4px; }

/* CF-4 -- "Did you mean …?" under Company Name / Website on Add/Edit Company. A warning, not an
   error: it never blocks the save, so it is amber and quiet rather than red. */
.dup-hint {
	margin-top: 6px;
	padding: 6px 10px;
	font-size: 13px;
	line-height: 1.45;
	color: #6B4E00;
	background: #FFF7E0;
	border-left: 3px solid #E0A800;
	border-radius: 4px;
}
.dup-hint[hidden] { display: none; }
.dup-hint a { color: inherit; font-weight: 600; text-decoration: underline; }
.dup-hint .dup-site { color: #8A7440; }


/* ==========================================================================================
   TICKET 1 -- the contact form as a PAGE, the secondary-company rows, and a Tags control that
   looks like the tag input it is.

   The Tags field is a selectize multi-select. It shipped with a 45px box, 20px side padding
   and no placeholder, so an empty one read as a stray blank rectangle with a second empty
   rectangle (the dropdown shell) beneath it -- which is exactly how it looked on screen.
   ========================================================================================== */

/* ---- the form when it is a page rather than a dialog ----------------------------------
   Two panels. The content column is 1400px and the fields want about 900 of it; stretching
   a first-name box to 700px to "use the space" reads worse than leaving it empty, so the
   spare column carries the guidance instead. The form itself becomes a white card so it
   stops showing the grey page ground through it.

   Contacts and Companies share this skin. Both are the same hand-written long form in the
   same frame, and giving each its own copy would let the two pages drift apart over a
   padding value.
   -------------------------------------------------------------------------------------- */
body.contact-form-page .cf-layout,
body.company-form-page .cf-layout,
body.pm-form-page .cf-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: 22px;
	align-items: start;
}
body.contact-form-page .add_customer_form,
body.company-form-page .add_organization_form,
body.pm-form-page .cf-layout .adminform_form,
body.pm-form-page .pm-form-main {
	max-width: none;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 24px 26px 18px;
}

/* ---- vertical rhythm --------------------------------------------------------------------
   The spacing between fields was never set: rows carried a 2px margin and everything you
   could see came from the label's own 5px and the control's height. That makes the gaps
   emergent rather than designed, so they drifted -- one row measured 74px against 2px
   everywhere else.

   One scale, applied once, so every field on both forms sits on the same grid:

       label -> control        6px
       control -> hint         6px
       field  -> next field   18px
       section rule           28px above, 12px below

   Scoped to the two PAGE forms only (`body.*-form-page`). The dialog keeps the tighter
   spacing it was designed for -- a modal has a height budget a page does not.
   ---------------------------------------------------------------------------------------- */
body.contact-form-page,
body.company-form-page {
	--f-gap: 18px;      /* between stacked fields */
	--f-label: 6px;     /* label to its control */
	--f-hint: 6px;      /* control to its helper line */
}

/* Direct children only: the phone repeater and the address block nest their own .row, and a
   blanket rule would double their spacing. */
body.contact-form-page .add_customer_form > .row,
body.company-form-page .add_organization_form > .row,
/* The phone repeater is a direct child but a `.flex`, not a `.row`, so a rule written only
   for rows skipped it -- it sat flush against the field below with no margin at all. Any
   direct-child block in these forms is a field group and takes the same gap. */
body.contact-form-page .add_customer_form > .flex,
body.company-form-page .add_organization_form > .flex {
	margin-bottom: var(--f-gap);
}
body.contact-form-page .add_customer_form > .row:last-of-type,
body.company-form-page .add_organization_form > .row:last-of-type { margin-bottom: 0; }

/* A nested row is a group inside one field's column -- it gets the label gap, not the field gap. */
body.contact-form-page .add_customer_form .row .row,
body.company-form-page .add_organization_form .row .row { margin-bottom: var(--f-label); }

body.contact-form-page .add_customer_form label,
body.company-form-page .add_organization_form label {
	display: block;
	margin-bottom: var(--f-label);
	font-weight: 500;
	line-height: 1.35;
}

/* Every control lands on the same baseline whatever plugin drew it -- a native input, a
   niceSelect div and a selectize shell were three different heights. */
body.contact-form-page .add_customer_form .form-control,
body.company-form-page .add_organization_form .form-control,
body.contact-form-page .add_customer_form .nice-select,
body.company-form-page .add_organization_form .nice-select,
body.contact-form-page .tags-for-regularpages .selectize-input,
body.company-form-page .tags-for-regularpages .selectize-input {
	min-height: 46px;
	margin-bottom: 0;
}

body.contact-form-page .field-hint,
body.company-form-page .field-hint {
	margin-top: var(--f-hint);
	margin-bottom: 0;
}

/* Section rules get their own breathing room rather than inheriting a field gap. */
body.contact-form-page .add_customer_form h4,
body.company-form-page .add_organization_form h4 { margin: 28px 0 12px; }

/* The two columns need a gutter that matches the vertical gap, or the form reads as denser
   across than it does down. */
body.contact-form-page .add_customer_form > .row,
body.company-form-page .add_organization_form > .row {
	margin-left: -9px;
	margin-right: -9px;
}
body.contact-form-page .add_customer_form > .row > [class*="col-"],
body.company-form-page .add_organization_form > .row > [class*="col-"] {
	padding-left: 9px;
	padding-right: 9px;
}

/* The repeatable "Also works at" rows follow the same scale. */
body.contact-form-page .assoc-extra-head { margin-bottom: var(--f-label); }
body.contact-form-page .assoc-extra-row { margin-bottom: var(--f-hint); }
body.contact-form-page .assoc-extra-add { margin-top: var(--f-hint); }
/* The section separators are the only structure inside a long form -- give them a rule. */
body.contact-form-page .add_customer_form h4,
body.company-form-page .add_organization_form h4 {
	margin: 22px 0 10px;
	padding-top: 16px;
	border-top: 1px solid #EDEFF3;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #7C899B;
}
body.contact-form-page .add_customer_form_savebutton,
body.company-form-page .add_organization_form_savebutton {
	margin-top: 20px;
	padding-top: 18px;
	border-top: 1px solid #EDEFF3;
}

body.contact-form-page .cf-side,
body.company-form-page .cf-side {
	position: sticky;
	top: 16px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}
body.contact-form-page .cf-side-card,
body.company-form-page .cf-side-card {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 16px 18px;
}
body.contact-form-page .cf-side-card h4,
body.company-form-page .cf-side-card h4 {
	margin: 0 0 8px;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #7C899B;
}
body.contact-form-page .cf-side-card p,
body.company-form-page .cf-side-card p {
	margin: 0 0 9px;
	font-size: 13px;
	line-height: 1.55;
	color: #5A6A80;
}
body.contact-form-page .cf-side-card p:last-child,
body.company-form-page .cf-side-card p:last-child { margin-bottom: 0; }
body.contact-form-page .cf-side-card strong,
body.company-form-page .cf-side-card strong { color: #1F2A37; }

/* The phone rows sit outside .row. They previously carried a hand-set 2px here, which is what
   left the phone block flush against the field under it once the rest of the form moved onto
   a scale -- and because this rule comes later in the file, it beat the scale silently. It now
   takes the same field gap as everything else. */
body.company-form-page .add_organization_form .phone { margin-bottom: var(--f-gap); }

/* A pinned property (Client Type) is its own full-width field, the same width and height as
   Company Name. The form's label rule makes every label a block, which let the checkboxes
   run into the phone row beside them. */
.add_organization_form > .pr-pinned { clear: both; }
.add_organization_form .pr-pinned .pr-multi {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 20px;
	width: 100%;
	min-height: 45px;
	margin: 0;
	padding: 8px 12px;
	border: 1px solid #E5E5E5;
	border-radius: 8px;
	background: #FFFFFF;
	box-sizing: border-box;
}
.add_organization_form .pr-pinned .pr-multi label {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	width: auto;
	margin: 0;
	font-weight: 400;
	line-height: 1.35;
}

/* Below the two-panel threshold the guidance drops under the form rather than squeezing. */
@media (max-width: 1180px) {
	body.contact-form-page .cf-layout,
	body.company-form-page .cf-layout,
	body.pm-form-page .cf-layout { grid-template-columns: minmax(0, 1fr); }
	body.contact-form-page .cf-side,
	body.company-form-page .cf-side,
	body.pm-form-page .cf-side { position: static; }
}

/* ---- rejected save ------------------------------------------------------------------
   The submit handler marks the offending field and writes the reason into #form-messages,
   but nothing in the theme ever gave `.error` a colour on these two forms: the message came
   out in the body grey and the field kept its normal border, so a refused save read as
   nothing having happened. `#form-messages.error` is styled per-module elsewhere in the
   theme (searchconditions.css, triggers.css and friends) and none of those files load here.

   Stated for the FORM, not for the page, because the dialog and the page share one template
   and one handler -- the dialog was equally colourless.
   -------------------------------------------------------------------------------------- */
.add_organization_form #form-messages.error,
.add_customer_form #form-messages.error {
	margin-top: 10px;
	font-size: 13px;
	font-weight: 500;
	color: #B42318;
}
.add_organization_form .form-control.error,
.add_customer_form .form-control.error {
	border-color: #D92D20;
	box-shadow: 0 0 0 3px rgba(217, 45, 32, .12);
}
.add_organization_form label.error,
.add_customer_form label.error { color: #B42318; }

/* ---- Tags ---- */
/* Once selectize owns a select it marks it `.selectized` and takes over the control. Anything
   else drawn for that same select is a second empty box -- either the bare native select, or a
   nice-select wrapper from the theme's blanket $('select').niceSelect(). Which one appears
   depends on script order, so this is stated as a fact about `.selectized` rather than fixed at
   one call site: JS ordering decides who runs first, CSS decides what is visible. */
select.selectized { display: none !important; }
select.selectized + .nice-select { display: none !important; }

.tags-for-regularpages .selectize-control { width: 100%; }
.tags-for-regularpages .selectize-input {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	min-height: 46px;
	padding: 8px 12px !important;
	border: 1px solid #DFE3EA;
	border-radius: 8px;
	background: #FFF;
	box-shadow: none;
	transition: border-color .12s ease, box-shadow .12s ease;
}
.tags-for-regularpages .selectize-input.focus,
.tags-for-regularpages .selectize-input.dropdown-active {
	border-color: #E0512F;
	box-shadow: 0 0 0 3px rgba(224, 81, 47, .12);
}
/* Each chosen tag is a chip, not bare text on a line. */
.tags-for-regularpages .selectize-input > .item {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin: 0;
	padding: 3px 8px 3px 10px;
	border-radius: 999px;
	background: #F1F3F6;
	border: 1px solid #E2E6EC;
	color: #1F2A37;
	font-size: 12.5px;
	line-height: 1.5;
}
.tags-for-regularpages .selectize-input > .item.active {
	background: #FDEAE4;
	border-color: #F0BCA9;
	color: #9A2A18;
}
.tags-for-regularpages .selectize-input > .item .remove {
	border: 0;
	padding: 0 0 0 2px;
	color: #8B98AB;
	text-decoration: none;
	font-size: 14px;
	line-height: 1;
}
.tags-for-regularpages .selectize-input > .item .remove:hover { color: #9A2A18; background: transparent; }
.tags-for-regularpages .selectize-input > input {
	min-width: 120px !important;
	height: 26px;
	margin: 0 !important;
	font-size: 13.5px;
}
.tags-for-regularpages .selectize-input > input::placeholder { color: #98A2B3; }
/* The empty second box was the dropdown shell painting with a border even with no results. */
.tags-for-regularpages .selectize-dropdown {
	border: 1px solid #DFE3EA;
	border-radius: 8px;
	margin-top: 4px;
	box-shadow: 0 8px 24px rgba(16, 24, 40, .10);
	overflow: hidden;
}
.tags-for-regularpages .selectize-dropdown:empty { display: none !important; border: 0; }
.tags-for-regularpages .selectize-dropdown .option { padding: 8px 12px; font-size: 13.5px; }
.tags-for-regularpages .selectize-dropdown .active { background: #FDEAE4; color: #9A2A18; }
.tags-for-regularpages .selectize-dropdown .create { padding: 8px 12px; font-size: 13.5px; }

/* ---- "Also works at": the secondary company rows (AC3) ---- */
.assoc-extra-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.assoc-extra-head label { margin: 0; font-weight: 600; }
.assoc-extra-row {
	display: grid;
	grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) 34px;
	gap: 10px;
	align-items: center;
	margin-bottom: 8px;
}
.assoc-extra-row .form-control { margin: 0; }
.assoc-extra-remove {
	height: 34px;
	border: 1px solid #DFE3EA;
	border-radius: 8px;
	background: #FFF;
	color: #8B98AB;
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	transition: color .12s ease, border-color .12s ease;
}
.assoc-extra-remove:hover { color: #9A2A18; border-color: #F0BCA9; }
.assoc-extra-add {
	margin-top: 2px;
	padding: 7px 14px;
	border: 1px dashed #C9D2DE;
	border-radius: 8px;
	background: transparent;
	color: #2F6BA8;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
}
.assoc-extra-add:hover { border-color: #2F6BA8; background: #F5F8FC; }

@media (max-width: 720px) {
	.assoc-extra-row { grid-template-columns: 1fr; }
	.assoc-extra-row .assoc-extra-remove { width: 100%; }
}


/* ==========================================================================================
   Field-level validation. The message belongs next to the control that caused it: one shared
   block at the foot of a long form is a message the user has to go looking for.
   ========================================================================================== */
.field-error {
	margin-top: 6px;
	font-size: 12.5px;
	line-height: 1.45;
	color: #9B2C2C;
}
.form-control.error,
.nice-select.error,
.selectize-input.error {
	border-color: #D1584B !important;
	box-shadow: 0 0 0 3px rgba(209, 88, 75, .12);
}
label.error { color: #9B2C2C; }
/* The scrolled-to field needs to be findable the moment the page stops moving. */
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
}


/* ==========================================================================================
   Companies list: no dead space under a short table.

   `.table-responsive` carries a global `min-height: 200px` (stylesheets.css:28) so an EMPTY
   table does not collapse to nothing. On a list with one or two rows that floor is taller than
   the content, and the surplus renders as a blank slab under the last row -- which is what it
   looked like on a brand with a single company.

   Overridden here rather than in the global rule: `.table-responsive` is used by tables all
   over the app and their empty states still want the floor. The empty state keeps its own
   height below, so nothing collapses.
   ========================================================================================== */
body.organizations_list_section .table-responsive { min-height: 0; }
body.organizations_list_section .table-responsive table { margin-bottom: 0; }
/* A genuinely empty list still needs somewhere to say so. */
body.organizations_list_section .table-responsive tbody:empty,
body.organizations_list_section .table-responsive tbody tr.is-empty td,
body.organizations_list_section .table-responsive tbody td.is-empty { min-height: 90px; height: auto; }


/* =========================================================================================
   11. EMPTY STATES AND THE COMPANIES TOOLBAR
   ========================================================================================= */

/* 11.1 Two-line empty state. `td.is-empty` already centres and pads (9.6); these give the
   message a headline and a quieter hint so it reads as a state, not as a failed row. */
td.is-empty .es-title,
tr.is-empty td .es-title {
	display: block;
	font-size: 15px;
	font-weight: 600;
	color: #374151;
	margin-bottom: 4px;
}
td.is-empty .es-hint,
tr.is-empty td .es-hint {
	display: block;
	font-size: 13px;
	font-weight: 400;
	color: #8A94A6;
}

/* 11.2 COMPANIES LIST TOOLBAR -- Export, Add Company and the column chooser on ONE row.

   Export/Add and the chooser used to be separate flex children of `.extended-buttons`, and
   `.buttons-section { width: 100% }` (stylesheets.css:3130) is a global that made the first of
   them consume an entire flex line, so the chooser dropped onto a row of its own. Reordering
   them with `order` was not enough: that container also holds the search box, the funnel, a
   bulk-actions dropdown, a <form>, two <script>s and two `.modal` divs as flex items, so what
   shares a line with what is not something CSS alone should be asked to guarantee.

   They are now one wrapper in the template (companies/manage-buttons-list-view.tpl), placed
   after the `.flex-1` spacer so the group sits at the right edge. These rules only undo the
   inherited full-width and the auto margin INSIDE that wrapper.

   Scoped to body.organizations_list_section (organizations.php:2167): ~30 other routes emit the
   same classes -- contactlist, support, settings, campaigns, deals, companylinks -- and keep
   their layout, as does the Companies card view (body.organizations_pipeline_section).
   ========================================================================================= */
body.organizations_list_section .extended-buttons > .toolbar-actions {
	display: flex;
	align-items: center;
	gap: 9px;
	flex: 0 0 auto;
	flex-wrap: nowrap;
}
body.organizations_list_section .toolbar-actions > .buttons-section {
	width: auto;
	flex: 0 0 auto;
}
/* display:flex, margin-top:0 and justify-content:flex-end already come from
   admin-buttons.css:8-13; only the gap between Export and Add Company is missing. */
body.organizations_list_section .toolbar-actions .adminbuttons {
	gap: 9px;
	flex-wrap: nowrap;
}
/* extended-buttons.css:44-50 gives .right-wrapper margin-left:auto to push it to the far edge.
   Inside the group that would tear the chooser away from the buttons it now belongs to. */
body.organizations_list_section .toolbar-actions > .right-wrapper {
	margin-left: 0;
	flex: 0 0 auto;
}
/* One divider before the group is enough; the second `.vr`
   (companies/list-view-buttons.tpl:2) now sits between two buttons and reads as clutter. */
body.organizations_list_section .toolbar-actions > .right-wrapper > .vr { display: none; }

/* =========================================================================================
   12. RECORD DETAIL TABS -- contacts AND companies

   Both pages emit body class `customer_details_page` (customerdetails.php:22 and
   organizationdetails.php:22), so everything here governs the two strips identically. That is
   the point: the company strip used to carry its own second class list on the <ul>
   (`flex md:flex-row flex-wrap ... mb-4 mt-4`), giving it different margins and different
   wrapping from the contact strip on what is meant to be the same control.

   Every section of a contact (Activity, Emails, Conversation, Tasks, Companies, Brands, Deals,
   Marketing Messages, Campaigns, Booked Calls, Files) was behind a closed <select>-styled
   dropdown, so reading "does this person have any open tasks?" cost a click and a scan of a
   menu. customerdetailstabs.tpl now emits its <li>s straight into the <ul class="nav nav-tabs">
   that customerdetails.tpl:399 always provided.

   The strip is ONE ROW that scrolls horizontally. Eleven tabs measure ~1220px against a 933px
   content column at 1280, so they do not fit on a line below ~1600px; wrapping them to a second
   row was the first attempt and the owner asked for a scroller instead. Two things make the
   overflow discoverable rather than a silent truncation -- the failure §10 of this file records
   on eleven other routes: the scrollbar is given an explicit slim style so it does not auto-hide
   to nothing, and a fade marks the right edge.
   ========================================================================================= */
.customer_details_page .profile-active .nav.nav-tabs {
	display: flex;
	flex-wrap: nowrap;
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: thin;
	-webkit-overflow-scrolling: touch;
	/* Stated here rather than relying on Bootstrap's `.nav` plus the Tailwind utilities the
	   company strip used to carry, so both strips get the same spacing from one rule. */
	margin: 0 0 15px;
	padding-left: 0;
	list-style: none;
	/* Room for the scrollbar so it cannot sit on top of the active tab's underline. */
	padding-bottom: 2px;
}
.customer_details_page .profile-active .nav.nav-tabs > li {
	/* Labels stay on one line; the strip scrolls instead of the text wrapping. */
	flex: 0 0 auto;
	white-space: nowrap;
}
/* A slim, quiet scrollbar. The platform default auto-hides on macOS, which would leave the
   strip looking truncated with no cue that the rest is reachable. */
.customer_details_page .profile-active .nav.nav-tabs::-webkit-scrollbar { height: 6px; }
.customer_details_page .profile-active .nav.nav-tabs::-webkit-scrollbar-track { background: transparent; }
.customer_details_page .profile-active .nav.nav-tabs::-webkit-scrollbar-thumb {
	background: #D8DEE7;
	border-radius: 999px;
}
.customer_details_page .profile-active .nav.nav-tabs::-webkit-scrollbar-thumb:hover { background: #BFC8D4; }

/* The right-edge fade says "there is more this way" without costing a row of height.

   A MASK, not a coloured gradient overlay. Nothing in the cascade paints a background on
   .profile-active or its ancestors that this file can name, so a `linear-gradient(to right,
   transparent, #F3F4F6)` would be guessing the page wash -- and a wrong guess renders as a grey
   smear over the last tab rather than a fade. A mask fades the strip itself to transparency and
   is therefore correct on any background. It also cannot intercept a click, which an overlay
   would without an explicit pointer-events:none. */
.customer_details_page .profile-active .nav.nav-tabs {
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
	mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
}

/* Bootstrap's `.nav-tabs > li { float: left; margin-bottom: -1px }` (bootstrap.css:4097) pulls a
   wrapped second row up over the first. `display:flex` on the parent de-floats the children and
   cancels both, so this is a consequence of the rule above rather than a separate fix. */

/* REQUIRED, not cosmetic. The inactive labels got their grey from
   `.dropdown-select-styled .dropdown-menu li a` (globalstyles.css:72-77) -- a selector that stops
   matching the moment the items leave the dropdown. `.profile-active .nav-tabs > li` is coloured
   in contacts/details.css:110-116, but the <a> does not inherit it because bootstrap.css:1099
   sets `a { color:#337ab7 }` on the anchor directly. Without this every inactive tab renders
   link-blue. The active tab keeps its own colour + 3px underline from contacts/details.css:118. */
.customer_details_page .profile-active .nav-tabs > li > a {
	color: #737373;
}
.customer_details_page .profile-active .nav-tabs > li > a:hover,
.customer_details_page .profile-active .nav-tabs > li > a:focus {
	color: #1A4159;
	background: transparent;
}

/* The activity filter is a `float:right` box lifted by `margin-top:-50px`
   (globalstyles.css:96-101) so it sits level with what used to be a single 44px dropdown row.
   Measured from its own static position below the </ul>, that 50px now lands it in the MIDDLE of
   a two-row strip -- and being a float painted after the tabs, it would cover Campaigns / Booked
   Calls / Files and swallow their clicks. Right-align it honestly instead.

   Safe to override globally: customerdetails.php:1590 and :1962 are the only two producers of
   `.customer_activity_filters` in the codebase, so no other screen can be disturbed. The shared
   `.dropdown-select-styled` block (globalstyles.css:50-91) is deliberately NOT touched -- the
   filter control itself still uses it. */
.customer_details_page .profile-active .filter.customer_activity_filters {
	display: flex;
	justify-content: flex-end;
}
.customer_details_page .customer_activity_filters .wrapper {
	float: none;
	margin-top: 0;
}

/* =========================================================================================
   13. EXTENDED SEARCH AND SAVED SEARCHES (Companies)

   The filter dialog was a stack of full-width label/select rows inside a default Bootstrap
   modal, most of them "(A-Z)" pickers. It is now a grouped two-column sheet: Company,
   Relationships, Revenue & timing, Location & size -- so a filter can be found by the kind of
   question being asked rather than by reading ten labels.

   Scoped to .xs-* / .ss-* class names introduced with these two dialogs, so nothing else in the
   app is reachable from here.
   ========================================================================================= */

.xs-modal .modal-dialog,
.ss-modal .modal-dialog {
	max-width: 720px;
	width: calc(100% - 32px);
	margin: 32px auto;
}
.ss-modal .modal-dialog { max-width: 560px; }

.xs-panel,
.ss-panel {
	background: #FFFFFF;
	border: 0;
	border-radius: 14px;
	box-shadow: 0 24px 60px rgba(16, 26, 43, .18);
	overflow: hidden;
}

/* ---- header ---- */
.xs-head,
.ss-head {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	padding: 22px 24px 16px;
	border-bottom: 1px solid #EEF1F5;
}
.xs-title,
.ss-title {
	margin: 0;
	font-size: 19px;
	font-weight: 650;
	color: #101A2B;
	line-height: 1.25;
}
.xs-sub,
.ss-sub {
	margin: 4px 0 0;
	font-size: 13px;
	color: #7C8AA0;
}
.xs-x,
.ss-x {
	margin-left: auto;
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: #7C8AA0;
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
}
.xs-x:hover,
.ss-x:hover { background: #F3F5F8; color: #101A2B; }

/* ---- body ---- */
.xs-body {
	padding: 4px 24px 8px;
	/* The sheet scrolls, the page behind it does not. 70vh keeps the footer -- and therefore
	   "Show results" -- on screen at laptop heights, which a full-height modal did not. */
	max-height: 70vh;
	overflow-y: auto;
}
.xs-group { padding: 18px 0 6px; border-bottom: 1px solid #F2F4F7; }
.xs-group:last-child { border-bottom: 0; }
.xs-group-title {
	margin: 0 0 12px;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: #98A2B3;
}
.xs-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 14px 18px;
}
.xs-span2 { grid-column: 1 / -1; }
.xs-field { display: flex; flex-direction: column; gap: 6px; margin: 0; min-width: 0; }
.xs-label {
	font-size: 12px;
	font-weight: 600;
	color: #475467;
}
.xs-input {
	width: 100%;
	min-height: 40px;
	padding: 8px 12px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: 13px;
	color: #101A2B;
	appearance: auto;
}
.xs-input:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}

/* ---- footer ---- */
.xs-foot {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 16px 24px;
	border-top: 1px solid #EEF1F5;
	background: #FBFCFD;
}
.xs-spacer { flex: 1 1 auto; }
.xs-clear { font-size: 13px; color: #7C8AA0; text-decoration: none; }
.xs-clear:hover { color: #101A2B; text-decoration: underline; }
.xs-btn,
.ss-btn {
	min-height: 40px;
	padding: 9px 16px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: 13px;
	font-weight: 600;
	color: #344054;
	cursor: pointer;
	white-space: nowrap;
}
.xs-btn:hover,
.ss-btn:hover { background: #F3F5F8; }
.xs-primary,
.ss-primary {
	background: #3FBF3C;
	border-color: #17803D;
	color: #0B1533;
}
.xs-primary:hover,
.ss-primary:hover { background: #A83A22; border-color: #A83A22; }

/* ---- save bar ---- */
.xs-savebar { padding: 16px 24px 20px; border-top: 1px solid #EEF1F5; background: #FBFCFD; }
.xs-saverow { display: flex; gap: 10px; margin-top: 6px; }
.xs-saverow .xs-input { flex: 1 1 auto; }
.xs-hint { margin: 8px 0 0; font-size: 12px; color: #8A94A6; }

/* ---- saved searches list ---- */
.ss-body { padding: 8px 16px 20px; max-height: 70vh; overflow-y: auto; }
.ss-list { list-style: none; margin: 0; padding: 0; }
.ss-item {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	padding: 12px 8px;
	border-bottom: 1px solid #F2F4F7;
}
.ss-item:last-child { border-bottom: 0; }
.ss-item.is-active { background: #FFF6F3; border-radius: 10px; }
.ss-apply { flex: 1 1 220px; min-width: 0; text-decoration: none; display: block; }
.ss-apply:hover .ss-name { color: #17803D; }
.ss-name { display: block; font-size: 14px; font-weight: 600; color: #101A2B; }
.ss-summary {
	display: block;
	margin-top: 2px;
	font-size: 12px;
	color: #8A94A6;
	/* Summaries are one line: a saved search with eight filters must not push the row
	   controls out of reach. */
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.ss-actions { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.ss-inline { margin: 0; display: inline-flex; }
.ss-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	border: 1px solid transparent;
	border-radius: 7px;
	background: transparent;
	color: #7C8AA0;
	cursor: pointer;
}
.ss-icon:hover { background: #F3F5F8; border-color: #E4E8EE; color: #101A2B; }
.ss-danger:hover { background: #FDF2F0; border-color: #F3D3CC; color: #17803D; }
.ss-rename { display: flex; gap: 8px; width: 100%; margin: 10px 0 2px; }
.ss-input {
	flex: 1 1 auto;
	min-height: 38px;
	padding: 8px 12px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	font-size: 13px;
	color: #101A2B;
}
.ss-input:focus { outline: none; border-color: #17803D; box-shadow: 0 0 0 3px rgba(63, 191, 60, .14); }

/* ---- empty state ---- */
.ss-empty { padding: 34px 20px 30px; text-align: center; }
.ss-empty-mark {
	width: 48px; height: 48px; margin: 0 auto 14px;
	display: flex; align-items: center; justify-content: center;
	border-radius: 50%; background: #ECFDF3; color: #3B9E6B; font-size: 22px;
}
.ss-empty-title { margin: 0; font-size: 15px; font-weight: 600; color: #374151; }
.ss-empty-hint { margin: 6px auto 0; max-width: 380px; font-size: 13px; color: #8A94A6; line-height: 1.5; }

/* ---- narrow ---- */
@media (max-width: 640px) {
	.xs-grid { grid-template-columns: minmax(0, 1fr); }
	.xs-foot { flex-wrap: wrap; }
	.xs-spacer { flex-basis: 100%; height: 0; }
}

/* Outcome of a saved-search write, carried back on the redirect. */
.ss-notice {
	margin: 0 0 12px;
	padding: 10px 14px;
	border: 1px solid #CDEBDA;
	border-radius: 8px;
	background: #F2FBF6;
	color: #276749;
	font-size: 13px;
}
.ss-notice.is-error { border-color: #F3D3CC; background: #FDF2F0; color: #A33A22; }

/* =========================================================================================
   14. CONTACT PROFILE CARD -- the identity block at the top of m=customerdetails

   Refines §36. The action row (Email / Message / Send / Schedule / Edit) looked loosely
   scattered because each control carries Bootstrap's `.btn` -- `padding: 6px 12px` plus a 1px
   transparent border (bootstrap.css:3104-3116) -- ON TOP of the 36px min-width §36.5 gives it.
   A 16px icon therefore sat in a ~42px box, so the 4px gap rendered as roughly 28px of air and
   the five icons read as five unrelated links rather than one toolbar.
   ========================================================================================= */

/* 14.1 One tight, deliberate toolbar. Padding is zeroed so the declared box size IS the box
   size, and the hit area stays at 34px -- above the 24x24 WCAG target floor. */
.profile-section .main_buttons {
	margin-top: 12px;
}
.profile-section .main_buttons > div {
	display: flex;
	align-items: center;
	gap: 2px;
	margin-left: -7px;   /* optically flush the first icon with the name above it */
}
.profile-section .main_buttons a.profile-btn-follow,
.profile-section .main_buttons a.btn.profile-btn-follow {
	width: 34px;
	height: 34px;
	min-width: 34px;
	min-height: 34px;
	padding: 0;
	margin: 0;
	border: 0;
	border-radius: 9px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
	background: transparent;
	transition: background-color .12s ease, transform .12s ease;
}
.profile-section .main_buttons a.profile-btn-follow:hover,
.profile-section .main_buttons a.profile-btn-follow:focus-visible {
	background: #FDF0EC;
	transform: translateY(-1px);
}
.profile-section .main_buttons a.profile-btn-follow:active {
	transform: none;
}
/* The icons are drawn at several sizes by their own SVGs; normalise so the row reads as one
   set rather than five glyphs that happen to sit together. */
.profile-section .main_buttons a.profile-btn-follow svg {
	width: 17px;
	height: 17px;
	display: block;
}

/* 14.2 Avatar. 72px next to a 22px name was top-heavy and pushed the meta line off the
   optical centre. A soft ring instead of the flat 2px border of the same colour as the fill,
   which was invisible and only added 4px. */
.profile-section .customer-icon {
	width: 64px;
	height: 64px;
	min-width: 64px;
	font-size: 21px;
	font-weight: 600;
	letter-spacing: .02em;
	border: 0;
	box-shadow: 0 0 0 4px #F4F6F9, 0 2px 6px rgba(16, 26, 43, .16);
}

/* 14.3 Vertical rhythm. The name, the meta line and the toolbar were three blocks with no
   agreed spacing; 32px of padding-left on the info column (contacts/details.css:20) against a
   64px avatar is also more than the gap needs. */
.profile-section .pl-2 {
	padding-left: 20px;
}
.profile-section h4 {
	margin: 0 0 2px;
}
.profile-section .customer-phone,
.profile-section .customer-email {
	font-size: 13.5px;
	color: #5B6676;
	line-height: 1.5;
}
.profile-section .customer-phone a {
	color: #5B6676;
	text-decoration: none;
	border-bottom: 1px solid #DDE2E9;
}
.profile-section .customer-phone a:hover {
	color: #17803D;
	border-bottom-color: #E9B4A6;
}
/* The separator only belongs BETWEEN two values. As a plain ::after it also printed after the
   phone when no email followed, leaving a trailing dot. */
.profile-section .customer-phone:last-child::after {
	content: none;
}

/* 14.4 Tighten the card itself. 28px/32px around a 64px avatar left the block floating. */
.profile-section {
	padding: 22px 24px;
}

/* =========================================================================================
   15. RECORD DETAIL TAB PANES -- one shape for every tab on a company / contact record

   READ THIS BEFORE ADDING A TAB. Each pane on m=organizationdetails was built by whoever added
   that tab, so nine tabs arrived in four different shapes: table tabs (Contacts, Tickets,
   Activity, Campaigns, Calls, Files) render a Grid inside `.table-responsive`; the messaging
   tabs (Emails, Conversation, Notes) render an AJAX-filled `.rd-dash-conversation` that is a
   `display: table-cell` and therefore never became a card at all; Notes adds a composer; and
   Conversation prepends a warning banner. The result was panes with different backgrounds,
   different widths and different amounts of dead space under them.

   The rules below give every pane the same card, the same padding and the same empty state, and
   they are written against the containers the app ALREADY emits -- no template needs to opt in.
   A new tab that renders either a Grid or an `.rd-dash-conversation` inherits all of it.

   The EMPTY STATE is `Grid::SingleLineLabel()` + `CellAddClass(..., 'is-empty')`, with the text
   as `<span class="es-title">` plus `<span class="es-hint">`. Typography comes from SS9.6/SS11.1.
   Every tab in organizationdetails.php now does this; keep new ones consistent.
   ========================================================================================= */

/* 15.1 The dead slab under short tables. `.table-responsive` carries a global
   `min-height: 200px` (stylesheets.css:26-29) which is floor, not content -- so a tab with one
   contact, or none, painted ~150px of empty white below the last row. The empty state supplies
   its own height, so nothing collapses. */
.customer_details_page .table-responsive { min-height: 0; }
.customer_details_page .table-responsive table { margin-bottom: 0; }
.customer_details_page .table-responsive tbody td.is-empty { min-height: 90px; height: auto; }

/* 15.2 The messaging panes become real cards.

   `.rd-dash-conversation` is `display: table-cell` with `background:#fff`
   (marketingmessages.css:46-52). A table-cell with no table around it shrink-wraps its content,
   so on Emails and Conversation -- where the content is an empty div waiting on AJAX -- the
   white never covered the pane and the tab read as an unstyled slab of page wash. */
.customer_details_page .profile-active .rd-dash-conversation {
	display: block;
	width: 100%;
	padding: 18px 20px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
}
/* Bootstrap's grid gutters put a 15px inset on `.col-md-12` and pull `.row` back by -15px.
   Inside a card that is padding fighting padding, and it was what made the messaging panes sit
   at a different width from the table panes. */
.customer_details_page .profile-active .rd-dash-conversation > .row { margin-left: 0; margin-right: 0; }
.customer_details_page .profile-active .rd-dash-conversation > .row > [class*="col-"] { padding-left: 0; padding-right: 0; }
/* A pane still waiting on its AJAX response should hold its height rather than collapsing to a
   1px line and then jumping when the content lands. */
.customer_details_page .profile-active .rd-dash-conversation-view:empty,
.customer_details_page .profile-active .rd-dash-note-view:empty { min-height: 80px; }

/* 15.3 Right-hand action buttons ("+ New" on Emails, "+ Upload" on Files) were floated with
   `pull-right` inside a wrapper carrying BOTH `.upload-image-button-wrapper` (display:table;
   width:auto -- custom.css:41) and Bootstrap's `.table` (width:100%). Two rules fighting over
   the width of a float is why the button sat half outside the pane's right edge. Laid out
   instead of floated, it cannot leave the container. */
.customer_details_page .profile-active .upload-image-button-wrapper,
.customer_details_page .profile-active .block-content-outer > .pull-right {
	display: flex;
	justify-content: flex-end;
	float: none;
	width: 100%;
	max-width: 100%;
	margin: 0 0 10px;
}

/* 15.4 Nothing on a record page may push the page sideways. Screens here have run past the
   right edge before (SS10 records eleven of them); a wide table scrolls inside its own pane. */
.customer_details_page .profile-active { max-width: 100%; min-width: 0; }
.customer_details_page .profile-active .table-responsive { overflow-x: auto; }

/* 15.5 The Notes composer. The textarea was a bare input on the card with no border and no
   rhythm against the Submit button below it, so the tab looked half-built next to the others. */
.customer_details_page .profile-active .rd-dash-conversation-answer textarea,
.customer_details_page .profile-active textarea.rd-dash-conversation-answer-text {
	width: 100%;
	min-height: 84px;
	padding: 10px 12px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	font-size: 13.5px;
	color: #101A2B;
	resize: vertical;
}
.customer_details_page .profile-active .rd-dash-conversation-answer textarea:focus {
	outline: none;
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.customer_details_page .profile-active .rd-dash-conversation-answer button {
	margin-top: 10px;
}

/* 15.6 The Conversation tab's "no phone number" banner. It was full-bleed on the page wash,
   above a pane that is now a card, so the two did not read as one tab. */
.customer_details_page .profile-active .aui-message {
	margin: 0 0 12px;
	padding: 10px 14px;
	border: 1px solid #F0E0B6;
	border-radius: 8px;
	background: #FDF8EC;
	color: #8A6D1F;
	font-size: 13px;
}

/* 15.7 An empty `.block` still reserves space. Emails and Conversation emit one containing
   nothing but `<div style="clear:both">`, which left a gap between the tabs and the pane. */
.customer_details_page .profile-active .block-content-outer:not(:has(> *:not([style*="clear"]))) {
	margin: 0;
	padding: 0;
}

.customer_details_page .profile-active .activity-log-pane .activity-log-toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin: 0 0 8px;
}
.customer_details_page .profile-active .activity-log-pane .activity-log-toolbar .ct-panel-head {
	margin: 0;
}
.customer_details_page .profile-active .activity-log-pane .filter.customer_activity_filters {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	margin: 0;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: 0;
}
.customer_details_page .profile-active .activity-log-pane .logs-wraper {
	display: block;
	width: 100%;
	margin: 0;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: 0;
}
.customer_details_page .profile-active .activity-log-pane .logs-wraper > .col-md-12,
.customer_details_page .profile-active .activity-log-pane .logs-wraper > .col-md-9 {
	padding-left: 0;
	padding-right: 0;
	width: 100%;
	float: none;
}
.customer_details_page .profile-active .activity-log-pane .activity-ib .ib-card {
	margin-bottom: 10px;
}
.customer_details_page .profile-active .activity-log-pane .activity-ib .ib-card-meta {
	font-size: var(--fs-xs);
	color: var(--text-soft);
}
.customer_details_page .profile-active .activity-log-pane .activity-ib .ib-empty {
	padding: 28px 16px;
	text-align: center;
	border: 1px dashed var(--line);
	border-radius: var(--r-md);
	background: var(--surface);
}
.customer_details_page .profile-active .activity-log-pane .activity-ib .ib-empty .es-title {
	display: block;
	font-weight: 600;
	color: var(--ink);
	margin-bottom: 4px;
}
.customer_details_page .profile-active .activity-log-pane .activity-ib .ib-empty .es-hint {
	display: block;
	font-size: var(--fs-sm);
	color: var(--text-muted);
}
/* Legacy row layout (default theme) — keep harmless if ever rendered */
.customer_details_page .profile-active .activity-log-pane .log-info {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	margin: 0;
	padding: 16px 0;
	background: transparent;
	border: 0;
	border-bottom: 1px solid #EEF1F5;
	border-radius: 0;
}
.customer_details_page .profile-active .activity-log-pane .log-info:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}
.customer_details_page .profile-active .activity-log-pane .log-info .image {
	flex: 0 0 40px;
	width: 40px;
	text-align: center;
}
.customer_details_page .profile-active .activity-log-pane .log-info .text {
	margin-left: 0;
	padding: 0;
	width: 100%;
	min-width: 0;
	background: transparent;
	border: 0;
	border-radius: 0;
}

/* 15.9 The same empty state outside a table. SS9.6 styles `td.is-empty`, but the Activity tab
   renders a log FEED, not a Grid, so its empty state is a plain <div>. Given the same class so
   the nine tabs cannot drift apart, and the same two-line typography as SS11.1. */
.customer_details_page .profile-active div.is-empty {
	display: block;
	padding: 40px 16px;
	text-align: center;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
}
.customer_details_page .profile-active div.is-empty .es-title,
.customer_details_page .profile-active div.is-empty .es-hint {
	display: block;
}
.customer_details_page .profile-active div.is-empty .es-title {
	font-size: 14px;
	font-weight: 600;
	color: #374151;
}
.customer_details_page .profile-active div.is-empty .es-hint {
	margin-top: 4px;
	font-size: 13px;
	color: #8A94A6;
}

/* 15.10 The messaging empty states render INSIDE the pane card (15.2), so they must not draw a
   second one. They also appear on screens that are not record pages -- the Inbox uses the same
   two templates -- so the typography is declared unscoped and only the card is suppressed. */
.nothing_found.is-empty {
	display: block;
	padding: 40px 16px;
	text-align: center;
}
.nothing_found.is-empty .es-title,
.nothing_found.is-empty .es-hint { display: block; }
.nothing_found.is-empty .es-title {
	font-size: 14px;
	font-weight: 600;
	color: #374151;
}
.nothing_found.is-empty .es-hint {
	margin-top: 4px;
	font-size: 13px;
	color: #8A94A6;
}
/* No card within a card. */
.customer_details_page .profile-active .rd-dash-conversation div.is-empty {
	border: 0;
	background: transparent;
	padding: 28px 16px;
}

/* =========================================================================================
   16. COMPANY RECORD HEADER -- the identity block and the field grid beside it

   `.company-info-section` is a flex row of three: the avatar, `.pl-2` (name + email + the edit
   pencil) and `.company-additional-info` (the field grid). `.pl-2` had no width bounds and there
   was no gutter between it and the grid, so on a company with a long email the address ran
   straight into the first field -- "ab.wasay.aw@gmail.com" and "Assign User" touching, with the
   edit pencil wedged between them and reading as an icon belonging to the ASSIGNED USER label.
   ========================================================================================= */

.customer_details_page .profile-section .company-info-section {
	/* The gutter that was missing. `gap` rather than a margin on `.pl-2`, so the avatar keeps
	   its own 20px and a wrapped layout does not inherit a stale side margin. */
	gap: 0 32px;
	align-items: flex-start;
	flex-wrap: wrap;
}
.customer_details_page .profile-section .company-info-section > .pl-2 {
	/* Bounded: wide enough for a real company name, narrow enough that it cannot crowd the
	   grid. `min-width: 0` lets the long email ellipsis instead of forcing the row wider. */
	/* 400px (was 320): Create Contact / Create Deal / Create Task (~366px) fit on one row with the 20px padding. */
	flex: 0 1 400px;
	min-width: 0;
	padding-left: 20px;
}
/* The email is the one string here with no natural break, and it is what pushed into the grid. */
.customer_details_page .profile-section .company-email,
.customer_details_page .profile-section .company-phone {
	display: inline-block;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	vertical-align: bottom;
}
/* Top-aligned so the field LABELS line up with the company name rather than floating against
   the vertical centre of whatever the tallest column happens to be. */
.customer_details_page .profile-section .company-additional-info {
	align-content: start;
	align-items: start;
	padding-top: 2px;
}
/* The edit pencil sat flush against the grid because `.ml-auto` pushes it to the right edge of
   a `.pl-2` that ends where the grid begins. */
.customer_details_page .profile-section .btn-edit-company {
	margin-left: 12px;
	cursor: pointer;
	color: #7C8AA0;
	border-radius: 8px;
	padding: 4px;
	display: inline-flex;
	transition: background-color .12s ease, color .12s ease;
}
.customer_details_page .profile-section .btn-edit-company:hover {
	background: #F1F3F6;
	color: #101A2B;
}

/* 16.2 The stat row under the header (Status / Stage / Confidence Level). A single stat left a
   40px coloured circle floating alone against a wide empty card. Compact chips, aligned to the
   same left edge as the identity block, read as part of the header rather than a stray widget. */
.customer_details_page .profile-section .company-info {
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 20px;
	padding-top: 20px;
	border-top: 1px solid #EEF1F5;
}
.customer_details_page .profile-section .info-item {
	height: auto;
	align-items: center;
	gap: 10px;
	padding: 10px 14px;
	background: #F9FAFB;
	border: 1px solid #EEF1F5;
	border-radius: 10px;
}
.customer_details_page .profile-section .info-item svg {
	width: 32px;
	height: 32px;
	flex: 0 0 auto;
}
.customer_details_page .profile-section .info-item h5 {
	margin: 0 0 2px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #8A94A6;
}

/* 16.3 Address is prose and wraps to three lines; the rest are single-line facts. Letting it
   span two tracks keeps the grid's rows from being driven by the one field that is a paragraph. */
.customer_details_page .profile-section .company-additional-info .fi-address {
	grid-column: span 2;
}

/* =========================================================================================
   17. THE RIGHT-HAND RAIL GUTTER (company and contact record pages)

   Both record pages carry a slide-in property panel that is `position: absolute` and parked
   mostly outside the container:

     .company_details_dropdown   width 210px, margin-right -165px   -> 45px visible
     .customerdetails_dropdown   width 410px, right 45px, margin-right -410px -> 45px visible

   Those 45px sit OVER the content. `.company-details-wrapper` reserved room for them with
   `padding: 24px 65px 24px 24px` (companies/details.css:11) until SS8.3 zeroed the horizontal
   padding on the grounds that the panels are absolutely positioned. They are -- but being
   absolute is what makes them overlap; it is not what makes them harmless. With the gutter
   gone, every right-aligned control on these pages rendered underneath the rail: the Files
   tab's "+ Upload", the Emails tab's "+ New", and the last column of every table.

   Sized to the rail plus a little air, rather than restoring the old arbitrary 65px. */
.customer_details_page .company-details-wrapper,
.customer_details_page .customer-details-wrapper {
	padding-right: 56px;
}

/* The wrapper is the positioning context (companies/details.css:10), so the rail's own offsets
   are unaffected by the padding above -- it stays exactly where it was.

   The gutter is NOT dropped on narrow screens. Checked every rule touching either rail across
   themes/vertical and themes/default: all of them are top-level, so neither panel is hidden at
   any width and its 45px still overlaps. `@media (max-width: 900px)` at SS36 shrinks
   `.customer-details-wrapper` to `padding: 16px`, which would put the content straight back
   under the rail -- so the right side is restated here, after it, with the rail width and no
   decorative air. */
@media (max-width: 900px) {
	.customer_details_page .company-details-wrapper,
	.customer_details_page .customer-details-wrapper {
		padding-right: 48px;
	}
}

/* =========================================================================================
   18. PEOPLE ACROSS THIS GROUP (company record, Contacts tab)

   A read-only roll-up of the people at companies BELOW this one in its corporate group. It is
   styled as a distinct panel, not as more rows on the contact table above it, because the two
   answer different questions -- "who works here?" versus "who do I know across this group?" --
   and a franchise's staff appearing in the first list with no attribution is how somebody ends
   up on a corporate mailing.
   ========================================================================================= */
.gp-panel { margin-top: 18px; }
.gp-panel .ct-panel-head {
	display: flex;
	align-items: baseline;
	gap: 10px;
}
.gp-count {
	font-size: 12px;
	font-weight: 500;
	color: #8A94A6;
}
.gp-hint {
	margin: 0 0 4px;
	padding: 0 16px;
	font-size: 12.5px;
	color: #8A94A6;
}
.gp-company {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 14px 16px 6px;
}
.gp-company-name {
	font-size: 13px;
	font-weight: 600;
	color: #101A2B;
	text-decoration: none;
}
.gp-company-name:hover { color: #17803D; }
/* Only ever shown for a company in ANOTHER brand. Cross-brand children are reachable through
   the same inheritance rule that opens them read-only, so they belong here -- but an unlabelled
   row from another brand reads as one of this brand's own people. */
.gp-brand {
	padding: 2px 7px;
	border-radius: 999px;
	background: #EEF2FF;
	color: #4558A9;
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: .03em;
	text-transform: uppercase;
}
.gp-list { list-style: none; margin: 0; padding: 0; }
.gp-row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	padding: 9px 16px 9px 28px;
	border-top: 1px solid #F2F4F7;
	font-size: 13px;
}
.gp-name { font-weight: 500; color: #101A2B; text-decoration: none; }
.gp-name:hover { color: #17803D; }
.gp-role { font-size: 12px; color: #6B7280; }
.gp-main {
	padding: 1px 6px;
	border-radius: 4px;
	background: #EAF3FF;
	color: #2C5FA8;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .04em;
}
.gp-contact {
	margin-left: auto;
	font-size: 12.5px;
	color: #7C8AA0;
	/* The contact column must never push the name off the row. */
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
@media (max-width: 640px) {
	.gp-contact { margin-left: 0; flex-basis: 100%; }
}

/* =========================================================================================
   19. LIST INDEX INTRO (m=contactlist -- Contact Lists / Company Lists)

   The page sits beside "All Contacts" and, since saved searches shipped, beside those too. All
   three render as a list of records, so nothing on screen distinguished them, and the empty
   state said "Nothing found" -- the phrasing a failed SEARCH uses -- which made an index with no
   rows read as a broken query rather than as "you have not made one yet".

   This block states the purpose so the screen is legible with no data in it at all.
   ========================================================================================= */
.ct-intro {
	margin: 0 0 14px;
	padding: 14px 16px;
	background: #F7F9FC;
	border: 1px solid #E4E9F0;
	border-radius: 10px;
}
.ct-intro-lead {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.55;
	color: #344054;
}
.ct-intro-lead strong { color: #101A2B; font-weight: 650; }
.ct-intro-note {
	margin: 6px 0 0;
	font-size: 12.5px;
	line-height: 1.5;
	color: #7C8AA0;
}
/* The list index is a plain admintable, so it needs the empty-state height floor removed the
   same way the record pages did -- `.table-responsive { min-height: 200px }` is global. */
body.contactlist .table-responsive,
.tablewrapper .table-responsive { min-height: 0; }
/* A link inside an empty state must still look like one. */
td.is-empty .es-hint a { color: #17803D; text-decoration: underline; }

/* =========================================================================================
   20. LIST INDEX -- release the reserved title band (m=contactlist)

   THE BUG. §8 reserves 58px at the top of `.block-content-outer` and hoists the first toolbar
   into it with `margin-top: -58px`. On this route the toolbar sits inside `.tablewrapper`,
   which is `overflow: hidden` (§2906). A negative top margin on the FIRST child of a clipping
   box does not escape it -- the 58px is cut off, and every sibling after the toolbar is dragged
   up into the cut-off region with it. That is why the Create List / Import buttons were missing
   entirely and the intro panel showed only its last line: both were inside the clipped band.

   Same shape, same fix as §27b on m=campaigns: release the band and let the stack sit below the
   title, rather than trying to hoist something into a box that clips.

   Only four modules put a toolbar inside a `.tablewrapper` -- campaigns (already handled),
   contactlist (here), support and unassignedpartners. The other two are left alone deliberately:
   this is scoped to one body class, not applied to the shared selector, because §8's hoist is
   correct wherever the toolbar is NOT inside a clipping wrapper and I have not checked those two
   routes' layouts.
   ========================================================================================= */
body.contactlist_index .block > .body-wrapper > .block-content-outer {
	padding-top: 12px;
}
body.contactlist_index .block > .body-wrapper > .block-content-outer > .tablewrapper > .additional-buttons-section {
	margin-top: 0;
	min-height: 0;
	padding-bottom: 16px;
	align-items: center;
}
/* A CARD INSIDE A CARD. §2906 gives the card treatment -- white, rounded, shadowed -- to
   `.tablewrapper` AND `.table-responsive`, and on this route the wrapper holds the toolbar, the
   intro and the table. So the Create List / Import buttons rendered inside a white slab of their
   own, which no other list page does: everywhere else the toolbar sits on the page wash and only
   the table is a card.

   The outer wrapper is demoted to a plain block; the inner `.table-responsive` keeps the card.
   Dropping `overflow: hidden` here also removes the clipping hazard for good -- the band release
   above already stops anything being pulled into it, but a wrapper that clips its own children
   is a trap for the next person who adds a negative margin. */
body.contactlist_index .block-content-outer > .tablewrapper {
	background: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	overflow: visible;
}
/* The toolbar is now on the wash, so it no longer needs the card's inner inset. */
body.contactlist_index .block-content-outer > .tablewrapper > .additional-buttons-section {
	padding-left: 0;
	padding-right: 0;
}
body.contactlist_index .tablewrapper > .ct-intro {
	margin: 0 0 14px;
}

/* =========================================================================================
   21. PHONE NUMBERS IN LIST COLUMNS, AND THE PARENT COLUMN

   A number carrying an extension -- "+1(234) 234-2342 ext (185) 772-8993" -- is 35 characters
   with no natural break, and the Phone column is one of the narrowest on the grid. It wrapped
   to six lines and tripled the height of its row, which on a list of any length is the loudest
   thing on the screen. One line, truncated, with the whole value on hover; these tables already
   scroll horizontally, so nothing is lost.
   ========================================================================================= */
.co-phone {
	display: inline-block;
	max-width: 190px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	vertical-align: middle;
}
/* Inside a call link the anchor supplies the colour; the span only handles the overflow. */
a > .co-phone { max-width: 170px; }

/* The Parent column named the parent instead of saying "yes" (OrganizationListHelper). Keep it
   on one line too -- a company name is longer than the column, and this cell is a link, so a
   wrapped name doubles the row height the same way the phone did. */
.co-parent {
	display: inline-block;
	max-width: 170px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	vertical-align: middle;
	color: #101A2B;
	text-decoration: none;
}
.co-parent:hover { color: #17803D; text-decoration: underline; }

@media (max-width: 900px) {
	.co-phone, a > .co-phone, .co-parent { max-width: 130px; }
}

/* =========================================================================================
   22. CONTACT LIST DETAIL TOOLBAR -- Advanced Search beside the filters, not adrift

   The gap between "All Statuses" and "Advanced Search" was an empty <div> doing a job nobody
   could see: `.additional-buttons-section .pipeline-dropdown { flex-grow: 1 }`
   (stylesheets.css:2538). contactlist.php emits that div with no content, so it collapsed to
   zero width and then expanded to eat every spare pixel, shoving the button to the far edge --
   which read as two unrelated toolbars rather than one row of filters.

   Scoped to this route rather than fixed at source: ten-plus modules emit the same empty div
   and several rely on it AS the spacer, so `:empty { flex-grow: 0 }` globally would re-flow
   toolbars across the app. This page does not need it -- it already has a real `.flex-1`
   spacer after the button (contactlist.php:696) for anything that must sit right.
   ========================================================================================= */
body.contacts_list_details .additional-buttons-section .pipeline-dropdown:empty {
	flex-grow: 0;
	flex-basis: 0;
	width: 0;
}
/* One consistent gap between every control in the row, instead of whatever each widget's own
   margin happened to be. */
body.contacts_list_details .additional-buttons-section.extended-buttons {
	gap: 10px;
	align-items: center;
}
/* The search box, the status select and the button are three different widgets from three
   different templates; pin them to one height so the row reads as a single control strip. */
body.contacts_list_details .additional-buttons-section .ab-button,
body.contacts_list_details .additional-buttons-section .nice-select,
body.contacts_list_details .additional-buttons-section input.form-search {
	min-height: 42px;
}
body.contacts_list_details .additional-buttons-section > .buttons {
	display: flex;
	align-items: center;
	margin: 0;
}

/* =========================================================================================
   23. BRAND TAGS (Ticket 7)

   A brand tag is a VISIBILITY GRANT, not a label: tagging a record with `Nibble` lets Nibble's
   team see and work it. That is why the chips are shown wherever the record is, rather than only
   on the settings screen the feature originally hid behind -- somebody reading a list needs to
   know which brands can see the row they are looking at.

   The home brand always renders first and is styled differently: it OWNS the record and cannot
   be removed, while every other chip can be revoked by unticking it.
   ========================================================================================= */
.bt-chips {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 4px;
	align-items: center;
}
.bt-chip {
	display: inline-block;
	padding: 2px 8px;
	border-radius: 999px;
	background: #EEF2FF;
	color: #4558A9;
	border: 1px solid #DDE3F7;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
}
/* The owning brand, in the dlivrd navy so it reads as the anchor rather than one tag among many. */
.bt-chip.is-home {
	background: #14204A;
	border-color: #14204A;
	color: #FFFFFF;
}

/* ---- the panel on the record ---- */
.bt-panel { margin-bottom: 16px; }
.bt-opts {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: 8px 16px;
	padding: 4px 16px 8px;
}
.ct-brandform .ct-brandopt {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 8px 10px;
	border: 1px solid #E4E7EC;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: 13px;
	font-weight: 500;
	color: #101A2B;
	cursor: pointer;
}
.ct-brandform .ct-brandopt:hover { border-color: #B9C2D0; background: #FAFBFD; }
.ct-brandform .ct-brandopt i {
	font-style: normal;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #6E7A8C;
}
/* The home row cannot be unticked, so it must not invite the click. */
.ct-brandform .ct-brandopt.is-home {
	background: #F4F6FA;
	border-color: #DDE3EC;
	cursor: default;
}
.bt-table-wrap { overflow-x: auto; }
.bt-status td, .bt-status th { padding: 10px 16px; }
.bt-select {
	min-height: 36px;
	padding: 6px 10px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	font-size: 13px;
	background: #FFFFFF;
}
.bt-select:focus { outline: none; border-color: #4ED84A; box-shadow: 0 0 0 3px rgba(78, 216, 74, .18); }

/* The brand-tag multi-select. `size` keeps it from collapsing to a one-line box that hides the
   fact several brands can be picked at once -- AC2 is "one OR multiple". */
.xs-multi {
	min-height: 96px;
	padding: 6px;
}
.xs-multi option { padding: 4px 6px; border-radius: 4px; }
.xs-hint-sm {
	display: block;
	margin-top: 4px;
	font-size: 11.5px;
	color: #8A94A6;
}

/* =========================================================================================
   24. DLIVRD PALETTE

   Retheme to the dlivrd.io identity: deep navy ground, bright green action colour.

   THE ONE THING THAT CONSTRAINS THIS. The brand green (#5CE55C on the site) is 1.64:1 on
   white -- unusable for text at any size. The site itself never uses it as text: "Partner With
   Us" is a green FILL with a dark label. So the green is taken as a fill colour with a navy
   label (7.47:1), and links and active states on white use a deepened green (#17803D, 5.01:1).
   Every value below was measured, not eyeballed:

       #5CE55C text on white ......... 1.64:1   rejected
       #17803D text on white ......... 5.01:1   PASS  -> --accent-text
       navy label on #3FBF3C ......... 7.47:1   PASS  -> --accent-fill + --accent-on-fill
       white label on #3FBF3C ........ 2.41:1   rejected
       white on #0E1A3C .............. 17.05:1  PASS  -> sidebar

   Declared as a token override rather than by editing the block at the top of this file, so the
   previous palette is still readable directly above it and the change is one block to revert.
   ========================================================================================= */
:root {
	--accent:      #3FBF3C;
	--accent-fill: #3FBF3C;   /* action fill */
	--accent-hot:  #35A833;   /* hover for a filled action */
	--accent-text: #17803D;   /* the accent as TEXT on a light ground */
	--accent-tint: #EBF9EB;

	/* The label that sits ON --accent-fill. Was implicitly white; with a green fill white is
	   2.41:1, so it becomes the brand navy. */
	--accent-on-fill: #0B1533;

	--surface-ink: #0E1A3C;   /* sidebar / dark chrome */
	--focus-ring: 2px solid #0E1A3C;
}

/* The primary action: green fill, navy label -- the site's own button, not white-on-green. */
.ab-button.primary,
input[type="submit"].primary,
button[type="submit"].primary,
.adminform_savebutton input[type="submit"],
.xs-btn.xs-primary,
.ss-btn.ss-primary {
	background: var(--accent-fill);
	border-color: var(--accent-fill);
	color: var(--accent-on-fill);
	font-weight: 650;
}
.ab-button.primary:hover,
input[type="submit"].primary:hover,
button[type="submit"].primary:hover,
.adminform_savebutton input[type="submit"]:hover,
.xs-btn.xs-primary:hover,
.ss-btn.ss-primary:hover {
	background: var(--accent-hot);
	border-color: var(--accent-hot);
	color: var(--accent-on-fill);
}

/* Anything still hard-coding the old orange. These were written before the token block existed;
   listed explicitly rather than with a global find-replace so each one stays greppable. */
.profile-section .main_buttons a.profile-btn-follow:hover,
.profile-section .main_buttons a.profile-btn-follow:focus-visible { background: var(--accent-tint); }
.customer_details_page .profile-active .nav-tabs > li.active > a,
.profile-active .nav-tabs > li.active > a,
.nav-tabs > li.active > a:hover,
.nav-tabs > li.active > a:focus {
	border-bottom-color: var(--accent);
	color: var(--accent-text);
}
.ct-name:hover, .gp-name:hover, .gp-company-name:hover,
.ss-apply:hover .ss-name, .co-parent:hover,
.profile-section .customer-phone a:hover { color: var(--accent-text); }
.xs-input:focus, .ss-input:focus, .ct-search input[type="search"]:focus,
.customer_details_page .profile-active .rd-dash-conversation-answer textarea:focus {
	border-color: var(--accent);
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .18);
}
.ct-toolbar > .ct-add,
.gp-panel .ct-panel-head { color: inherit; }

/* The sidebar picks up the brand navy. One variable, because the rail, its active row and the
   avatar mark all derive from it. */
.left-side, .sidebar, aside.main-sidebar, .main-sidebar {
	background: var(--surface-ink);
}
.profile-section .customer-icon,
.profile-section .company-icon {
	background: var(--surface-ink);
	box-shadow: 0 0 0 4px #F4F6F9, 0 2px 6px rgba(11, 21, 51, .18);
}

/* 23.1 Brand Segmentation report (Ticket 7, AC2 -- the reports half). */
.br-filter { margin-bottom: 16px; }
.br-filter-row {
	display: flex;
	align-items: flex-end;
	gap: 16px;
	flex-wrap: wrap;
	padding: 16px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
}
.br-filter-row .xs-field { flex: 0 1 320px; }
.br-filter-actions { display: flex; align-items: center; gap: 12px; padding-bottom: 2px; }
.br-table th.br-num, .br-table td.br-num { text-align: right; white-space: nowrap; }
.br-table td.br-num a { color: var(--accent-text); text-decoration: none; font-weight: 600; }
.br-table td.br-num a:hover { text-decoration: underline; }
.br-total td {
	border-top: 2px solid #E4E7EC;
	font-weight: 700;
	color: #101A2B;
	background: #FAFBFD;
}

/* 23.2 Brand tag panel -- tightened, and identical on companies and contacts.

   The two panels are rendered by one class (GS\Brands\BrandPanel), so they cannot drift; these
   rules are what make the result look deliberate rather than like a form dropped on a card. */
.bt-panel .ct-panel-head {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: #98A2B3;
	padding: 16px 18px 0;
	border: 0;
}
.bt-panel .ct-hint {
	margin: 6px 0 0;
	padding: 0 18px;
	font-size: 13px;
	line-height: 1.5;
	color: #7C8AA0;
}
.bt-opts {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
	gap: 8px;
	padding: 14px 18px 4px;
}
.ct-brandform .ct-brandopt {
	min-height: 44px;          /* one height for every option, however long the name wraps */
	gap: 10px;
	padding: 10px 12px;
	border-radius: 10px;
	line-height: 1.35;
}
.ct-brandform .ct-brandopt.is-home { background: #F4F6FA; border-color: #DDE3EC; }
.ct-brandform .ct-brandopt i { margin-left: auto; }
.ct-brandform .pr-save { padding: 14px 18px 18px; }

/* The status table is a plain two-column table -- deliberately NOT inside an overflow wrapper,
   which clipped the niceSelect dropdown that luna.js attaches to every select. */
.bt-status { width: 100%; }
.bt-status th {
	font-size: 11px;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #98A2B3;
}
.bt-status th, .bt-status td { padding: 12px 18px; }
.bt-status td:last-child, .bt-status th:last-child { width: 260px; }
/* niceSelect replaces the <select> with its own markup; give that the same footprint so the
   row does not change height when the plugin initialises. */
.bt-status .nice-select { min-height: 40px; line-height: 38px; width: 100%; }
.bt-status .nice-select .list { width: 100%; }
.bt-pending td { background: #FCFDFE; }
.bt-pending .ct-chip i { color: #98A2B3; }

/* 23.3 Save-on-toggle feedback. The Save button is gone -- the tick is the decision -- so the
   panel has to say that something happened, and say it where the eye already is. */
.bt-status-note {
	padding: 0 18px 16px;
	font-size: 12.5px;
}
.bt-saved {
	display: inline-block;
	padding: 3px 10px;
	border-radius: 999px;
	background: #EBF9EB;
	border: 1px solid #CBEBCB;
	color: #17803D;
	font-weight: 600;
}
/* No-JS only: the script hides this as soon as it binds, so a working browser never sees it. */
.bt-fallback-save { padding: 14px 18px 18px; }

/* 25. DEAL BOARD -- the "+ Add" belongs at the FOOT of its column, always.

   `customerspipeline.tpl:115` already emits it after the card loop, and `.leadcontainer` is a
   `display: table-cell` (referraldraganddrop.css:70), so in source order it is last. It was
   still reading as a control between the header and the first card.

   Making the column a flex column and pushing the button with `margin-top: auto` fixes it
   whatever the cause: the button lands at the END of the stack, and in a short column it sits at
   the BOTTOM rather than floating directly under the last card -- which is what "at any case
   keep it at the end" asks for. `order` as well as auto-margin, so it stays last even if
   something reorders the children.

   Was scoped to body.deals alone because the Contact Pipeline -- same template -- was not what
   had been reported. On 11 Sep 2026 it was: see section 26.7. The two boards now share every
   board rule through `body:is(.deals, .customers_pipeline_view)`, which has the specificity of
   `body.deals` exactly, so nothing on the deal board moved. */
body:is(.deals, .customers_pipeline_view) .leadcontainer {
	display: flex;
	flex-direction: column;
	/* was table-cell; the row is a flex container on this board, so the column can be too */
	vertical-align: top;
}
body:is(.deals, .customers_pipeline_view) .leadcontainer > div { flex: 0 0 auto; }
body:is(.deals, .customers_pipeline_view) .leadcontainer .showmoreleads {
	order: 99;
	margin-top: auto;
	padding-top: 8px;
}
/* A column with no cards must still give the button somewhere to sit, or it collapses onto the
   header. */
body:is(.deals, .customers_pipeline_view) .leadcontainer { min-height: 160px; }

/* 25.1 Pipeline drag affordances. */
body.deals .li-pipe-card { cursor: grab; }
body.deals .li-pipe-card:active { cursor: grabbing; }
body.deals .li-pipe-card.is-dragging { opacity: .45; }
body.deals .li-pipe-body {
	/* A column with one card must still be a target big enough to aim at. */
	min-height: 90px;
	border-radius: 10px;
	transition: background-color .12s ease, box-shadow .12s ease;
}
body.deals .li-pipe-body.is-over {
	background: #EBF9EB;
	box-shadow: inset 0 0 0 2px #3FBF3C;
}

/* =========================================================================================
   26. DEAL DETAIL -- THE SURFACE UNDER THE HEADER

   WHAT WAS ACTUALLY WRONG. Nothing on `m=deals&d=view` was a card. `.content` is
   `background: #F2F2F2` (styles/style.css:960) and neither `.block` nor `.block-content-outer`
   paints over it on this route -- verified by parsing every one of the 33 stylesheets the page
   loads and looking for a background on any `block*` selector: two hits, neither on this path.
   So the header, the toolbar, the board heading and the five columns were four loose blocks on
   bare wash, and the board -- the whole point of the screen -- had no edge at all.

   THREE BANDS, NOT ONE SLAB. The header is a card, the toolbar sits on the wash, the board is a
   card. That is the rhythm every list in this app already uses (see the note at section 20 on
   m=contactlist: "everywhere else the toolbar sits on the page wash and only the table is a
   card"), and wrapping the toolbar in white as well would have produced the card-inside-a-card
   this file has already had to unpick once.

   ONE SKIN FOR ONE TEMPLATE. `customerspipeline.tpl` renders both this board and the Contact
   Pipeline (m=customers&d=list, body.customers_pipeline_view). This section was first scoped
   to body.deals alone -- the Contact pipeline had not been reported, and an unstyled
   `.board-card` div is a no-op -- so for ten days the same DOM wore two skins: this one on
   Deals, and the 2019 `#ECEAE8` slab with 360px columns on Contacts. On 11 Sep 2026 the
   Contact board WAS reported (it had vanished for brand 1 behind an empty
   `company_pipeline`, see TCompany::CompanyPipeline()), and once it was back the gap was the
   next thing anyone would see.

   So every board rule below is `body:is(.deals, .customers_pipeline_view)`. `:is()` takes the
   specificity of its most specific argument -- one class -- which is what `body.deals` had, so
   the cascade on Deals is unchanged. Rules for things only the deal routes have (`.deal-head`,
   `.deal-toolbar`, `.li-pipe-*`) keep `body.deals`. What only the Contact board has is in 26.7.
   ========================================================================================= */

/* 26.1 The two cards. */
body.deals .deal-head,
body:is(.deals, .customers_pipeline_view) .board-card {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 12px;
	box-shadow: var(--sh-1);
}

body.deals .deal-head {
	padding: 16px 20px;
	margin-bottom: 12px;
}

body:is(.deals, .customers_pipeline_view) .board-card {
	padding: 16px 20px 18px;
}

/* The toolbar is the band BETWEEN them and keeps its own margins. `.deal-toolbar-form` carries
   a 12px bottom margin from section 5046 which, in a row that is `align-items: center`, pushes
   the search field up against the buttons beside it. */
body.deals .deal-toolbar { margin: 0 0 12px; }
body.deals .deal-toolbar-form { margin-bottom: 0; }

/* 26.2 The board heading, now inside the card it describes.
   A rule under it rather than a gap: the heading names the columns below, and a hairline says
   "these belong together" where whitespace only says "these are two things". */
body:is(.deals, .customers_pipeline_view) .board-card .board-head {
	margin: 0 0 14px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--line);
}
body:is(.deals, .customers_pipeline_view) .board-title { font-size: 15px; }
body:is(.deals, .customers_pipeline_view) .board-sub { font-size: var(--fs-sm); }

/* The wrapper bleeds 10px each side to cancel the 10px column gutter
   (referraldraganddrop.css:290). The gutter is 6px now, so the bleed has to be 6px or the card
   loses its left padding. */
body:is(.deals, .customers_pipeline_view) .board-card .draggable-wrapper {
	margin-left: -6px;
	width: calc(100% + 12px);
}

/* 26.3 COLUMNS THAT FIT THE CARD.
   `min-width: 360px` on both the header cell and the column (referraldraganddrop.css:19, :69)
   is 1800px for the five default stages -- section 35.5 measured 705px of it off-screen, which
   is why Sold and Lost were invisible on a 1440 display. 240px is enough for a name, a company
   and an email, and `flex: 1 1 240px` also fixes the opposite case: `width: 20%` left a
   three-stage pipeline using 60% of the card with 40% blank beside it.

   The header row and the column row are separate flex containers, so the two must be given the
   SAME basis and the same gutter or the labels stop lining up with what they label. */
body:is(.deals, .customers_pipeline_view) .dragable-header .wrapper .headerstep,
body:is(.deals, .customers_pipeline_view) .dragable-container .wrapper > div {
	flex: 1 1 240px;
	width: auto;
	min-width: 240px;
	padding: 0 6px;
}
body:is(.deals, .customers_pipeline_view) .dragable-header .wrapper .headerstep { padding-top: 0; padding-bottom: 0; }

/* 26.4 The column header.
   Was a centred `#ECEAE8` slab -- a warm grey that reads as dirty on white. Now a label row:
   stage on the left, count on the right, a coloured spine on the leading edge.

   The spine is a border rather than the template's own accent `<span>`, which carries the
   Tailwind class `bg-primary-500` and no Tailwind is loaded on this route, so it has never
   painted anything. Only `sold` and `lost` get a colour of their own: those two class names are
   the stage KEY, and a brand may define stages this file has never heard of, so everything else
   takes the neutral spine rather than a wrong one. */
body:is(.deals, .customers_pipeline_view) .customers.dragable-header .wrapper .headerstep > div {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	background: var(--surface-alt);
	border: 1px solid var(--line);
	border-left: 3px solid #C9D2DE;
	border-radius: 10px;
	padding: 9px 12px;
	margin-bottom: 10px;
	text-align: left;
	box-shadow: none;
}
body:is(.deals, .customers_pipeline_view) .headerstep.sold > div { border-left-color: #17803D; }
body:is(.deals, .customers_pipeline_view) .headerstep.lost > div { border-left-color: #B3261E; }

body:is(.deals, .customers_pipeline_view) .headerstep > div > span.absolute { display: none; }

body:is(.deals, .customers_pipeline_view) .headerstep > div > span:not(.absolute):not(.total-count) {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--ink);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

body:is(.deals, .customers_pipeline_view) .dragable-header .wrapper .headerstep .total-count {
	flex: 0 0 auto;
	min-width: 22px;
	margin: 0;
	padding: 1px 7px;
	border-radius: 999px;
	background: var(--surface-mute);
	font-size: 11px;
	font-weight: 600;
	color: var(--text-muted);
}

/* 26.5 The column itself is a track, so an empty stage still looks like somewhere a card can
   go. Section 25 gave it a 160px floor for the "+ Add" button; a track needs a little more. */
body:is(.deals, .customers_pipeline_view) .leadcontainer {
	min-width: 0;
	min-height: 190px;
	padding: 10px;
	background: var(--surface-alt);
	border: 1px solid var(--line);
	border-radius: 10px;
}
/* Section 25.1 paints the pipeline board's drop target green. Same signal here, replacing the
   orange tint that was the odd one out. */
.leadcontainer.is-over {
	background: #EBF9EB;
	box-shadow: inset 0 0 0 2px #3FBF3C;
}

/* 26.6 THE CARD.
   `padding: 20px 30px` and a 25px gap made a card ~150px tall to carry five short lines, so
   three cards filled a column and the board could not be read without scrolling. The content is
   unchanged -- every field the template emits is still on the card -- it is the spacing and the
   type scale that were wrong. */
body:is(.deals, .customers_pipeline_view) .leadcontainer > div[id] {
	margin: 0 0 10px;
	padding: 11px 13px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .05);
	transition: border-color .12s ease, box-shadow .12s ease;
}
body:is(.deals, .customers_pipeline_view) .leadcontainer > div[id]:hover {
	border-color: #C9D2DE;
	box-shadow: var(--sh-2);
}

/* The name is the card. The "Name:" label in front of it is the one piece of text on here that
   tells the reader nothing they could not see, and it was competing with the value it labels. */
body:is(.deals, .customers_pipeline_view) .leadcontainer .name {
	margin: 0 0 7px;
	padding: 0 22px 0 0;
	border-bottom: 0;
}
body:is(.deals, .customers_pipeline_view) .leadcontainer .name > label { display: none; }
body:is(.deals, .customers_pipeline_view) .leadcontainer .name a {
	font-size: 14px;
	font-weight: 600;
	line-height: 19px;
	color: var(--ink);
}
body:is(.deals, .customers_pipeline_view) .leadcontainer .name a:hover { color: #17803D; }

/* Company / phone / email. One line each, truncated rather than wrapped: an address like
   abdul@gmail.com is fine at 240px and a long one would otherwise take three lines and push the
   value off the bottom of the card. `display: block` and not flex, because the ellipsis has to
   apply to the label and the value together -- the value is a bare text node on two of the
   three rows and cannot be given an overflow of its own. */
body:is(.deals, .customers_pipeline_view) .leadcontainer .cellphone {
	display: block;
	margin: 0 0 3px;
	font-size: 12.5px;
	font-weight: 400;
	line-height: 17px;
	color: var(--text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
body:is(.deals, .customers_pipeline_view) .leadcontainer .cellphone > label,
body:is(.deals, .customers_pipeline_view) .leadcontainer .confidence_level > label,
body:is(.deals, .customers_pipeline_view) .leadcontainer .contact_point_count > label {
	margin-right: 5px;
	font-size: 11px;
	font-weight: 500;
	color: #8A97A8;
}
body:is(.deals, .customers_pipeline_view) .leadcontainer .cellphone a { color: var(--text); }
body:is(.deals, .customers_pipeline_view) .leadcontainer .cellphone a:hover { color: #17803D; }

/* Confidence and Touches are two numbers, not two paragraphs. */
body:is(.deals, .customers_pipeline_view) .leadcontainer .confidence_level,
body:is(.deals, .customers_pipeline_view) .leadcontainer .contact_point_count {
	display: inline-block;
	margin: 5px 10px 0 0;
	font-size: 11.5px;
	line-height: 16px;
	color: var(--text-muted);
}
body:is(.deals, .customers_pipeline_view) .leadcontainer .confidence_level b,
body:is(.deals, .customers_pipeline_view) .leadcontainer .contact_point_count b { color: var(--ink); }

body:is(.deals, .customers_pipeline_view) .dragable-container .value {
	margin-top: 9px;
	padding: 8px 0 0;
	border-top: 1px solid #EEF1F4;
	font-size: 13px;
	font-weight: 700;
	color: #17803D;
}

/* The edit menu sat 20px in from a 30px padding box; with 13px of padding it needs to move, and
   the name row above is what it would otherwise overlap (hence the 22px right padding there). */
body:is(.deals, .customers_pipeline_view) .leadcontainer .delete_edit_lead {
	right: 8px;
	top: 8px;
	margin-top: 0;
}

/* Two `.locationwrap` divs are emitted per card for labels a deal never sets -- member type,
   approval, location, unread, tags -- and each contributes `margin-top: 5px` and a table box to
   a card that has nothing to put in it. `:not(:has(*))` and not `:empty`, which the template's
   own indentation defeats: the div contains a whitespace text node. */
body:is(.deals, .customers_pipeline_view) .leadcontainer .locationwrap:not(:has(*)) { display: none; }

/* The track has its own 10px inset now, so the button's `padding: 0 10px !important`
   (referraldraganddrop.css:96) doubles it and the "+ Add" ends up narrower than the cards it
   sits under. !important is the only thing that beats an !important. */
body:is(.deals, .customers_pipeline_view) .leadcontainer .showmoreleads { padding: 0 !important; }

/* The empty board. Not a column state -- the template emits this once, beside the columns, when
   the deal has nobody on it at all. */
body:is(.deals, .customers_pipeline_view) .nodatafound {
	padding: 30px 16px;
	color: var(--text-muted);
	font-size: var(--fs-md);
}

@media (max-width: 767px) {
	body.deals .deal-head { padding: 14px 15px; }
	body:is(.deals, .customers_pipeline_view) .board-card { padding: 14px 12px 16px; }
	body:is(.deals, .customers_pipeline_view) .dragable-header .wrapper .headerstep,
	body:is(.deals, .customers_pipeline_view) .dragable-container .wrapper > div { flex: 0 0 220px; min-width: 220px; }
}

/* 26.7 CONTACT PIPELINE -- what this board has that the deal board does not.

   Same template, same card, same column; four things the deal board never emits and so
   section 26 never had to place: a money line in every stage header (MRR/ARR per stage,
   `customerspipeline.tpl:36-47`), a totals line above the columns, chips on the cards (member
   type, approval, location, unread, e-mail status, tags) and the vertical "Add Column" rail.
   Everything below is scoped to body.customers_pipeline_view and touches only those four.

   THE MONEY LINE IS THE ONE THING WORTH LOOKING AT. Every other element on this board says
   who is where; this one says what the stage is worth, and it is the reason a manager opens
   the board rather than the list. It was a bold 14px "MRR: $0.00  ARR: $0.00" row ABOVE the
   stage name -- louder than the name, and identical on the seven stages that carry nothing.
   Now it is the second line of the header, 11px, and it reads `data-amount`: a stage worth
   nothing fades to the faint tone, a stage worth something keeps the ink. The attribute is
   the same one customerdraganddrop.js:59-62 rewrites on every drop, so the emphasis follows
   the cards without a line of new script. */

/* The header wraps to two lines: name + count on the first, money on the second. The money
   block sits BEFORE the name in the DOM (it used to be above it), so it is ordered last. */
body.customers_pipeline_view .customers.dragable-header .wrapper .headerstep > div {
	flex-wrap: wrap;
	row-gap: 5px;
	padding: 9px 12px 8px;
}
/* The name takes what the pill leaves. Shared rule 26.4 gives it `flex: 0 1 auto` (max-content
   basis), so a stage name past ~190px made the row wrap BEFORE the pill and parked "0" alone on
   a second line. A zero basis cannot trigger a wrap; the ellipsis from 26.4 does the rest. */
body.customers_pipeline_view .headerstep > div > span:not(.absolute):not(.total-count) {
	flex: 1 1 0;
	min-width: 0;
}
body.customers_pipeline_view .headerstep > div > .flex {
	order: 3;
	flex: 1 1 100%;
	display: flex;
	gap: 12px;
	margin: 0;            /* .mb-10 is 10px under the row it no longer sits above */
	min-width: 0;
}
body.customers_pipeline_view .headerstep > div > .flex > .w-50 {
	width: auto;
	flex: 0 1 auto;
	min-width: 0;
}
/* Outer wrapper per figure ("MRR:" + value) and the inner value span share the class
   `.total-value` (referraldraganddrop.css:23 floats both right). Element names tell them
   apart. */
/* The selector carries the full `.dragable-header .wrapper .headerstep` chain on purpose:
   referraldraganddrop.css:23 styles `.total-value` at (0,4,0), and a shorter scoped selector
   here at (0,3,3) LOST to it -- the money rendered 14px/600/#0F0F0F with only the zero rule
   (which happened to be (0,4,3)) taking effect. */
body.customers_pipeline_view .dragable-header .wrapper .headerstep div.total-value {
	float: none;
	display: inline-flex;
	align-items: baseline;
	gap: 4px;
	width: auto;
	font-size: 11px;
	font-weight: 500;
	line-height: 14px;
	color: var(--text-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
body.customers_pipeline_view .dragable-header .wrapper .headerstep div.total-value > .mr-10 { margin-right: 0; }
body.customers_pipeline_view .dragable-header .wrapper .headerstep span.total-value {
	float: none;
	width: auto;
	font-size: 11px;
	font-weight: 600;
	color: var(--ink-2);
}
body.customers_pipeline_view .dragable-header .wrapper .headerstep span.total-value[data-amount="0"] {
	font-weight: 500;
	color: var(--text-muted);   /* 4.1:1 on the slab -- AA for the figure, still a step under --ink-2 */
}

/* The totals line. Was `pull-right mb-10`, a float hanging over the top-right corner of the
   header row. Now the first line inside the card, with a rule under it like the deal board's
   heading (26.2) -- it describes the columns below the same way. */
body.customers_pipeline_view .board-card .total_values_info {
	float: none !important;   /* bootstrap .pull-right is `float: right !important` */
	width: 100%;
	display: flex;
	justify-content: flex-end;
	margin: 0 0 12px;
	padding: 0 0 10px;
	border-bottom: 1px solid var(--line);
	font-size: var(--fs-sm);
	color: var(--text-muted);
}
body.customers_pipeline_view .board-card .total_values_info .mr-10 { margin-right: 14px; }
body.customers_pipeline_view .board-card .total_values_info strong {
	font-weight: 600;
	color: var(--ink);
}

/* Nine stages do not fit 1440px at 240px each; the wrapper already scrolls sideways
   (referraldraganddrop.css:299 overflow: auto). Room for the bar, so it does not sit on the
   column footers, and a pale bar so it is a hint rather than a chrome element. */
body.customers_pipeline_view .board-card .draggable-wrapper {
	padding-bottom: 8px;
	scrollbar-width: thin;
	scrollbar-color: #C9D2DE transparent;
}
body.customers_pipeline_view .board-card .draggable-wrapper::-webkit-scrollbar { height: 8px; }
body.customers_pipeline_view .board-card .draggable-wrapper::-webkit-scrollbar-thumb {
	background: #C9D2DE;
	border-radius: 999px;
}

/* CHIPS. One grammar for every badge the card can carry. The legacy set is four unrelated
   pills -- a violet `.label-info` (with !important on its background, hence the !important
   here and nowhere else), a coral `.label-warning`, Bootstrap's grey `.label-default` and its
   red `.label-danger` -- floated left inside a `display: table` wrapper. Now: one shape, one
   size, tone by meaning. Neutral for facts (location, member type, tags), green for a
   verified e-mail, red for an invalid one or an unread thread, amber for "Not Approved". */
body.customers_pipeline_view .leadcontainer .locationwrap {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	width: auto;
	margin-top: 8px;
}
body.customers_pipeline_view .leadcontainer .locationwrap:first-child { margin-top: 0; }
body.customers_pipeline_view .leadcontainer .label,
body.customers_pipeline_view .leadcontainer .location {
	float: none;
	display: inline-block;
	margin: 0;
	padding: 2px 8px;
	border: 0;
	border-radius: 999px;
	background: var(--surface-mute) !important;
	font-size: 11px;
	font-weight: 500;
	line-height: 16px;
	color: var(--text);
	text-decoration: none;
	white-space: nowrap;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
}
/* Tags inside .locationwrap are coloured BY POSITION elsewhere -- styles.css:684-720 rotates
   dark / indigo / blue over nth-child with `color: #fff !important` on the first. Position says
   nothing about a tag, and on a board it makes the first chip of every card the loudest thing
   on it. The !important on colour is the only way past that one; it is scoped to this board. */
body.customers_pipeline_view .leadcontainer .locationwrap > a {
	color: var(--text) !important;
	font-weight: 500;
	font-size: 11px;
	padding: 2px 8px;
	border-radius: 999px;
	white-space: nowrap;
}
body.customers_pipeline_view .leadcontainer a.label:hover,
body.customers_pipeline_view .leadcontainer a.location:hover,
body.customers_pipeline_view .leadcontainer .locationwrap > a:hover { color: var(--ink) !important; }
/* Member type / approval chips are emitted before .locationwrap, as loose siblings. */
body.customers_pipeline_view .leadcontainer .referral-label { margin: 0 4px 6px 0; }
/* Colour is !important on the three tones as well: the positional-tag override above had to
   be !important to beat styles.css:696, and without matching weight here a "Do Not Text"
   (label-danger) or "No Response" (label-warning) tag inside .locationwrap kept its red or
   amber tint with slate text -- half a chip. */
body.customers_pipeline_view .leadcontainer .label-success {
	background: var(--success-tint) !important;
	color: var(--success) !important;
}
body.customers_pipeline_view .leadcontainer .label-danger {
	background: var(--danger-tint) !important;
	color: var(--danger) !important;
}
body.customers_pipeline_view .leadcontainer .not-approved,
body.customers_pipeline_view .leadcontainer .label-warning {
	background: var(--warning-tint) !important;
	color: var(--warning) !important;
}
/* The e-mail status chip is emitted straight after the e-mail row with the `.location` float;
   it is a line of its own now, spaced like the rows around it. */
body.customers_pipeline_view .leadcontainer .cellphone + .location { margin: 2px 0 4px; }

/* A card worth nothing should not close on a bold green figure. The template emits a hidden
   `<span id="amount_N" data-amount="...">` just before `.value` -- the same span
   customerdraganddrop.js:53 reads -- so a zero can be told apart without touching PHP. */
body.customers_pipeline_view .dragable-container span[data-amount="0"] + .value {
	color: var(--text-muted);   /* 4.4:1 on the card; the green non-zero figure is the contrast */
	font-weight: 600;
}

/* The star that marks an opportunity owner sits inside .name before the label. */
body.customers_pipeline_view .leadcontainer .name > a .fa,
body.customers_pipeline_view .leadcontainer .name > a > i {
	margin-right: 5px;
	font-size: 12px;
	color: var(--warning);
	vertical-align: 1px;
}

/* The note. `max-width: 250px; display: inline-block` (referraldraganddrop.css:121) let it
   run beside whatever preceded it; it is a row like the others, in the meta tone. */
body.customers_pipeline_view .leadcontainer .note {
	display: block;
	max-width: none;
	margin: 6px 0 0;
	font-size: 12px;
	line-height: 16px;
	color: var(--text-muted);
	word-wrap: break-word;
}
body.customers_pipeline_view .leadcontainer .note > label {
	margin-right: 5px;
	font-size: 11px;
	font-weight: 500;
	color: #8A97A8;
}

/* "Show All" under a capped column (the lost column shows ten). A quiet full-width link,
   not a raised button competing with the cards above it. */
body.customers_pipeline_view .leadcontainer .showmoreleads .ab-button {
	display: block;
	width: 100%;
	padding: 7px 10px;
	border: 1px dashed var(--line-strong);
	border-radius: 8px;
	background: transparent;
	font-size: var(--fs-sm);
	font-weight: 500;
	text-align: center;
	color: var(--text);   /* the only copy in the control: 7:1 on the track, not the 4.1:1 meta tone */
}
body.customers_pipeline_view .leadcontainer .showmoreleads .ab-button:hover {
	border-color: #C9D2DE;
	color: var(--ink);
	background: var(--surface);
}

/* "Add Column": the vertical rail at the end of the row, kept vertical -- it is the one
   control that earns its place in the gutter rather than a column of its own -- but drawn as
   the track it would become, not a raised white pill. */
body.customers_pipeline_view .add-new-column-button {
	align-self: stretch;
	margin: 0 6px 0 4px;
	/* --text-soft, not --line-strong: a control's boundary and glyph want 3:1 (WCAG 1.4.11);
	   the hairline token is 1.2:1 on white and reads as nothing there. */
	border: 1px dashed var(--text-soft);
	border-radius: 10px;
	background: transparent;
}
body.customers_pipeline_view .add-new-column-button a {
	height: 100%;
	padding: 14px 9px;
	gap: 6px;
	font-size: var(--fs-sm);
	font-weight: 500;
	color: var(--text);
}
body.customers_pipeline_view .add-new-column-button a svg {
	width: 16px;
	height: 16px;
	margin: 0;
	color: var(--text-soft);
}
body.customers_pipeline_view .add-new-column-button:hover { border-color: var(--text-muted); background: var(--surface-alt); }
body.customers_pipeline_view .add-new-column-button:hover a { color: var(--ink); }
body.customers_pipeline_view .add-new-column-button:hover a svg { color: var(--ink); }

@media (max-width: 767px) {
	body.customers_pipeline_view .headerstep > div > .flex { gap: 8px; }
	body.customers_pipeline_view .board-card .total_values_info { justify-content: flex-start; }
}

/* =========================================================================================
   27. DEALS LIST -- ONE TOOLBAR ROW, AND A PIPELINE PICKER THAT IS NOT A FULL-WIDTH SLAB

   Two things were wrong and only one of them was spacing.

   THE PICKER. `.deal-pipe-bar select { min-width: 180px }` (lineitems.css:231) has never applied
   to anything a user can see. luna.js:30 runs `$('select').niceSelect()` on every page, which
   hides the <select> and inserts a `.nice-select` DIV beside it -- and stylesheets.css:1711
   declares that div `width: 100%; height: 45px`. So the Pipeline control was the full width of
   the page and 3px taller than everything beside it. Section 20 paid for exactly this on the
   deal board's own toolbar; same cause, same fix, one screen later.

   THE SPACING. The button was in an `.additional-buttons-section` of its own, above the pipeline
   row, above the search row -- three stacked rows where Contacts and Companies each have one.
   That block is also what held section 8's 58px title band open on this route, because section
   26.1 releases the band with a `:has()` test for that very class. Folding "+ New deal" into the
   toolbar row (deals.php) removes the block, which releases the band, which is what makes the
   spacing match the other two lists. Nothing here tunes a number by hand.
   ========================================================================================= */

/* 27.1 The picker, sized to the row it now sits in -- 42px, the height of `.ct-search`'s input
   and of `.ct-add`. The open list is `position: absolute; width: 100%` against this wrapper, so
   it follows the 240px without a rule of its own. */
.deal-pipe-bar .nice-select {
	flex: 0 0 240px;
	width: 240px;
	height: 42px;
	padding: 0 34px 0 13px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	font-weight: 400;
	color: #101A2B;
}

/* The real <select> underneath, for the no-JS case and for the moment before niceSelect runs. */
.deal-pipe-bar select {
	flex: 0 0 240px;
	width: 240px;
	min-width: 0;
	height: 42px;
	padding: 8px 11px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	color: #101A2B;
}

/* 27.2 The bar as a member of the toolbar row rather than a row of its own. It keeps its
   standalone margins on m=deals&d=pipeline, where it is still the only thing on its line. */
.ct-toolbar > .deal-pipe-bar {
	flex: 0 0 auto;
	align-items: center;
	margin: 0;
}
.ct-toolbar > .deal-pipe-bar > label {
	margin: 0;
	font-size: var(--fs-sm);
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--text-muted);
	white-space: nowrap;
}

/* Every control in this row is 42px, so centre them. `.ct-toolbar` stays `flex-start` globally:
   on Contacts the row is a search field and a button and the top edge is the right anchor if the
   row ever wraps. */
body.deals .ct-toolbar { align-items: center; }

/* 27.3 The deal list's property filters are <select>s inside `.ct-search`, and they hit the same
   `width: 100%` as the picker did. Contacts renders no select in this row, so this is scoped
   rather than added to `.ct-search` itself. */
body.deals .ct-search .nice-select,
body.deals .ct-search select {
	flex: 0 0 180px;
	width: 180px;
	height: 42px;
	padding: 0 30px 0 12px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: var(--fs-md);
	font-weight: 400;
	color: #101A2B;
}

@media (max-width: 767px) {
	.ct-toolbar > .deal-pipe-bar { width: 100%; }
	.deal-pipe-bar .nice-select,
	.deal-pipe-bar select { flex: 1 1 auto; width: 100%; }
}

/* =========================================================================================
   28. THE DEAL FORM -- m=deals&d=add and d=edit

   28.1 IS THE BUG. The rest is layout.
   ========================================================================================= */

/* 28.1 A NESTED TABLE INSIDE A FORM WAS BEING UNBUILT.
   ------------------------------------------------------------------------------------------
   common_adminform.css:100-109 declares, in bare descendant form:

       .adminform_form tr              { display: flex; flex-direction: column; }
       .adminform_form tr td           { width: 100%; }
       .adminform_form tr td:first-child { margin-bottom: 10px; }

   Those were written for the LEGACY `<table class="adminform_table">` form, where stacking a
   row into label-over-field was the whole point. Forms render as `<div class="form-group">`
   now, so all three style nothing the form itself emits -- but they still reach every table
   NESTED inside a form, and the deal form nests one: the Line Items grid.

   Every `<tr>` became a vertical stack of full-width cells. That is the screenshot: PRODUCT,
   QTY, LOCATIONS, UNIT PRICE, FREQUENCY, LINE TOTAL and MRR each on a line of its own, headers
   drifting above controls they do not label, the whole grid unreadable and unusable.

   Put back per element, not per property. `display: table-row` is what makes a header line up
   over its own column again; nothing short of returning the elements to table layout does that.
   `th` is deliberately NOT given `width: auto` -- lineitems.css sizes the columns through
   `th.li-c-prod`, `th.li-c-n`, `th.li-c-freq`, `th.li-c-x`, and a blanket reset here would
   outrank all four and hand the table back to auto-layout. */
.adminform_form table:not(.adminform_table) tr {
	display: table-row;
	flex-direction: row;
}
.adminform_form table:not(.adminform_table) > thead { display: table-header-group; }
.adminform_form table:not(.adminform_table) > tbody { display: table-row-group; }
.adminform_form table:not(.adminform_table) td { width: auto; }
.adminform_form table:not(.adminform_table) td:first-child { margin-bottom: 0; }

/* 28.2 THE CARD USES THE PAGE.
   `max-width: 720px` (section 19) is right for a form that is only fields -- a 1200px text input
   is not a better text input. This form is not only fields: it carries a two-column record
   picker and a seven-column line-item grid, both of which were being folded into the ~430px
   field column of a 720px card while half the screen sat empty beside them. */
body.deals .adminform_form .adminform_table,
body.deals .adminform_form .adminform_savebutton {
	max-width: none;
}

/* Two fields per row, so the width buys something on the plain fields as well. The panels below
   opt back out to full width. */
body.deals .adminform_form .adminform_table > .form-group { grid-column: span 3; }
/* ...but not inside a pop-up: the Create Task modal (CR-19) opens on the deal page and was split into half-width
   columns by the rule above. Pop-up forms keep one field per row, as on every other page. */
body.deals #ai_modal .adminform_form .adminform_table > .form-group,
body.deals .modal .adminform_form .adminform_table > .form-group { grid-column: 1 / -1; }

/* 28.3 A PANEL IS NOT A FIELD.
   The picker, the pipeline note and the Line Items grid arrive as generated `buttons_*` rows, so
   each was handed an empty label cell and the 1fr remainder. Selected on what the row CONTAINS
   rather than on that generated id: the id is an implementation detail of the form builder and
   the content is the actual reason these rows are different. */
body.deals .adminform_form .adminform_table > .form-group:has(.deal-pick),
body.deals .adminform_form .adminform_table > .form-group:has(.li-lipanel),
body.deals .adminform_form .adminform_table > .form-group:has(.pr-panel),
body.deals .adminform_form .adminform_table > .form-group:has(.deal-form-note) {
	grid-column: span 6;
	grid-template-columns: minmax(0, 1fr);
}
body.deals .adminform_form .form-group:has(.deal-pick) > div:first-child,
body.deals .adminform_form .form-group:has(.li-lipanel) > div:first-child,
body.deals .adminform_form .form-group:has(.pr-panel) > div:first-child,
body.deals .adminform_form .form-group:has(.deal-form-note) > div:first-child {
	display: none;
}

/* The form builder emits a row per injected block, and one of them is injected empty -- it drew
   a hairline and 24px of padding between the picker and Line Items and meant nothing. */
body.deals .adminform_form .form-group:has(> div:last-child:empty) { display: none; }

/* 28.4 THE PICKER'S OWN NOTE WAS TAKING A COLUMN.
   `.deal-pick` is `grid-template-columns: 1fr 1fr` and the note is its first child, so the note
   took cell 1, Contacts took cell 2, and Companies wrapped to the next row -- which is why the
   two lists were stacked diagonally instead of sitting side by side. It is a caption for both
   columns, so it spans both. */
.deal-pick-note {
	grid-column: 1 / -1;
	margin: 0;
	font-size: var(--fs-md);
	color: #5A6A80;
}
.deal-pick {
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	margin: 2px 0 0;
}

/* 28.5 The Line Items panel is the last thing in the form; its own 16px bottom margin plus the
   row's padding was a band of nothing above Save. */
body.deals .adminform_form .li-lipanel { margin: 2px 0 0; }

@media (max-width: 1100px) {
	body.deals .adminform_form .adminform_table > .form-group { grid-column: span 6; }
}
@media (max-width: 767px) {
	.deal-pick { grid-template-columns: minmax(0, 1fr); }
}

/* =========================================================================================
   29. THE DEAL PIPELINE BOARD -- m=deals&d=pipeline

   The third deal surface, and the one left behind. Sections 26 and 27 gave the per-deal board
   and the deals list a shape; this page still had columns sitting straight on the page wash and
   a column header of its own design, so the three screens under one tab strip looked like three
   products.

   `.li-pipeline` is rendered from exactly one place (deals.php), so these rules cannot reach
   another screen -- but they are scoped to `body.deals` anyway, to match the rest of this file
   and because lineitems.css owns the base definitions and should stay readable on its own.

   THE SPACING ABOVE THE BUTTON is not fixed here. It was an `.additional-buttons-section`
   holding one button, which is the class section 8 hoists into the reserved 58px title band and
   the class section 26.1 tests for before releasing it. deals.php now emits `.ct-toolbar`
   instead, exactly as the list does, so the band is released and the gap matches by
   construction rather than by a margin chosen to look right.
   ========================================================================================= */

/* 29.1 The card holds the columns, and the head sits above them with a rule -- section 26.2
   already paints `.board-card` and `.board-head`, so this only tunes the head that carries a
   sub-line and no title of its own. */
body.deals .board-card > .board-head:first-child .board-sub { margin-top: 0; }
body.deals .board-card > .board-head:only-child { margin-bottom: 0; }

/* The mask on `.li-pipeline` (section 35.5) fades the right edge to say "more columns this
   way". Inside a card it has to fade to the CARD, and a mask fades to transparent, so the
   column strip is given the card's own inset and the fade lands on white. */
body.deals .board-card .li-pipeline {
	padding-bottom: 8px;
	gap: 12px;
}

/* 29.2 The column header, matched to section 26.4: a label row with a coloured spine, not a
   heading. Same reasoning about which stages get a colour of their own -- `sold` and `lost` are
   stage KEYS and a brand may define stages this file has never heard of, so everything else
   takes the neutral spine. */
body.deals .li-pipe-col {
	background: var(--surface);
	border: 1px solid var(--line);
	overflow: hidden;
}
body.deals .li-pipe-head {
	align-items: center;
	padding: 9px 12px;
	background: var(--surface-alt);
	border-bottom: 1px solid var(--line);
	border-left: 3px solid #C9D2DE;
	flex-wrap: nowrap;
}
body.deals .li-pipe-col.is-sold .li-pipe-head { border-left-color: #17803D; }
body.deals .li-pipe-col.is-lost .li-pipe-head { border-left-color: #B3261E; }

body.deals .li-pipe-name {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--ink);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
body.deals .li-pipe-count {
	flex: 0 0 auto;
	min-width: 22px;
	padding: 1px 7px;
	border-radius: 999px;
	background: var(--surface-mute);
	font-size: 11px;
	font-weight: 600;
	color: var(--text-muted);
	text-align: center;
}
/* Money is green on every other deal surface -- the card figure, the line-item totals, the
   per-deal board. It was indigo here and nowhere else. */
body.deals .li-pipe-mrr {
	flex: 0 0 auto;
	font-size: 11px;
	font-weight: 600;
	color: #17803D;
	font-variant-numeric: tabular-nums;
}

/* 29.3 The track, matched to section 26.5 -- an inset a card can be dropped into, legible when
   the stage is empty. */
body.deals .li-pipe-body {
	padding: 10px;
	gap: 10px;
	background: var(--surface-alt);
	min-height: 120px;
}
body.deals .li-pipe-empty {
	padding: 26px 0;
	color: #A8B3C2;
	font-size: var(--fs-sm);
}

/* 29.4 The card, matched to section 26.6 so a deal looks the same whichever board it is on. */
body.deals .li-pipe-card {
	padding: 11px 13px;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .05);
	transition: border-color .12s ease, box-shadow .12s ease;
}
body.deals .li-pipe-card:hover {
	border-color: #C9D2DE;
	box-shadow: var(--sh-2);
}
body.deals .li-pipe-card-name {
	font-size: 14px;
	font-weight: 600;
	line-height: 19px;
	color: var(--ink);
}
body.deals .li-pipe-card-sub {
	font-size: 12.5px;
	line-height: 17px;
	color: var(--text-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
body.deals .li-pipe-card-fig {
	margin-top: 8px;
	padding-top: 8px;
	border-top: 1px solid #EEF1F4;
	font-size: 12px;
	font-weight: 600;
	color: #17803D;
}
/* A deal with neither a value nor an MRR emits the figure row empty; a rule and 16px of space
   for nothing is worse than no row. */
body.deals .li-pipe-card-fig:empty { display: none; }

body.deals .li-pipe-foot {
	padding: 9px 12px;
	background: var(--surface);
	border-top: 1px solid var(--line);
	color: var(--text-muted);
	font-variant-numeric: tabular-nums;
}

/* 29.5 The grand total is the card's foot now, not a line floating under the page. */
body.deals .board-card > .li-pipe-grand {
	margin: 14px 0 0;
	padding-top: 12px;
	border-top: 1px solid var(--line);
	color: var(--ink);
	font-variant-numeric: tabular-nums;
}

/* =========================================================================================
   30. PIPELINES SETUP -- m=dealpipelines

   The third tab under Deals, and the one still on the old rhythm. Sections 27 and 29 moved the
   list and the board onto `.ct-toolbar`; this page kept `.additional-buttons-section`, so two
   of the three tabs released the reserved title band and one held it open.
   ========================================================================================= */

/* 30.1 A right-hand action group inside the shared toolbar.
   `.ct-add` is the single-button case (Contacts, Deals): `margin-left: auto` on the button
   itself. Two buttons need the auto-margin on a group, or the gap between them collapses to
   whatever the toolbar's own gap happens to be. */
.ct-toolbar > .ct-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-left: auto;
	flex: 0 0 auto;
}
.ct-toolbar > .ct-actions .ab-button { white-space: nowrap; }

/* A toolbar carrying nothing but its actions still owns the row. */
body.dealpipelines .ct-toolbar { align-items: center; }

/* 30.2 Column widths, so a number sits under the word that names it.
   Without them the table auto-sizes: `Pipeline` took the slack AND the number columns took a
   third of the page each, which is how `5` ended up ~190px right of `STAGES`. The name column
   is the only one left unsized, so it absorbs the remainder. */
body.dealpipelines .li-lists th.li-c-num { text-align: right; width: 120px; }
body.dealpipelines .li-lists th.li-c-status { width: 130px; }
body.dealpipelines .li-lists th.li-c-act { width: 270px; }

/* 30.3 On a settings table the row actions ARE the interface.
   Section 14 fades them to 0 and section 35.6 lifts that to .55, both reasoning about a long
   record list where six identical Edit/Delete pairs are noise. This table is a handful of rows
   whose whole purpose is Open / Rename / Make default / Archive, and there is no other route to
   three of those four. */
body.dealpipelines .li-lists td.row-actions { opacity: 1; }

/* 30.4 Page rhythm, matching the lists that already had it (identity.css section 5100). The
   band is released now, so the intro is the first thing under the title and sets the top. */
body.dealpipelines .li-intro { margin: 0 0 12px; }
body.dealpipelines .ct-list-wrap { margin-top: 0; }
body.dealpipelines .li-foot { margin-top: 12px; max-width: 900px; line-height: 1.5; }
body.dealpipelines .li-flash { margin-bottom: 12px; }

@media (max-width: 900px) {
	body.dealpipelines .li-lists th.li-c-num,
	body.dealpipelines .li-lists th.li-c-status,
	body.dealpipelines .li-lists th.li-c-act { width: auto; }
}

/* =========================================================================================
   31. PRODUCT LISTS -- m=lineitems

   The same three faults as section 30, on the screen section 30's table markup was copied
   from. Kept as its own section rather than merged into a shared selector list: the two pages
   have different columns, and a shared rule would have to be widened every time either one
   gains a column.
   ========================================================================================= */

/* 31.1 Column widths. The name column is the only one left unsized, so it takes the slack --
   which matters more here than on Pipelines, because `.li-desc` puts the list's description on
   a second line inside that cell and it needs the room. */
body.lineitems .li-lists th.li-c-num { text-align: right; width: 110px; }
body.lineitems .li-lists th.li-c-brand { width: 170px; }
body.lineitems .li-lists th.li-c-src { width: 120px; }
body.lineitems .li-lists th.li-c-status { width: 120px; }
body.lineitems .li-lists th.li-c-date { width: 130px; white-space: nowrap; }
body.lineitems .li-lists th.li-c-act { width: 150px; }

body.lineitems .li-products th.li-c-num { text-align: right; width: 130px; }
body.lineitems .li-products th.li-c-sku { width: 150px; }
body.lineitems .li-products th.li-c-freq { width: 130px; }
body.lineitems .li-products th.li-c-type { width: 110px; }
body.lineitems .li-products th.li-c-status { width: 120px; }
body.lineitems .li-products th.li-c-act { width: 150px; }

/* 31.2 Row actions, same reasoning as section 30.3: on a settings table Open / Edit / Archive
   are the interface, not decoration on a record the user came to read. */
body.lineitems .li-lists td.row-actions,
body.lineitems .li-products td.row-actions { opacity: 1; }

/* 31.3 The record header, now that the duplicate <h2> is gone (lineitems.php). The crumb is
   the top line of the block and no longer sits under a heading, so it carries the spacing. */
body.lineitems .li-listhead { margin-bottom: 14px; }
body.lineitems .li-crumb {
	margin-bottom: 8px;
	font-weight: 500;
}
body.lineitems .li-listdesc { margin-top: 0; }
body.lineitems .li-foot { margin-top: 12px; max-width: 900px; line-height: 1.5; }

/* The action row on a list can run to five buttons; wrapping is fine, drifting apart is not. */
body.lineitems .li-listhead-actions { align-items: center; gap: 8px; }

@media (max-width: 900px) {
	body.lineitems .li-lists th[class*="li-c-"],
	body.lineitems .li-products th[class*="li-c-"] { width: auto; }
}

/* =========================================================================================
   32. THE SIDEBAR MARK

   WHAT IS ACTUALLY ON DISK. `themes/vertical/images/logo.png` and `logo-toggle.png` are the
   same file, byte for byte -- a 32x32 mark. The comment above the collapsed-rail rules
   promises "the full lockup when open, a compact mark when collapsed"; there is no lockup,
   so the open rail renders the compact mark and 200px of empty navy beside it. That part is
   an ASSET gap, not a CSS one, and is left for a real lockup to fill: index.tpl already reads
   `$pb.s.current_logo`, so uploading one in Control Panel replaces this with no code change.

   WHAT WAS FIXABLE HERE is that the mark was in the wrong place twice over.

     1. `.navbar-brand { margin: auto }` (styles.css) centres it inside a 250px header, while
        every menu item below is left-aligned. One element on the whole rail was centred, which
        is what made a small icon read as a stray one rather than as a logo.
     2. `.navbar-brand > img { padding-top: 8px }` -- declared twice, stylesheets.css:788 and
        styles.css -- pushes it down inside a row that is already `align-items: center`, so it
        sat 8px below the middle of its own header.

   22px, not the 14px this row used: `.luna-nav.nav` has `padding: 8px 10px` and each item's
   anchor adds `8px 12px`, so every menu icon's left edge is at 22px. The mark now stands on
   that same line.
   ========================================================================================= */

.navigation .tog-button-left {
	justify-content: flex-start;
	padding: 10px 22px;
	min-height: 60px;
}

.navigation .navbar-brand {
	display: inline-flex;
	align-items: center;
	float: none;
	height: auto;
	margin: 0;
	padding: 0;
}

.navigation .navbar-brand > img {
	display: block;
	padding-top: 0;
}

/* The collapsed rail is 68px wide and has nothing to align to, so the mark is centred there --
   deliberately the opposite of the open rail, where there is a column to line up with. Matched
   to the open rail's height so the menu below starts at the same y in both states;
   styles.css pins `.navbar-mibile-view` to 63px, which is the only reason this restates it. */
body.nav-toggle .navigation .navbar-mibile-view {
	min-height: 60px;
	height: auto;
	padding: 10px 8px;
}

/* ONE BOX FOR ANY MARK, whatever the brand uploaded.
   `.navigation .navbar-mibile-view img` (identity.css:1021) constrains HEIGHT only --
   `max-height: 30px; width: auto`. That is fine for a tall narrow mark and wrong for a wide
   one: brand 17's is 70x37, so capping the height to 30 leaves it 57px WIDE, which overflows
   this container's 41px content box (57px rail minus 2x8px padding) and pushes it against
   both edges of a 68px rail.
   Since the file is operator-uploaded there is no safe assumption about its dimensions, so
   both axes are bounded and `object-fit: contain` does the letterboxing. A 200x13 wordmark,
   a 24x24 glyph and a 70x37 block all land inside the same 40x28 box, centred by the flex
   parent, without distortion. */
body.nav-toggle .navigation .navbar-mibile-view img {
	max-width: 40px;
	max-height: 28px;
	width: auto;
	height: auto;
	object-fit: contain;
}

/* =========================================================================================
   33. WORKSPACES AND BRANDS -- the two platform lists

   Same three faults as sections 30 and 31, on the two screens a SuperAdmin lands on first.

   Brands needs no rules here: it renders through `PB\UI\Grid`, whose `AddCol()` already takes
   a width, so its columns are sized at source (companiesmgmt.php). Adding a second, CSS-side
   opinion about the same table is how two sources of truth start disagreeing.
   ========================================================================================= */

/* 33.1 Column widths. `Brands` and `People` are `.num-cell`, so their headers right-align over
   the values -- `.deal-list th` is left-aligned and section 19's grid never made an exception
   for a numeric column. The name column stays unsized and takes the remainder. */
body.workspaces .deal-list th.ws-c-num { text-align: right; width: 110px; }
body.workspaces .deal-list th.ws-c-slug { width: 220px; }
body.workspaces .deal-list th.ws-c-status { width: 130px; }
body.workspaces .deal-list th.ws-c-act { width: 110px; }

/* 33.2 The slug is an identifier -- one line, monospaced digits, never wrapped. */
body.workspaces .deal-list td.ws-slug {
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	color: var(--text-muted);
}

/* 33.3 Row actions at full strength. Section 14 fades them to 0 and section 35.6 lifts that to
   .55, both reasoning about a long record list where the actions repeat down every row and the
   row itself is clickable. Neither holds here: this is a short platform list, the row is NOT
   clickable, and Edit is the only way in. */
body.workspaces .deal-list td.row-actions { opacity: 1; }

@media (max-width: 900px) {
	body.workspaces .deal-list th[class*="ws-c-"] { width: auto; }
}

/* =========================================================================================
   34. THE BRAND WIZARD -- m=companieswizard

   34.1 "SOMETHING CUTTING FROM THE TOP" IS MARGIN COLLAPSE, and the cause is a specificity
   fight this file started with itself.

   Section 26.1 releases the reserved 58px title band with

       .block > .body-wrapper > .block-content-outer:not(:has(> .additional-buttons-section))
         :not(:has(> .tablewrapper > .additional-buttons-section))
         :not(:has(> form > .additional-buttons-section)):not(:has(> .dash-nav-row))
         { padding-top: 0 }

   Three classes plus four `:not(:has(...))`, each contributing its argument's specificity, is
   (0,7,0). Section 33.1's `body.wizard_page .block > .body-wrapper > .block-content-outer
   { padding-top: 12px }` is (0,4,1) and loses, and wizardstyles.css's own `padding: 40px 20px
   10px` is (0,1,0) and loses by more. So this card computed to `padding-top: 0`.

   With no padding and no border at the top of the card, the <h2>'s Bootstrap `margin-top: 20px`
   collapses up through `.stepssection` (identity gives it `margin-top: 0`, which does not stop a
   collapse) and straight out of `.block-content-outer`. The 20px lands ABOVE the white card, so
   the card's top edge sits exactly on the heading's text box -- which is the heading looking
   sliced off.

   Fixed with PADDING on `.stepssection`, not with more margin and not by out-specifying section
   26.1. Padding cannot collapse, so this holds no matter which of the three rules above wins the
   padding-top argument later.
   ========================================================================================= */
/* `:not(.campaigns-chrome)` because the campaign wizard shares `body.wizard_page` and has no
   such bug: section 27c HIDES its <h2> outright, so its first visible child is the step bar,
   whose `margin: 0 0 12px` (section 33.1) has no top margin to collapse. Adding 24px there
   would move a page nobody reported. */
body.wizard_page:not(.campaigns-chrome) .block > .body-wrapper > .block-content-outer > .stepssection {
	margin-top: 0;
	padding: 24px 20px 0;
}

/* 34.2 The heading was centred while the step bar under it was left-aligned -- identity moved
   the bar to flex/left in section 33.1 and left `.stepssection h2 { text-align: center }`
   (stylesheets.css) where it was. Nothing else in this app centres a heading. Left, at the app's
   own scale, on the same 20px line as the bar and the fields below it. */
body.wizard_page:not(.campaigns-chrome) .stepssection > h2 {
	margin: 0 0 14px;
	text-align: left;
	font-size: 17px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink);
}

/* 34.3 A WIZARD IS A FORM, and a 1560px-wide "Brand Name" field is not one.
   `.wizard .addcustomer { max-width: 800px }` (stylesheets.css) was written for exactly this,
   but the markup carries no `.wizard` class, so the panel ran the full width of the page.

   Selected on the form the brand wizard actually emits rather than on `body.wizard_page`, which
   also covers the campaign sequence editor -- that one is already sized in section 33 and must
   not be narrowed again. */
body.wizard_page .block > .body-wrapper > .block-content-outer:has(form.company_wizard) {
	max-width: 880px;
}

/* The inner `.addcustomer` is a second white card inside the first -- same background, same
   radius, its own 20px. Invisible today because white on white, but it doubles the inset the
   fields sit at. One card. */
body.wizard_page .block-content-outer:has(form.company_wizard) > .addcustomer {
	background: transparent;
	box-shadow: none;
	padding: 0 20px 8px;
}

/* =========================================================================================
   35. THE USER FORM'S TWO BIG PANELS, IN TWO COLUMNS EACH

   The card keeps its width (section 21). What changes is the two blocks under the fields,
   which were tall stacks of full-width rows: Brand access ran ~420px and the permissions grid
   ~22 rows down the page, so the form was mostly scrolling.

   Both render from usersmgmt.php and nowhere else -- checked -- so `body.user_management_section`
   covers every instance and nothing outside it can be reached by these rules.
   ========================================================================================= */

/* 35.1 BRAND ACCESS: the three modes beside the brand list rather than above it.
   `.ba-brands` is DIMMED, not hidden, when the mode is `home` or `all_in_workspace`
   (section 12), so the right-hand column is never empty -- it is the same control, greyed. */
@media (min-width: 1100px) {
	body.user_management_section .brand-access {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		align-items: start;
	}
	body.user_management_section .brand-access > .perm-head { grid-column: 1 / -1; }

	body.user_management_section .ba-modes { padding-bottom: 14px; }

	/* Was a full-width block under the modes: `border-top` and a 10px lift. Beside them it
	   needs a vertical rule instead, and no lift. */
	body.user_management_section .ba-brands {
		border-top: 0;
		border-left: 1px solid #EEF1F4;
		margin-top: 0;
		max-height: 268px;
	}
}

/* 35.2 MODULE ACCESS: the six groups in two columns.
   Multi-column rather than a two-track grid, deliberately. The groups are uneven -- Work 3
   rows, Records 7, Growth 4, Service 2, Insight 1, Admin 5 -- and a grid pairs them by source
   order, so row one would be 3 against 7 and leave four rows of white under Work. Columns
   BALANCE, so the two sides come out close to the same height whatever the group sizes are,
   and `break-inside: avoid` is what keeps a group whole.

   `column-span: all` on the head keeps the title, the note and "Select everything I can grant"
   across the full width where they belong. */
@media (min-width: 1100px) {
	body.user_management_section .perm-grid {
		columns: 2;
		column-gap: 0;
		column-rule: 1px solid #EEF1F4;
	}
	body.user_management_section .perm-grid > .perm-head {
		column-span: all;
		margin-bottom: 4px;
	}
	body.user_management_section .perm-grid > .perm-group {
		break-inside: avoid;
		padding-bottom: 8px;
	}
	/* The rule between the columns already separates them; a border-top on the first group of
	   the SECOND column would be a line starting halfway down for no reason. */
	body.user_management_section .perm-grid > .perm-group + .perm-group { border-top: 0; }

	/* Half the width means the module name column has to give some back, or four action chips
	   wrap onto a second line on every row. 130px still fits "Companylinks". */
	body.user_management_section .perm-grid .perm-mod { flex: 0 0 130px; }
	body.user_management_section .perm-grid .perm-row { padding-left: 16px; padding-right: 16px; }
}

/* =========================================================================================
   36. THE SIDEBAR RAIL TOGGLE

   36.1 IT DISAPPEARED IN THE STATE YOU NEED IT MOST.
   styles.css declares `.nav-toggle .hide-toggle-side { display: none }`, and the toggle's own
   container carries BOTH classes -- so the moment the rail is collapsed the control vanishes,
   in the one state where the only thing left to do with it is expand again. style.css tries to
   keep the anchor alive with `.nav-toggle .toggle-sh { display: block !important }`, but an
   !important on a child cannot un-hide its parent, which is why that rule has never had any
   effect.

   36.2 AND IT WAS A WHITE DISC ON A WHITE PAGE.
   The circle is painted inside the SVG: `fill="white"` with a 1.5px `#E5E5E5` stroke. The
   button straddles the rail edge, so its left half sits on navy and reads fine, and its right
   half sits on the content wash -- white on white, outlined by a hairline two shades off the
   background. That is the half you look at, and it was effectively invisible.

   Fixed by making the BUTTON the circle -- real background, real border, real box-shadow, which
   is legitimate now that the element itself is round -- and hiding the SVG's own disc so the two
   outlines do not double up. The chevron is all that is left of the artwork.

   Scoped `.wrapper > .left-nav-toggle`: the same markup appears inside `#mobile-menu`, whose
   svg paths identity.css already fills separately, and which is not this control.
   ========================================================================================= */

body.nav-toggle .wrapper > .left-nav-toggle.hide-toggle-side { display: block; }

/* Above `.navigation`, which is z-index 2 normally and 999 while collapsed (stylesheets.css). */
.wrapper > .left-nav-toggle { z-index: 1050; }

.wrapper > .left-nav-toggle .toggle-sh {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: #FFFFFF;
	border: 1px solid #D3DBE5;
	box-shadow: 0 2px 8px rgba(16, 26, 43, .28);
	transition: box-shadow .12s ease, border-color .12s ease, background-color .12s ease;
}

.wrapper > .left-nav-toggle .toggle-sh:hover {
	border-color: #17803D;
	box-shadow: 0 3px 12px rgba(16, 26, 43, .34);
}

/* A round button gets a round focus ring; `outline` follows border-radius. */
.wrapper > .left-nav-toggle .toggle-sh:focus-visible {
	outline: 2px solid #17803D;
	outline-offset: 2px;
}

/* The disc the SVG draws for itself. Redundant now, and its stroke sat 1px inside the real
   border as a second, paler outline. */
.wrapper > .left-nav-toggle .toggle-sh svg > path:first-child { display: none; }

.wrapper > .left-nav-toggle .toggle-sh svg {
	width: 22px;
	height: 22px;
	display: block;
	transition: transform .16s ease;
}

.wrapper > .left-nav-toggle .toggle-sh:hover svg > path { stroke: #17803D; }

/* 36.3 THE ARROW FOLLOWS THE STATE -- and the SVG turns, not the container.
   style.css flips the whole `.left-nav-toggle` with `transform: rotate(180deg)`. That box is
   padding-asymmetric (25px left, 10px right), so rotating it also MOVES the button ~15px, which
   is why the collapsed position had to be guessed at separately. Rotating the mark alone leaves
   the geometry to `left`, where it can be reasoned about.

   THE POSITION, DERIVED RATHER THAN GUESSED. The container is `position: absolute` against the
   initial containing block (`.wrapper` sets no position), and its left padding is 25px, so the
   28px button's centre lands at `left + 25 + 14` = `left + 39`.

     expanded   rail 248px (section 886) . left 215 -> centre 254 -> 6px past the edge
     collapsed  rail  68px (section 1013) . centre must be 74 -> left = 74 - 39 = 35

   My previous 39px used 244 as the expanded rail width. The rail is 248, so the button ended up
   4px further out than the expanded state and read as detached from the rail rather than sitting
   on its edge. */
body.nav-toggle .wrapper > .left-nav-toggle {
	transform: none;
	left: 35px;
}
body.nav-toggle .wrapper > .left-nav-toggle .toggle-sh svg { transform: rotate(180deg); }

/* 36.4 THE OPEN RAIL'S LOCKUP.
   `themes/vertical/images/logo.png` and `logo-toggle.png` are the same 32x32 file, byte for
   byte, so the open rail and the collapsed rail were showing the same mark -- an icon alone
   beside 200px of navy. The theme does ship a 156x44 wordmark at
   `assets/images/required/logo-default.png`, but it reads "Cielos" and belongs to whatever this
   was white-labelled from; putting it in a dlivrd sidebar would be worse than the icon.

   So the lockup is the mark plus the `logo_text` setting as type -- the same string the <img>
   already uses for its alt, which is why setting it also fixes the unnamed link that section 32
   flagged. It is rendered ONLY when no lockup has been uploaded
   (`$pb.s.logo_is_theme_default`); a brand that uploads a real image gets that image alone.

   Nothing here invents a mark: a real lockup at `files/img/systemlogo<brandID>.jpg`, uploaded in
   Control Panel, supersedes all of it with no code change. */
.navigation .navbar-brand {
	gap: 10px;
	text-decoration: none;
}

.navigation .navbar-brand .nav-wordmark {
	font-size: 18px;
	font-weight: 600;
	letter-spacing: -.01em;
	line-height: 1;
	color: #FFFFFF;
	white-space: nowrap;
}

/* The collapsed rail is 68px. The mark alone fits; the word does not. */
body.nav-toggle .navigation .navbar-brand .nav-wordmark { display: none; }

/* 36.5 THE OPEN RAIL'S LOCKUP: CENTRED, LARGER, WITH ROOM BETWEEN ITS TWO HALVES.

   This reverses the alignment decision in section 32, on the owner's instruction. That section
   moved the mark to the 22px gutter so it stood on the same line as every menu icon; with a
   wordmark beside it the pair is a lockup rather than an icon, and a lockup centred in the rail
   is what was asked for. The 22px reasoning is left in section 32 as the record of why it was
   left-aligned before, not as a rule that still applies.

   The mark stays at its native 32px. `logo.png` IS 32x32, so any "enlarge" applied to the image
   is upscaling a line-art glyph and softens every stroke in it; the size comes from the type
   instead, which is vector and gains nothing but clarity. */
.navigation .tog-button-left {
	justify-content: center;
	padding: 14px 12px;
	min-height: 66px;
}

/* The space between the mark and the word is a MARGIN, not `gap`.
   `gap` only does anything while `.navbar-brand` computes to a flex box, which it does solely
   because section 32 sets `display: inline-flex` on it -- styles.css declares it as a plain
   anchor with `float: unset; padding: 8px 0`. A margin on the word survives whatever any sheet
   later decides that display should be, and this is one small rule that should not depend on
   another one two sections away still being in force. */
.navigation .navbar-brand {
	gap: 0;
}

/* `flex: 0 0 auto` so the mark cannot be squeezed by the text beside it -- a flex item's default
   `min-width: auto` protects text, not a replaced element, and the img was the one giving way. */
.navigation .navbar-brand img {
	flex: 0 0 auto;
	max-height: 32px;
}

.navigation .navbar-brand .nav-wordmark {
	margin-left: 10px;
	font-size: 22px;
	font-weight: 600;
	letter-spacing: -.015em;
	line-height: 1;
}

/* =========================================================================================
   37. REPORTS -- SAYING WHICH FIGURES THE PERIOD GOVERNS (m=platformstats)

   The page carries one period control and a line reading "Showing Last 30 days", and then two
   of its five blocks quietly ignore both it and the user filter: the contact-base counts with
   their ratio, and the campaign opens/clicks/unsubscribes. Fetching the page at today / 7 / 14 /
   30 returns the same numbers for those, which is how a reader ends up mistrusting the ones that
   ARE correct.

   Phase 1 does not change what is counted -- it makes each block state its own scope. The
   caption is driven from a flag set next to the queries (platformstats.php), so the two cannot
   drift apart later.
   ========================================================================================= */
.platformstats .stat-scope {
	margin: 2px 0 0;
	font-size: var(--fs-sm);
	font-weight: 400;
	line-height: 1.45;
	color: var(--text-muted);
}

/* Under a section headline it is a caption for the whole block, so it needs the headline's
   bottom margin rather than the tight one above. */
.platformstats .dashboard-section-headline + .stat-scope {
	margin: -6px 0 14px;
}

/* Inside a stat box the caption sits above the row of figures and must not be squeezed onto
   the same line as the first of them. */
.platformstats .stat-scope-block {
	display: block;
	width: 100%;
	margin: 0 0 10px;
	padding: 0 0 10px;
	border-bottom: 1px solid #EEF1F4;
}

/* The donut's caption sits under its title, above the dial. */
.platformstats .progressbar .title + .stat-scope {
	margin: 4px 0 12px;
	max-width: 280px;
}

.platformstats .panel-heading .stat-scope {
	margin-top: 4px;
	text-transform: none;
	letter-spacing: 0;
}

/* =========================================================================================
   38. REPORTS -- REVENUE AND THE STAGE FUNNEL (m=platformstats, phase 2)

   Its own classes rather than the page's existing `.statsbox` nesting. Those tiles are four
   levels of Bootstrap columns wrapped around a 24px SVG, inherited from the product this used
   to be; matching them would have meant inheriting dashboard.css's layout for a block that has
   different content and a different job. Everything below is self-contained and sits above the
   comms tiles, which is the point -- this tab used to open on Text Messages.
   ========================================================================================= */

.platformstats .rev { margin: 0 0 26px; }
.platformstats .rev-head { margin-bottom: 12px; }

.platformstats .rev-warn {
	margin: 0 0 12px;
	padding: 10px 14px;
	border: 1px solid #E8D3A8;
	border-radius: 8px;
	background: #FBF0DC;
	color: #96601A;
	font-size: var(--fs-sm);
	line-height: 1.5;
}

/* Six across on a wide screen, and it degrades by halving rather than by reflowing to an
   awkward 5+1. `auto-fit` with a 210px floor gives 6 / 3 / 2 / 1 at the widths that matter. */
.platformstats .rev-kpis {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
	gap: 12px;
	margin-bottom: 18px;
}

.platformstats .rev-kpi {
	display: block;
	padding: 14px 16px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 10px;
	border-left: 3px solid #C9D2DE;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	text-decoration: none;
	transition: border-color .12s ease, box-shadow .12s ease;
}
a.rev-kpi:hover {
	border-color: #C9D2DE;
	box-shadow: var(--sh-2);
}
/* Won and lost are the only two tiles that carry a judgement, so they are the only two that
   carry a colour. Everything else is neutral on purpose -- six coloured tiles is a rainbow, and
   a rainbow has no emphasis in it. */
.platformstats .rev-kpi.is-won  { border-left-color: #17803D; }
.platformstats .rev-kpi.is-lost { border-left-color: #B3261E; }

.platformstats .rev-k {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--text-muted);
}
.platformstats .rev-v {
	margin-top: 6px;
	font-size: 22px;
	font-weight: 700;
	line-height: 1.15;
	color: var(--ink);
	font-variant-numeric: tabular-nums;
}
.platformstats .rev-s {
	margin-top: 4px;
	font-size: var(--fs-sm);
	color: var(--text-muted);
	line-height: 1.4;
}

/* ---- the funnel ---------------------------------------------------------------------- */

.platformstats .rev-funnel {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 10px;
	padding: 16px 18px 8px;
}
.platformstats .rev-funnel-head { margin-bottom: 12px; }
.platformstats .rev-funnel-title {
	font-size: 15px;
	font-weight: 700;
	color: var(--ink);
}
.platformstats .rev-funnel-head .stat-scope a { color: #17803D; }

/* Name | bar | count | value. The bar is the only fluid track, so the numbers stay in a column
   the eye can run down instead of drifting with the longest stage name. */
.platformstats .rev-row {
	display: grid;
	grid-template-columns: minmax(120px, 190px) minmax(0, 1fr) 46px minmax(90px, 130px);
	align-items: center;
	gap: 14px;
	padding: 9px 0;
	border-bottom: 1px solid #F1F3F6;
}
.platformstats .rev-row:last-child { border-bottom: 0; }

.platformstats .rev-row-name {
	font-size: var(--fs-md);
	font-weight: 600;
	color: var(--ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.platformstats .rev-row-bar {
	height: 10px;
	border-radius: 999px;
	background: var(--surface-well);
	overflow: hidden;
}
.platformstats .rev-row-bar > span {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: #9FB3CC;
	/* A stage with nothing in it still renders its track, so the row keeps its height and the
	   funnel reads as a shape rather than as a list with holes. */
	min-width: 0;
}
.platformstats .rev-row.is-won  .rev-row-bar > span { background: #3FBF3C; }
.platformstats .rev-row.is-lost .rev-row-bar > span { background: #D8776A; }

.platformstats .rev-row-n,
.platformstats .rev-row-v {
	font-variant-numeric: tabular-nums;
	text-align: right;
	color: var(--ink);
}
.platformstats .rev-row-n { font-weight: 700; }
.platformstats .rev-row-v { font-size: var(--fs-sm); color: var(--text-muted); }

@media (max-width: 760px) {
	.platformstats .rev-row {
		grid-template-columns: minmax(0, 1fr) 40px;
		gap: 8px;
	}
	/* The bar and the money are the first things to go: on a phone the stage and its count are
	   the sentence, and the rest is detail. */
	.platformstats .rev-row-bar,
	.platformstats .rev-row-v { display: none; }
}

/* 38.1 The Revenue block sits on the page gutter like every other block on this route.
   `.rev` is not a `.row`, and dashboard.css gives `.platformstats .row` its 15px of horizontal
   padding -- so the KPI tiles started 15px left of the tiles beneath them. Same inset, taken
   from the same place, rather than a magic number. */
.platformstats .rev {
	padding-left: 15px;
	padding-right: 15px;
}

/* =========================================================================================
   39. REPORTS -- THE DEALS TREND (m=platformstats, phase 3)

   Hand-drawn SVG, no charting library. flot is loaded on this route but its crosshair and
   tooltip are separate plugins that are not, so a flot line chart would have needed a new
   dependency to get the hover layer a line chart is expected to have. Everything below is a
   `:hover` rule; there is no JavaScript.

   The palette (#2F6BA8 created / #1E8E5A won / #D97706 lost) was validated, not chosen. The
   obvious pick was this page's own green and red, which measure ΔE 4.0 under deuteranopia --
   won and lost, the two series a reader most needs to tell apart, would have been one colour
   to a colourblind reader. The trio that passes has a worst pair of 6.4, which is only legal
   WITH secondary encoding: that is what the legend, the direct end labels and the numbers
   table are for. Do not remove them to tidy the block up.
   ========================================================================================= */

.platformstats .rev-trend {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 10px;
	padding: 16px 18px;
	margin-bottom: 14px;
}

/* Identity comes from the swatch; the text stays in ink. */
.platformstats .tr-legend {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 18px;
	margin-bottom: 10px;
}
.platformstats .tr-key {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-size: var(--fs-sm);
	color: var(--text-muted);
}
.platformstats .tr-key i {
	width: 10px;
	height: 10px;
	border-radius: 3px;
	flex: 0 0 auto;
}
.platformstats .tr-key b { color: var(--ink); font-variant-numeric: tabular-nums; }

.platformstats .tr-wrap { width: 100%; }
.platformstats .tr-svg { width: 100%; height: 190px; display: block; overflow: visible; }

/* Hairline, solid, recessive -- never dashed. */
.platformstats .tr-grid { stroke: #EEF1F4; stroke-width: 1; }
.platformstats .tr-tick,
.platformstats .tr-x {
	fill: #8A97A8;
	font-size: 11px;
	font-family: inherit;
}
.platformstats .tr-end {
	font-size: 12px;
	font-weight: 600;
	font-family: inherit;
}

/* 2px, round join and cap. */
.platformstats .tr-line {
	fill: none;
	stroke-width: 2;
	stroke-linejoin: round;
	stroke-linecap: round;
}

/* r=4 is the 8px minimum; the 2px surface ring keeps a dot legible where two series cross. */
.platformstats .tr-dot {
	stroke: var(--surface);
	stroke-width: 2;
}

/* ---- the hover layer, in CSS ---------------------------------------------------------- */

.platformstats .tr-hit { cursor: crosshair; }
.platformstats .tr-cross {
	stroke: #C9D2DE;
	stroke-width: 1;
	opacity: 0;
}
.platformstats .tr-read {
	fill: var(--ink);
	font-size: 11.5px;
	font-family: inherit;
	opacity: 0;
	pointer-events: none;
}
.platformstats .tr-hit:hover .tr-cross,
.platformstats .tr-hit:focus .tr-cross { opacity: 1; }
.platformstats .tr-hit:hover .tr-read,
.platformstats .tr-hit:focus .tr-read { opacity: 1; }
/* Keyboard reaches the same readout the pointer does. */
.platformstats .tr-hit:focus { outline: none; }
.platformstats .tr-hit:focus-visible .tr-cross { stroke: #17803D; stroke-width: 2; }

/* ---- the table view ------------------------------------------------------------------- */

.platformstats .tr-table { margin-top: 12px; }
.platformstats .tr-table > summary {
	cursor: pointer;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: #17803D;
	list-style: none;
}
.platformstats .tr-table > summary::-webkit-details-marker { display: none; }
.platformstats .tr-table > summary::before { content: '▸ '; }
.platformstats .tr-table[open] > summary::before { content: '▾ '; }
.platformstats .tr-table table { margin-top: 10px; }
.platformstats .tr-table th.li-c-num { text-align: right; width: 110px; }

@media (max-width: 760px) {
	/* The end labels need 104px of gutter that a phone does not have; the legend already
	   names every series, and the table carries the values. */
	.platformstats .tr-svg { height: 150px; }
}

/* 39.1 Export sits on the section heading, not in a toolbar of its own -- it belongs to the
   Revenue block and to the window that block is showing. */
.platformstats .rev-head .dashboard-section-headline {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
}
.platformstats .rev-export {
	font-size: var(--fs-sm);
	font-weight: 600;
	color: #17803D;
	text-decoration: none;
	white-space: nowrap;
}
.platformstats .rev-export:hover { text-decoration: underline; }

/* =========================================================================================
   40. REPORTS -- THE LOWER HALF, ON THE SAME TILE AS THE UPPER (m=platformstats)

   Phase 1 renamed these two blocks; it did not restyle them, so "Contact base" and "Campaigns"
   were still the previous product's markup sitting under a Revenue row built this week. Two
   numbers adrift in a 340px-tall box, a donut, and three headings so large they wrapped.

   They now use `.rev-kpi` -- the same tile as the Revenue row. The `rev-` prefix is historical:
   it is the page's stat tile, shared by all three blocks, and section 38 defines it.

   THE DONUT IS GONE. `Appointment rate` is a single ratio against a limit, which the form
   reference calls a METER, not a pie of two slices; a 0% ring reads as a broken widget while a
   0% meter reads as an empty one. Dropping it also drops the last `.ldBar`, so loading-bar.js
   now has nothing to find on this route -- harmless, and the CSS/JS pair can be unlinked from
   the template whenever someone is confident no other block wants it.
   ========================================================================================= */

/* The rate tile carries a meter under its value, so it needs the room two plain numbers do not. */
.platformstats .rev-kpi.rep-wide {
	grid-column: span 2;
}

.platformstats .rep-meter {
	margin: 10px 0 2px;
	height: 8px;
	border-radius: 999px;
	background: var(--surface-well);
	overflow: hidden;
}

/* Same ramp as the track, a step darker -- the reference's rule for a meter, so state reads
   across the whole bar rather than from a colour change. */
.platformstats .rep-meter > span {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: #2F6BA8;
	transition: width .2s ease;
}

/* A section heading and its scope caption, with the air the old markup put inside the boxes. */
.platformstats .dashboard-section-headline {
	font-size: 15px;
	font-weight: 700;
	color: var(--ink);
	margin: 0 0 4px;
}
.platformstats .status-stats { margin: 0; }

@media (max-width: 760px) {
	.platformstats .rev-kpi.rep-wide { grid-column: span 1; }
}

/* =========================================================================================
   41. CAMPAIGNS LIST -- THE TOOLBAR OUT OF THE CARD, AND THE ROW THAT OVERFLOWED

   Section 27b fixed this page's vertical rhythm and deliberately stopped there. Two things it
   left are now visible: the toolbar is INSIDE the table's card, and the right-hand button falls
   off the screen.

   THE CARD IN A CARD. Section 19 gives `.tablewrapper` the card treatment -- white, rounded,
   shadowed -- and campaigns.php opens one around the toolbar, the filters AND the table, so the
   buttons render inside a white slab that no other list has. Section 20 already unpicked exactly
   this on m=contactlist; this is the same fix on the same cause: the outer wrapper becomes a
   plain block and the table keeps the card.

   THE OVERFLOW. `Broadcast` carries `action-buttons pull-right`, a float, inside that fixed-width
   card. A float cannot be measured by the row it sits in, so the row never grew to hold it and
   the button was clipped by the viewport. Flex with wrap replaces the float; nothing needs to
   guess a width.
   ========================================================================================= */

body.campaigns-list .block-content-outer > .tablewrapper {
	background: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	/* Dropping `overflow: hidden` here also removes the clipping hazard section 20 warned about:
	   a wrapper that clips its own children is a trap for the next negative margin. */
	overflow: visible;
	padding-left: 0;
	padding-right: 0;
}

/* The table keeps the card the wrapper just gave up. */
body.campaigns-list .campaignlist {
	background: var(--surface);
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	overflow-x: auto;
}

/* The button row: a flex that wraps, not three floats. */
body.campaigns-list .additional-buttons-section .adminbuttons {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}
body.campaigns-list .additional-buttons-section .adminbuttons .ab-button {
	float: none;
	margin-right: 0;
}

/* Counts read down a column, so they align on their right edge like every other numeric column
   in this theme -- and the header goes with them, or the number sits under nothing. */
body.campaigns-list .admintable th[data-id="contactsqty"],
body.campaigns-list .admintable th[data-id="openers"],
body.campaigns-list .admintable th[data-id="clickers"],
body.campaigns-list .admintable th[data-id="unsubscr"],
body.campaigns-list .admintable td.at-cell-contactsqty,
body.campaigns-list .admintable td.at-cell-openers,
body.campaigns-list .admintable td.at-cell-clickers,
body.campaigns-list .admintable td.at-cell-unsubscr {
	text-align: right;
	font-variant-numeric: tabular-nums;
}

/* The switch and the state pill are both controls-shaped; centre them in their own columns so
   the eye can tell the column apart from the counts either side. */
body.campaigns-list .admintable th[data-id="status"],
body.campaigns-list .admintable td.at-cell-status,
body.campaigns-list .admintable th[data-id="statuslab"],
body.campaigns-list .admintable td.at-cell-statuslab {
	text-align: center;
}
body.campaigns-list .admintable td.at-cell-statuslab .campaign-label { display: inline-block; }

/* =========================================================================================
   42. BRAND vCARD SETTINGS -- SECTIONS, AND A CARD YOU CAN SEE

   Sixteen fields arrived as one undifferentiated run: Company Name sat next to Instagram with
   nothing between them saying they belong to different things, and two of the sixteen (Zip and
   Instagram) had been given no row class at all, so they alone rendered full width with a
   left-hand label -- a layout the other fourteen did not use. The form now declares three
   sections (Identity / Address / Social Profiles) and gives every field a width, so section 22's
   six-column grid can do its job instead of being half-instructed.

   THE PANEL ON THE RIGHT IS THE POINT. This route is the only place a brand's outward contact
   details are set, and until now nothing on it showed what those details produce. The preview
   is filled from the inputs by vcardpreview.js -- never from PHP -- so it is a view of the form
   rather than a second rendering of the same mapping that could drift from it.

   THE CARD IN A CARD, AGAIN. `.embed_grid .socialsharewrap` (styles.css:1394) draws a bordered
   25px-padded box, and `.adminform_form` (common_adminform.css:110) draws another one inside it.
   Same cause and same fix as section 41: the outer wrapper goes flat and the pieces inside keep
   the card.
   ========================================================================================= */

body.vcard-settings-page .embed_grid .socialsharewrap.vcard-settings {
	background: transparent;
	border: 0;
	border-radius: 0;
	padding: 0;
}

/* 42.1 The page: form and preview side by side, the preview following you down a long form.
   `300px` rather than a fraction -- the panel holds a contact card, whose width is set by its
   content and not by how much room the form leaves over.

   The breakpoint is 1400px, not the 1180px this started at, because section 43 now spends 254px
   of the row on the settings rail. Under it the preview drops beneath the form and takes the
   full width, which keeps two fields per row in the form rather than squeezing three columns
   onto a laptop. */
body.vcard-settings-page .vcard-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 300px;
	gap: 20px;
	align-items: start;
}
@media (max-width: 1400px) {
	body.vcard-settings-page .vcard-layout { grid-template-columns: minmax(0, 1fr); }
	body.vcard-settings-page .vcard-preview { max-width: 420px; }
}

body.vcard-settings-page .vcard-formcol { min-width: 0; }

/* 42.1a ONE CARD, NOT THREE.
   Three nested white boxes were stacked here: `.socialsharewrap` (styles.css:1394, flattened
   above), then `<form class="adminform_form">` -- which common_adminform.css:110 gives
   `background: var(--surface)` and its own padding -- and then `.adminform_table`, which
   section 19 gives a border, a radius and 22px/24px of its own. Two of those three drew a
   rounded white panel a few pixels apart, and their padding compounded to 44px before the
   first label. The form element goes flat and `.adminform_table` is the card.

   Flattening the form also puts the Save row outside the card, which is where the Brand
   editor keeps it. `padding: 0` on that row because common_adminform.css:65 insets it 14px,
   which would leave the button not quite aligned with the card's left edge. */
body.vcard-settings-page .adminform_form.vcard-form {
	/* Both, deliberately: common_adminform.css:110 sets the LONGHAND `background-color`, and a
	   reader checking only the shorthand here cannot tell whether it wins. It does -- the
	   shorthand resets the longhand and this rule is later and more specific -- but stating it
	   costs one line and settles the question. */
	background: transparent;
	background-color: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	padding: 0;
}
body.vcard-settings-page .adminform_form.vcard-form .adminform_table {
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	padding: 18px 22px 22px;
}
body.vcard-settings-page .adminform_form.vcard-form .adminform_savebutton {
	padding: 0;
	text-align: left;
}

/* 42.2 SECTION HEADS.
   A separator renders as a row whose first cell holds the caption and whose second cell is
   empty (common_adminform.tpl:21-23). Section 22 already spans it across all six tracks and
   stops it reserving label height; what it needs here is to read as a heading rather than as a
   field with no input -- small, spaced, with a rule under it.

   `:first-child` is the Identity head, which opens the form and so takes no top margin. Written
   as a margin override rather than a different class because the PHP emits one kind of
   separator and the position is the only thing that differs. */
body.vcard-settings-page .vcard-form .form-group.adminform-separator {
	/* `.form-group` is `display: table` (common_adminform.css:16), which would wrap the caption
	   in an anonymous cell and make the rule under it a table edge rather than a heading edge. */
	display: block;
	margin: 22px 0 4px;
	padding-bottom: 8px;
	border-bottom: 1px solid #EEF1F4;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #6B7A90;
}
body.vcard-settings-page .vcard-form .form-group.adminform-separator:first-child { margin-top: 6px; }
body.vcard-settings-page .vcard-form .form-group.adminform-separator > div:last-child { display: none; }

/* 42.3 THE FIELD HINTS.
   `SetFieldBottomText` puts a `.adminform-filed-btm-txt` span under the input, which the theme
   renders italic at --fs-xs. Italic on a line that says which value the card falls back to
   reads as an aside; this is the field's own rule, so it gets the same weight as any other
   secondary line in this stylesheet. */
body.vcard-settings-page .vcard-form .adminform-filed-btm-txt {
	display: block;
	margin-top: 5px;
	font-style: normal;
	font-size: 12px;
	line-height: 1.4;
	color: #8B98AB;
}

/* 42.4 THE REGION LIST FOLLOWS THE COUNTRY.
   State and Province occupy the same slot; whichever the country does not name is removed from
   the flow entirely, so the field after it closes the gap rather than leaving a hole where a
   control used to be. A class, not jQuery's .show()/.hide(), which would write `display: block`
   inline over the grid item -- see the note in businesssettings.php. */
body.vcard-settings-page .vcard-form .form-group.vcard-region.is-region-off { display: none; }

/* 42.5 THE PREVIEW PANEL. */
body.vcard-settings-page .vcard-preview { position: sticky; top: 14px; }
@media (max-width: 1400px) {
	body.vcard-settings-page .vcard-preview { position: static; }
}
body.vcard-settings-page .vcard-preview[hidden] { display: none; }

.vcp-head { margin-bottom: 10px; }
.vcp-eyebrow {
	display: block;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: #6B7A90;
}
.vcp-note {
	margin: 4px 0 0;
	font-size: 12px;
	line-height: 1.45;
	color: #8B98AB;
}

.vcp-card {
	background: #FFFFFF;
	border: 1px solid #EEF1F4;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	padding: 18px;
}

.vcp-id {
	display: flex;
	align-items: center;
	gap: 12px;
	padding-bottom: 14px;
	border-bottom: 1px solid #EEF1F4;
}
.vcp-avatar {
	flex: 0 0 auto;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: #EEF3F8;
	color: #2F6BA8;
	font-size: 17px;
	font-weight: 600;
	line-height: 40px;
	text-align: center;
}
.vcp-name {
	min-width: 0;
	font-size: 15px;
	font-weight: 600;
	color: #101A2B;
	overflow-wrap: anywhere;
}

/* A value the card will carry because a field was left blank is shown in the muted ink every
   other placeholder-grade value in this theme uses. Same on the name, where a fallback is the
   likeliest case of all -- the brand's own name is what an untouched form produces. */
.vcp-name.is-fallback { color: #8B98AB; font-weight: 500; }
.vcp-row.is-fallback dd { color: #8B98AB; }

.vcp-rows { margin: 0; }
.vcp-row {
	display: grid;
	grid-template-columns: 68px minmax(0, 1fr);
	gap: 10px;
	padding: 9px 0;
	border-bottom: 1px solid #F3F6F9;
}
.vcp-row[hidden] { display: none; }
.vcp-row:last-child { border-bottom: 0; }
.vcp-row dt {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #8B98AB;
	padding-top: 2px;
}
.vcp-row dd {
	margin: 0;
	font-size: 13px;
	line-height: 1.45;
	color: #101A2B;
	overflow-wrap: anywhere;
}
/* The address arrives as one span per line rather than as markup, so it stacks here. */
.vcp-line { display: block; }

.vcp-social {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px solid #EEF1F4;
}
.vcp-social[hidden] { display: none; }
.vcp-chip {
	background: #F4F7FA;
	border-radius: 999px;
	padding: 3px 10px;
	font-size: 11px;
	font-weight: 500;
	color: #5A6A80;
}

/* =========================================================================================
   43. THE SETTINGS TABS AS A LEFT RAIL

   Eleven tabs never fitted a horizontal strip. Worse than the wrapping: section 12 reserves a
   58px band at the top of `.block-content-outer` and hoists the FIRST toolbar into it with
   `margin-top: -58px`, so the strip was pulled up on top of `<h2 id="block0title">` -- which on
   this route reads "vCard", directly underneath a tab that also reads "vCard". The half-hidden
   word at the top-left of the settings pages was the page title with a tab sitting on it.

   The rail is the pattern the Brand editor and Global settings already use
   (themes/default/companiesmgmt_tabs.tpl + globalsettings.css `.global-settings-sidebar`). It is
   restated here rather than reused by loading globalsettings.css, because that stylesheet also
   carries `.global-settings-body input { max-width: 500px }` and a set of `display: table` form
   rules that would fight section 22's grid. Same look, none of the freight.

   HOW THE TWO COLUMNS HAPPEN WITHOUT TOUCHING THIRTY CALL SITES. The strip and the page content
   are SIBLINGS inside `.block-content-outer` -- nine modules emit them that way, 30 times. Rather
   than restructure all thirty into a wrapper, the shared parent becomes the grid and the strip is
   assigned column 1. `body.settings-tabs-rail` is declared next to each strip render, so an action
   that draws no strip keeps the ordinary single-column body; every settings page was checked to
   hold exactly one `.block-content-outer`, which is what makes the parent safe to claim.
   ========================================================================================= */

/* 43.1 No hoist. A 500px rail pulled up 58px lands on the page title; the band exists for a
   58px-high toolbar and there no longer is one. Both halves of section 12's mechanism have to
   go together -- the reservation and the pull -- or the page keeps 58px of dead space. */
body.settings-tabs-rail .block > .body-wrapper > .block-content-outer { padding-top: 14px; }
body.settings-tabs-rail .block > .body-wrapper > .block-content-outer > .additional-buttons-section {
	margin-top: 0;
	min-height: 0;
}

/* 43.2 The shell. */
body.settings-tabs-rail .block > .body-wrapper > .block-content-outer {
	display: grid;
	grid-template-columns: 236px minmax(0, 1fr);
	column-gap: 18px;
	align-items: start;
}
body.settings-tabs-rail .block-content-outer > .additional-buttons-section { grid-column: 1; }
body.settings-tabs-rail .block-content-outer > *:not(.additional-buttons-section) { grid-column: 2; }

/* 43.3 The strip container becomes the rail's card. `.extended-buttons` is a wrapping flex row
   and `.buttons.flex` another flex; both have to stand down before a list can stack inside them. */
body.settings-tabs-rail .block-content-outer > .additional-buttons-section.extended-buttons {
	display: block;
	position: sticky;
	top: 14px;
	width: auto;
	padding: 10px;
	background: #FFFFFF;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
}
body.settings-tabs-rail .block-content-outer > .additional-buttons-section > .buttons.flex { display: block; }
/* An empty div the modules emit for a control this page does not have. As a flex child it was
   invisible; as a block it would be a 0-height gap at the top of the card. */
body.settings-tabs-rail .block-content-outer > .additional-buttons-section > .pipeline-dropdown { display: none; }

/* 43.4 The list, matched to `.global-settings-sidebar` so the two settings surfaces read as one
   product. Tighter row spacing than that rail's 10px: it carries six items and this one eleven. */
.settings-rail ul { list-style: none; margin: 0; padding: 0; }
.settings-rail li + li { margin-top: 2px; }
.settings-rail a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 9px 12px;
	border-radius: 8px;
	font-size: 14px;
	font-weight: 400;
	line-height: 1.25;
	color: #475569;
	text-decoration: none;
}
.settings-rail a:hover { background: #F6F8FA; color: #101A2B; }
.settings-rail li.active a { background: #F1F5F9; color: #0F172A; font-weight: 600; }

/* The icons are inline SVG of assorted viewBoxes, sized by their own width/height attributes.
   A fixed 18px box stops a 20px one from shifting its label out of line with the other ten. */
.settings-rail .icon {
	flex: 0 0 18px;
	display: flex;
	align-items: center;
	justify-content: center;
	color: currentColor;
}
.settings-rail .icon svg { display: block; width: 18px; height: 18px; }
.settings-rail .title { min-width: 0; }

/* 43.5 The content column takes the width the rail left it.
   Section 19 caps every form card in the app at 720px -- right for a form standing alone on a
   page, wrong inside a column that has already given 254px away. Same override the user form
   needed at section 21, and the save row goes with it or the button stops short of the card. */
body.settings-tabs-rail .adminform_form .adminform_table { max-width: none; }
body.settings-tabs-rail .adminform_form .adminform_savebutton { max-width: none; }

/* 43.6 Below the rail's own breakpoint the two columns stack, and the rail stops sticking --
   a sticky element as tall as the viewport pins the page. */
@media (max-width: 1000px) {
	body.settings-tabs-rail .block > .body-wrapper > .block-content-outer {
		display: block;
	}
	body.settings-tabs-rail .block-content-outer > .additional-buttons-section.extended-buttons {
		position: static;
		margin-bottom: 14px;
	}
	.settings-rail ul { display: flex; flex-wrap: wrap; gap: 4px; }
	.settings-rail li + li { margin-top: 0; }
}

/* =========================================================================================
   44. THE LIST FILTERS -- STYLING THE CONTROL THAT IS ACTUALLY ON SCREEN

   The filter dropdown on m=contacts sat on a line of its own, full width, with Search and Clear
   pushed onto a third line under a search box capped at 380px. Three rows of controls where the
   markup describes one.

   THE RULE THAT WAS MEANT TO SIZE IT STYLES A HIDDEN ELEMENT. `.ct-search select` (section 15)
   sets `max-width: 220px` -- but luna.js:30 runs `$('select').niceSelect()` over the whole page,
   which sets the real <select> to `display: none` and inserts a `div.nice-select` beside it. That
   div is what the user sees, and nothing scoped to `.ct-search` had ever named it, so it fell
   through to `stylesheets.css:1711`: `.nice-select { width: 100%; height: 45px }`. A 100%-wide
   flex item takes the whole line, and everything after it wraps.

   So the fix is not a width tweak: it is styling the visible control at all. Both the wrapper and
   the <select> underneath are sized here, the same pairing section 27.1 uses for the pipeline
   picker -- the <select> is what renders in the moment before niceSelect runs, and forever if
   scripting is off, and a control that changes size on load is its own bug.

   `.nice-select .list` is `position: absolute; width: 100%` against the wrapper
   (nice-select.css:89), so the open menu follows these widths without a rule of its own.

   THE SAME DEFECT ON THE CONTACT RECORD. `.ct-addform` -- the "add a company" row on
   m=customerdetails -- is a flex row of picker + role + Primary + Add, with its <select> sized to
   `min-width: 180px`. Same hidden element, same 100%-wide replacement, same broken row. Fixed
   here rather than filed, because it is one defect with one cause.
   ========================================================================================= */

/* 44.1 The search toolbar's filter. 220px mirrors the `max-width` the <select> rule already
   chose; 42px is the height of `.ct-search input[type="search"]` and of `.ct-add`, so the row
   lines up on one baseline. `flex: 0 0` -- a filter is a fixed-width control, and letting it
   grow would take the space the search box should have. */
.ct-search .nice-select {
	flex: 0 0 220px;
	width: 220px;
	height: 42px;
	min-height: 42px;
	/* 32px on the right clears the caret nice-select.css absolutely positions at `right: 12px`. */
	padding: 0 32px 0 13px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	font-size: 13px;
	font-weight: 400;
	line-height: 1.2;
	color: #101A2B;
}
.ct-search .nice-select:hover { border-color: #C7D0DA; }
.ct-search .nice-select.open,
.ct-search .nice-select:focus {
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}

/* The real control underneath, so the row does not resize when niceSelect runs. */
.ct-search select {
	flex: 0 0 220px;
	width: 220px;
}

/* 44.2 AN ACTIVE FILTER LOOKS ACTIVE.
   With the row on one line the filters sit beside each other, and "Referral" on its own does not
   say which property it filters -- m=companies renders two of these side by side. The modules add
   `is-on` to a select that is holding a value, and niceSelect copies the <select>'s class list
   onto its own div (jquery.nice-select.js:60), so one class covers both controls.

   Green because that is what every other "this control is engaged" state in this stylesheet uses
   (focus rings, `.icon-button:hover`); the border alone would read as focus. `Clear` beside them
   is still the way out -- this only makes it visible that there is something to clear.

   `.deal-toolbar-form` is in this list but NOT in the sizing rules above. The deal board's own
   toolbar (section 26) had already been given a sized `.nice-select`, so it never showed the
   defect this section exists for -- but its stage filter answers the same question, so it gets
   the same engaged state. Its `.deal-pipe-bar` sibling deliberately does not: a pipeline picker
   always holds a value, and a control that is permanently "on" is telling you nothing. */
.ct-search .nice-select.is-on,
.ct-search select.is-on,
.deal-toolbar-form .nice-select.is-on,
.deal-toolbar-form select.is-on {
	border-color: #17803D;
	background: #F3FAF5;
	color: #17803D;
	font-weight: 500;
}

/* 44.3 The add-company row on the contact record. 38px here, not 42px: that row's own inputs
   and buttons were built at 38px (section 15), and the picker has to match its neighbours rather
   than the toolbar on another page. */
.ct-addform .nice-select {
	flex: 0 1 220px;
	width: 220px;
	height: 38px;
	min-height: 38px;
	padding: 0 30px 0 11px;
	border: 1px solid #DDE2E9;
	border-radius: 7px;
	background: #FFFFFF;
	font-size: 13px;
	font-weight: 400;
	line-height: 1.2;
	color: #101A2B;
}
.ct-addform .nice-select:hover { border-color: #C7D0DA; }
.ct-addform .nice-select.open,
.ct-addform .nice-select:focus {
	border-color: #17803D;
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.ct-addform select { flex: 0 1 220px; width: 220px; }

/* 44.4 Narrow screens: the filters give up their fixed width and stack, which is what the
   <select> rule at section 15 already did and what the wrapper never learned to do. */
@media (max-width: 767px) {
	.ct-search .nice-select,
	.ct-search select {
		flex: 1 1 100%;
		width: 100%;
	}
	.ct-addform .nice-select,
	.ct-addform select {
		flex: 1 1 100%;
		width: 100%;
	}
}

/* 44.5 ONE HEIGHT ACROSS THE ROW.
   The search input, the filter and `+ Add Contact` are all 42px; the Search button kept
   `.ab-button`'s default 36px, so it sat 6px short in the middle of them. Scoped to the search
   form -- `.ab-button` is the app's button and 36px is right everywhere it is not standing in a
   row of 42px controls. */
.ct-search .ab-button { min-height: 42px; }


/* ==========================================================================================
   45. THE USER PROFILE PAGE
   ------------------------------------------------------------------------------------------
   `index.php?m=employeedetails&id=N` -- the same screen whether you open your own profile or
   another user's from User Management, so it only has to be right once.

   EVERYTHING HERE IS SCOPED TO `body.employee_details`. The markup it targets is shared:
   `.profilesidebar` appears in 15 templates, `.profile-btn-follow` in 7, `.customerimg` in 4
   (contact, company and referral detail pages among them). Styling those bare would have
   restyled half the product from one page's redesign.
   ========================================================================================== */

/* 45.1 THE AVATAR WAS AN OVAL.
   `.customerimg` is 80x80 in stylesheets.css:497, but it sits in a `display:flex` row with no
   `flex: none`, so it shrinks under the name and email beside it -- measured 35 wide by 80 tall
   at a 1440 viewport, with `border-radius: 100px` making it a pill. It only looks round on a
   very wide monitor, which is why it survived review. */
body.employee_details .customerimg {
	flex: 0 0 80px;
	justify-content: center;
	border: 0;
	background: #1A4159;
	color: #FFFFFF;
	font-size: 24px;
	font-weight: 600;
	text-transform: uppercase;
	margin-bottom: 0;
}
body.employee_details .customerimg img { width: 100%; height: 100%; object-fit: cover; }

/* 45.2 The sidebar becomes a card, matching the surface used on every other detail screen
   (`.ct-panel`, `.op`, `.assoc-strip`): white, 1px #E4E7EC, 10px radius. */
body.employee_details .profilesidebar {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 20px 18px;
}
/* The header stacks rather than sitting side by side. Beside an 80px avatar the text block got
   ~138px of a 268px column, which broke `qa.superadmin@example.com` mid-word into
   "qa.superadmin@exa / mple.com". Full width it fits on one line, and a centred identity is the
   shape a profile card wants anyway. */
body.employee_details .employee-details-wrapper > .flex {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 10px;
	padding-bottom: 16px;
	margin-bottom: 4px;
	border-bottom: 1px solid #EDF0F4;
}
body.employee_details .employee-details-wrapper > .flex > div:last-child { width: 100%; min-width: 0; }
body.employee_details .referral-side-info-email,
body.employee_details .referral-side-info-phone { font-size: 12px; overflow-wrap: break-word; }
body.employee_details .customerimg + div { min-width: 0; }
body.employee_details .referral-side-info-title {
	margin: 0 0 4px;
	font-size: 18px;
	font-weight: 600;
	color: #101A2B;
	overflow-wrap: anywhere;
}
body.employee_details .referral-side-info {
	font-size: 12.5px;
	color: #6B7A90;
	overflow-wrap: anywhere;
}
body.employee_details .referral-side-info a { color: #C9421F; text-decoration: none; }
body.employee_details .referral-side-info a:hover { text-decoration: underline; }
body.employee_details .referral-side-info i { color: #A8B4C4; margin-right: 5px; }

/* 45.3 Label / value rows. They were underlined full-width rows with the value floated right,
   which reads as a form, not a record. Same two-column shape as the company quick-look panel. */
body.employee_details .customer-info-additional .list-group-item,
body.employee_details .referral-customer-url-side-info {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 8px 0;
	border: 0;
	border-bottom: 1px solid #F1F3F6;
	background: transparent;
	font-size: 12.5px;
	color: #6B7A90;
	text-transform: none;
	letter-spacing: 0;
}
body.employee_details .referral-customer-url-side-info span,
body.employee_details .referral-customer-url-side-info b {
	font-size: 13px;
	font-weight: 600;
	color: #101A2B;
	text-align: right;
}

/* The role / notification rows are a plain Bootstrap `.list-group`, not the container styled
   above -- label and value in one text node with a heavy full-width rule under each. Read as a
   form; should read as a record. */
body.employee_details .profilesidebar .list-group { margin: 8px 0 16px; padding: 0; border: 0; }
body.employee_details .profilesidebar .list-group > .list-group-item {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 9px 0;
	border: 0;
	border-bottom: 1px solid #F1F3F6;
	border-radius: 0;
	background: transparent;
	font-size: 12.5px;
	font-weight: 500;
	color: #6B7A90;
	text-transform: none;
	letter-spacing: 0;
}
body.employee_details .profilesidebar .list-group > .list-group-item:last-child { border-bottom: 0; }
body.employee_details .profilesidebar .list-group > .list-group-item > span {
	font-size: 13px;
	font-weight: 600;
	color: #101A2B;
	text-align: right;
}
body.employee_details .profilesidebar .list-group > .list-group-item a { color: #101A2B; text-decoration: none; }
body.employee_details .profilesidebar .list-group > .list-group-item a:hover { color: #C9421F; }

/* 45.4 ONE BUTTON SYSTEM.
   Measured before: two appearances and two different corner radii -- the connect buttons at 7px
   with grey text, the account actions at 8px in red. Red is the product's destructive colour
   (`.ab-button.danger`), and none of Edit / Reset Password / Update User Role destroys anything,
   so red was signalling danger where there is none. All of them now use the app's standard
   control: 36px tall, 13px, 7px radius. */
body.employee_details .profile-btn-follow {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	width: 100%;
	min-height: 36px;
	margin: 0 0 8px;
	padding: 7px 14px;
	border: 1px solid #DDE3EB;
	border-radius: 7px;
	background: #FFFFFF;
	color: #35435A;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.35;
	text-align: center;
	white-space: normal;
	box-shadow: none;
	transition: border-color .15s ease, color .15s ease, background .15s ease;
}
body.employee_details .profile-btn-follow:hover,
body.employee_details .profile-btn-follow:focus {
	border-color: #F05B3A;
	color: #C9421F;
	background: #FEF3EF;
}
body.employee_details .profile-btn-follow i { font-size: 14px; }

/* The one primary action on the screen. Rule 9.2: solid orange means exactly that. */
body.employee_details .profile-btn-follow.btn-primary,
body.employee_details .profile-btn-follow.profile-edit-btn {
	background: #F05B3A;
	border-color: #F05B3A;
	color: #FFFFFF !important;
}
body.employee_details .profile-btn-follow.btn-primary:hover,
body.employee_details .profile-btn-follow.profile-edit-btn:hover {
	background: #D9451F;
	border-color: #D9451F;
	color: #FFFFFF;
}
/* `stylesheets.css:454` paints every `.profilesidebar .btn-danger` #DB524B with `!important`,
   which is why Update User Role, Reset Password and Edit all arrived red. None of the three
   destroys anything. `!important` is the only thing that outranks an `!important`, and this is
   scoped to one page rather than lifted from the shared sheet, which 14 other screens use. */
body.employee_details .profile-btn-follow.btn-danger {
	border-color: #DDE3EB;
	color: #35435A !important;
	background: #FFFFFF;
}
body.employee_details .profile-btn-follow.btn-danger:hover {
	border-color: #F05B3A;
	color: #C9421F !important;
	background: #FEF3EF;
}
/* Reserved for an action that really does destroy something. Nothing on this page carries it
   today; it exists so the colour keeps its meaning when something eventually does. */
body.employee_details .profile-btn-follow.is-destructive {
	border-color: #C0301C;
	color: #C0301C !important;
	background: #FFFFFF;
}
body.employee_details .profile-btn-follow.is-destructive:hover {
	background: #C0301C;
	border-color: #C0301C;
	color: #FFFFFF !important;
}
/* The connect buttons keep their brand colour on hover only, so six of them in a column do not
   compete with the page's own accent. */
body.employee_details .profile-btn-follow.facebook:hover { border-color: #1877F2; color: #1877F2; background: #F0F5FE; }
body.employee_details .profile-btn-follow.twitter:hover  { border-color: #1D9BF0; color: #1D9BF0; background: #EFF8FE; }
body.employee_details .profile-btn-follow.linkedin:hover { border-color: #0A66C2; color: #0A66C2; background: #EFF5FC; }

/* 45.5 The two columns were 10px apart, against the 20-24px this product uses everywhere else. */
body.employee_details .customer-details-wrapper { display: flex; align-items: flex-start; gap: 22px; }
body.employee_details .customer-details-wrapper > .col-md-3 { flex: 0 0 268px; max-width: 268px; padding: 0; }
body.employee_details .customer-details-wrapper > .col-md-9 { flex: 1 1 auto; min-width: 0; padding: 0; }

/* 45.6 Tabs, matching the company detail screen's strip.
   The strip is `.nav-tabs` directly inside `.profilesidebarright` -- NOT inside `.tabssection`,
   which is a different block further down this same template. Eight tabs also wrapped, orphaning
   "Video Calls" onto its own row; they scroll sideways instead, so the row stays one line. */
body.employee_details .profilesidebarright > .nav-tabs {
	display: flex;
	flex-wrap: nowrap;
	overflow-x: auto;
	border-bottom: 1px solid #E4E7EC;
	margin-bottom: 14px;
	padding-bottom: 0;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
}
body.employee_details .profilesidebarright > .nav-tabs > li { float: none; flex: 0 0 auto; margin: 0; }
body.employee_details .profilesidebarright > .nav-tabs > li > a {
	border: 0;
	border-bottom: 2px solid transparent;
	border-radius: 0;
	padding: 9px 2px;
	margin: 0 22px 0 0;
	font-size: 13.5px;
	font-weight: 500;
	color: #6B7A90;
	background: transparent;
	white-space: nowrap;
}
body.employee_details .profilesidebarright > .nav-tabs > li.active > a,
body.employee_details .profilesidebarright > .nav-tabs > li.active > a:hover,
body.employee_details .profilesidebarright > .nav-tabs > li.active > a:focus {
	color: #C9421F;
	border-bottom-color: #F05B3A;
	background: transparent;
	font-weight: 600;
}
body.employee_details .profilesidebarright > .nav-tabs > li > a:hover { color: #35435A; background: transparent; }

/* 45.7 The empty state read as a failure. Same treatment as the other lists. */
body.employee_details .nothing-found,
body.employee_details .admintable_nothingfound {
	padding: 30px 0;
	text-align: center;
	font-size: 13px;
	color: #8B98AB;
}

@media (max-width: 900px) {
	body.employee_details .customer-details-wrapper { display: block; }
	body.employee_details .customer-details-wrapper > .col-md-3 { max-width: none; margin-bottom: 16px; }
}

/* ==========================================================================================
   46. GLOBAL SEARCH -- THE TOP-BAR BOX AND ITS TYPE-AHEAD
   ==========================================================================================

   The control was a 73%-wide input floated inside a 300px-offset absolute box, sized for
   nothing in particular and with no results surface at all -- it existed only to submit the
   page. It now opens as a fixed 460px combobox anchored under the search icon, with a result
   panel that carries the same 7px radius, #E4E7EC borders, 36px control height and #F05B3A
   accent as the rest of the identity, so the one piece of chrome present on every screen no
   longer reads as though it came from a different product.

   Everything is scoped to #search-form-popup / #gs-panel. The top bar is shared markup and
   there is no body class to hang this on, so the ids are the fence.
   ------------------------------------------------------------------------------------------ */

/* 46.1 The box itself. `left:-300px` on a 73% form was the old geometry; this pins the panel
   to the icon and gives the input the full width, which is what makes room for the results. */
#search-form-popup {
	position: absolute;
	top: -6px;
	right: 0;
	left: auto;
	width: 460px;
	max-width: calc(100vw - 40px);
	z-index: 1050;
}

#search-form-popup .navbar-form {
	float: none !important;
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	position: relative;
}

#search-form-popup .navbar-form .form-control {
	width: 100%;
	height: 40px;
	padding: 0 40px 0 14px;
	background: #FFF;
	border: 1px solid #D6DCE5;
	border-radius: 8px;
	box-shadow: 0 6px 20px rgba(16, 26, 43, 0.10);
	font-size: 13px;
	color: #101A2B;
}

#search-form-popup .navbar-form .form-control:focus {
	border-color: #F05B3A;
	box-shadow: 0 0 0 3px rgba(240, 91, 58, 0.14), 0 6px 20px rgba(16, 26, 43, 0.10);
	outline: none;
}

#search-form-popup .navbar-form .form-control::placeholder { color: #98A2B3; font-size: 13px; }
/* styles.css:918 turns the placeholder white on focus, which reads as "the box emptied". */
#search-form-popup .navbar-form .form-control:focus::placeholder { color: #B7C0CD; }

#search-form-popup .navbar-form button {
	position: absolute;
	top: 0;
	right: 0 !important;
	left: auto !important;
	width: 40px;
	height: 40px;
	padding: 0;
	background: transparent;
	border: 0;
	box-shadow: none;
	color: #667085;
	display: flex;
	align-items: center;
	justify-content: center;
}
#search-form-popup .navbar-form button:hover { background: transparent; padding: 0; color: #F05B3A; }

/* 46.2 The results surface. A separate card under the input rather than a taller input, so
   the query stays visible and readable while the list scrolls. */
.gs-panel {
	position: absolute;
	top: 46px;
	left: 0;
	right: 0;
	background: #FFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	box-shadow: 0 14px 40px rgba(16, 26, 43, 0.16);
	overflow: hidden;
	text-align: left;
	font-size: 13px;
	color: #101A2B;
}
.gs-panel[hidden] { display: none !important; }

/* 46.3 Object-type filter chips. These re-query rather than filter what is on screen -- the
   all-groups response is capped at five per type, so filtering client-side would silently
   claim five was the total. */
.gs-scopes {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	padding: 10px 12px;
	border-bottom: 1px solid #EEF1F5;
	background: #FAFBFC;
}
.gs-scope {
	height: 26px;
	padding: 0 11px;
	border: 1px solid #DDE3EB;
	border-radius: 13px;
	background: #FFF;
	color: #5A6779;
	font-size: 12px;
	font-weight: 500;
	line-height: 24px;
	cursor: pointer;
}
.gs-scope:hover { border-color: #C3CCD9; color: #35435A; }
.gs-scope.is-on {
	background: #F05B3A;
	border-color: #F05B3A;
	color: #FFF;
}

/* 46.4 The scrolling result body. Capped so the panel can never run off a laptop screen. */
.gs-body {
	max-height: 400px;
	overflow-y: auto;
	overscroll-behavior: contain;
}

.gs-group + .gs-group { border-top: 1px solid #EEF1F5; }

.gs-group-head {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 10px 14px 6px;
}
.gs-group-title {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: #8B98AB;
}
.gs-group-count {
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 9px;
	background: #EEF1F5;
	color: #5A6779;
	font-size: 11px;
	font-weight: 600;
	line-height: 18px;
	text-align: center;
}
.gs-group-all {
	margin-left: auto;
	padding: 0;
	border: 0;
	background: none;
	color: #F05B3A;
	font-size: 12px;
	font-weight: 600;
	cursor: pointer;
}
.gs-group-all:hover, .gs-group-all:focus { color: #C9421F; text-decoration: underline; }

/* 46.5 One result row. The whole row is the hit target -- a title-only link makes people aim. */
.gs-item {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 14px;
	color: #101A2B;
	text-decoration: none;
	cursor: pointer;
}
.gs-item:hover,
.gs-item:focus,
.gs-item.is-active {
	background: #FFF4F1;
	color: #101A2B;
	text-decoration: none;
	outline: none;
}
.gs-item.is-active { box-shadow: inset 3px 0 0 #F05B3A; }

.gs-ava {
	flex: 0 0 30px;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	background: #1A4159;
	color: #FFF;
	font-size: 11px;
	font-weight: 600;
	line-height: 30px;
	text-align: center;
	text-transform: uppercase;
}
/* One hue per object type, so the type is readable before the label is. Eight groups is
   more than a palette can carry as "categories", so these run cool-to-warm in registry
   order rather than pretending to be eight unrelated identities. */
.gs-ava--contacts    { background: #1A4159; }
.gs-ava--companies   { background: #2E6F8E; }
.gs-ava--deals       { background: #1F7A5C; }
.gs-ava--lineitems   { background: #4A7C3F; }
.gs-ava--leadgen     { background: #8A7A2B; }
.gs-ava--marketing   { background: #A2542F; }
.gs-ava--automations { background: #6B4A7A; }
.gs-ava--users       { background: #5B4B8A; }
.gs-ava--tickets     { background: #8A5A2B; }
.gs-ava--recent,
.gs-ava--all       { background: #EEF1F5; color: #5A6779; font-size: 14px; }

.gs-item-text { min-width: 0; flex: 1 1 auto; }
.gs-item-title {
	display: block;
	font-size: 13px;
	font-weight: 500;
	line-height: 18px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.gs-item-sub {
	display: block;
	font-size: 12px;
	line-height: 16px;
	color: #8B98AB;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.gs-item-meta {
	flex: 0 0 auto;
	max-width: 34%;
	font-size: 12px;
	color: #5A6779;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.gs-panel mark {
	padding: 0;
	background: rgba(240, 91, 58, 0.18);
	color: inherit;
	font-weight: 700;
}

/* 46.6 Empty, hint and error states get the same frame as results, not a bare line of text. */
.gs-state { padding: 22px 16px; text-align: center; }
.gs-state-title { font-size: 13px; font-weight: 600; color: #35435A; }
.gs-state-note  { margin-top: 4px; font-size: 12px; color: #8B98AB; }
.gs-state.is-error .gs-state-title { color: #C9421F; }

/* 46.7 The footer keeps the full-page view one click away and teaches the keyboard. */
.gs-foot { border-top: 1px solid #EEF1F5; background: #FAFBFC; }
.gs-foot .gs-item { padding: 10px 14px; font-weight: 500; }
.gs-hint {
	display: block;
	padding: 0 14px 9px;
	font-size: 11px;
	color: #98A2B3;
}
.gs-hint kbd {
	display: inline-block;
	min-width: 16px;
	margin-right: 3px;
	padding: 1px 4px;
	border: 1px solid #DDE3EB;
	border-bottom-width: 2px;
	border-radius: 4px;
	background: #FFF;
	box-shadow: none;
	color: #5A6779;
	font-family: inherit;
	font-size: 10px;
	line-height: 14px;
}

@media (max-width: 640px) {
	#search-form-popup { width: calc(100vw - 24px); right: -8px; }
	.gs-body { max-height: 60vh; }
	.gs-item-meta { display: none; }
}

/* ------------------------------------------------------------------------------------------
   46.8 THE FULL RESULTS PAGE

   The page and the dropdown are now two renderings of one query (see GS\Search\GlobalSearch),
   so they should read as the same feature. These are the page's own three pieces: the object
   filter, the section heads, and the states. The result tables themselves are ordinary TGrids
   and inherit the standard table styling -- deliberately, so a search result looks like every
   other row in the product.
   ------------------------------------------------------------------------------------------ */

.gs-page-scopes {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0 0 18px;
}
.gs-page-scope {
	height: 30px;
	padding: 0 13px;
	border: 1px solid #DDE3EB;
	border-radius: 15px;
	background: #FFF;
	color: #5A6779;
	font-size: 12px;
	font-weight: 500;
	line-height: 28px;
	text-decoration: none;
}
.gs-page-scope:hover,
.gs-page-scope:focus { border-color: #C3CCD9; color: #35435A; text-decoration: none; }
.gs-page-scope.is-on {
	background: #F05B3A;
	border-color: #F05B3A;
	color: #FFF;
}

/* The section head carries its own count, so "how many did this find" is answered before the
   table is read -- and before the "View all" button below it is needed. */
.gs-page-sec {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 26px 0 10px;
	font-size: 15px;
	font-weight: 600;
	color: #101A2B;
}
.gs-page-sec:first-of-type { margin-top: 4px; }
.gs-page-count {
	min-width: 22px;
	height: 20px;
	padding: 0 7px;
	border-radius: 10px;
	background: #EEF1F5;
	color: #5A6779;
	font-size: 12px;
	font-weight: 600;
	line-height: 20px;
	text-align: center;
}

.gs-page-note {
	padding: 26px 22px;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	background: #FFF;
	color: #5A6779;
	font-size: 13px;
	line-height: 1.55;
}
.gs-page-note strong { color: #35435A; }
.gs-page-note--empty { text-align: center; }

/* 46.9 The results page runs SEVERAL small tables down one screen, which is the case the global
   table styling was never tuned for.

   `.table-responsive { min-height: 200px }` (stylesheets.css:28) reserves a fixed slab under
   every grid so an EMPTY list still has somewhere to print "nothing found". On a list screen
   that is invisible -- the table is already taller. Here a Contacts group with one hit rendered
   an 84px table inside a 200px box, so the page read as a column of half-empty cards. The same
   override is already made for the organizations list (6493), the customer detail page (7040)
   and the tab wrapper (7437); this is the fourth page with the same shape. */
body.search_results_page .table-responsive { min-height: 0; }

/* The zero-result line still needs room, or "Nothing matches" sits jammed against the header. */
body.search_results_page .table-responsive tbody td { min-height: 0; }
body.search_results_page .admintable tbody tr td[colspan]:not([colspan="1"]) { padding: 26px 12px; text-align: center; color: #8B98AB; }

/* A search result exists to be clicked. In the shared table style the first cell is the same
   near-black as every other cell, so the one thing the row is FOR did not look actionable. */
body.search_results_page .admintable tbody td:first-child a {
	color: #101A2B;
	font-weight: 600;
}
body.search_results_page .admintable tbody td:first-child a:hover,
body.search_results_page .admintable tbody td:first-child a:focus {
	color: #C9421F;
	text-decoration: underline;
}

/* Each group is a block: head, table, then its "View all" button. Tighten the gap the button
   block carries by default so it belongs to the table above it rather than floating between
   two groups. */
body.search_results_page .start_wizard__button { margin: 10px 0 4px; }
body.search_results_page .start_wizard__button .adminbuttons { padding: 0; }

/* ------------------------------------------------------------------------------------------
   45.8 EVERY TAB ON THE PROFILE GETS THE SAME SURFACE

   Measured before this rule: only three of the seven tab bodies -- Assigned Contacts, Shared
   Content and Video Calls -- sat on a white card, and they did so BY ACCIDENT. The card was
   never the tab's; it belongs to `.table-responsive`, which those three happen to contain.
   Tags, Content, Videos and Upload Video rendered their contents straight onto the page's
   grey, and Videos rendered literally nothing -- zero characters -- when the user had no
   videos, so an empty tab was indistinguishable from a broken one.

   The card now belongs to the tab BODY, which every tab has, so the surface is the same
   whether the tab holds a table, a form, a button list or nothing at all.
   ------------------------------------------------------------------------------------------ */
body.employee_details .profilesidebarright .block-content-outer {
	background: #FFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	padding: 18px 20px;
	min-height: 220px;
}

/* A table brings its own edge-to-edge surface. Nesting it inside the card's padding would
   inset the header row and draw a second frame around it, so those tabs keep the card and
   give up the padding -- which is exactly how Assigned Contacts already looked. */
body.employee_details .profilesidebarright .block-content-outer:has(> .table-responsive) {
	padding: 0;
	overflow: hidden;
}
body.employee_details .profilesidebarright .block-content-outer > .table-responsive {
	border-radius: 10px;
	min-height: 0;
	background: transparent;
}

/* The panel wrapper is a zero-height hook the UI layer always emits; it must not add a gap
   above the first real element in a tab that now has padding of its own. */
body.employee_details .profilesidebarright .block-content-outer > .common_adminpanel:empty { display: none; }

/* 45.9 THE EMPTY STATE, one voice for every tab.
   `SingleLineLabel()` renders into a full-width cell; the tabs that are not tables get the
   same treatment through `.profile-tab-empty` (emitted by employeedetails.php). Both read the
   same and sit in the same place, so "nothing here yet" looks deliberate on all seven. */
body.employee_details .profile-tab-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 180px;
	padding: 20px;
	text-align: center;
}
body.employee_details .profile-tab-empty .pte-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background: #EEF1F5;
	color: #8B98AB;
}
body.employee_details .profile-tab-empty .pte-title {
	font-size: 13px;
	font-weight: 600;
	color: #35435A;
}
body.employee_details .profile-tab-empty .pte-note {
	font-size: 12px;
	color: #8B98AB;
	max-width: 420px;
	line-height: 1.5;
}

/* The two tabs that are genuinely a working surface rather than a list -- Content and Upload
   Video -- were flush against the page edge. Inside the card they need their own bottom
   breathing room, and their bootstrap grid must not push out of it. */
body.employee_details .profilesidebarright .block-content-outer > .col-md-12,
body.employee_details .profilesidebarright .block-content-outer .campainsection { padding-left: 0; padding-right: 0; }
body.employee_details .profilesidebarright .block-content-outer form { margin-bottom: 0; }

/* =========================================================================================
   35. PROJECTS WORKSPACE

   The PM module kept its own icon strip, mixed actions into the level-2 pills, and printed
   raw counts. This section skins it onto the same language as Deals / Calendar / record
   tabs: glance, .ct-toolbar, .ct-list, .deal-head, a bare nav-tabs strip, and .cf-layout
   for add/edit pages. No second button scale, no route sheet.
   ========================================================================================= */

/* .pm-glance now carries .cal-glance too, so it inherits the white card, radius, shadow and
   padding instead of floating the tiles straight on the page wash. Only the bottom margin is
   PM's own. The gap is NOT overridden any more -- it was 18px/28px against the shared 12px,
   which is what made the Projects strip read as a different component from Calendar's. */
body.pm .pm-glance { margin: 0 0 16px; }
body.pm .pm-glance .cal-stats { flex-wrap: wrap; }
body.pm .pm-workspace {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 18px 20px 14px;
	margin-bottom: 16px;
}

body.pm .pm-head { margin-bottom: 14px; }
body.pm .pm-head-id {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0 0 8px;
}
body.pm .pm-head-desc {
	max-width: 62ch;
	margin: 0 0 10px;
	color: #47566A;
	line-height: 1.5;
}
body.pm .pm-head-meta { display: flex; flex-wrap: wrap; gap: 6px; }
body.pm .pm-head .pm-bar { min-width: 140px; }
body.pm .pm-board-filters {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 10px 16px;
	margin: 0 0 16px;
}

body.pm-workspace-page .pm-workspace > .nav.nav-tabs {
	display: flex;
	flex-wrap: nowrap;
	overflow-x: auto;
	gap: 4px;
	margin: 0 0 14px;
	padding: 0 0 2px;
	border-bottom: 1px solid #E4E7EC;
	list-style: none;
}
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li { float: none; flex: 0 0 auto; margin: 0; }
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li > a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 10px 12px;
	font-size: 13px;
	font-weight: 600;
	color: #6B7A90;
	border: 0;
	background: transparent;
	white-space: nowrap;
}
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li > a:hover,
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li > a:focus {
	color: #35435A;
	background: transparent;
	border: 0;
}
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li.active > a,
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li.active > a:hover,
body.pm-workspace-page .pm-workspace > .nav.nav-tabs > li.active > a:focus {
	color: #101A2B;
	background: transparent;
	border: 0;
	box-shadow: inset 0 -3px 0 var(--accent);
}
body.pm-workspace-page .pm-workspace .tab-item-count {
	min-width: 18px;
	padding: 0 6px;
	border-radius: 999px;
	background: #F1F3F6;
	color: #47566A;
	font-size: 11px;
	font-weight: 600;
	line-height: 18px;
	text-align: center;
}

body.pm .pm-toolbar { align-items: center; margin-bottom: 14px; }
body.pm .pm-toolbar .ct-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

body.pm .pm-filters,
body.pm .pm-viewswitch {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	align-items: center;
}
body.pm .pm-filter {
	display: inline-flex;
	align-items: center;
	/* 42px, not 36px: .ct-toolbar is align-items:flex-start and .ct-add is min-height:42px,
	   so a 36px pill sat visibly short of the Search and Create controls on the same row. */
	height: 42px;
	padding: 0 12px;
	border: 1px solid #DDE2E9;
	border-radius: 7px;
	background: #FFFFFF;
	color: #35435A;
	font-size: 13px;
	font-weight: 600;
	text-decoration: none;
}
body.pm .pm-filter:hover { background: #F7F9FB; color: #101A2B; }
body.pm .pm-filter.is-on {
	background: var(--accent-tint);
	border-color: var(--accent);
	color: var(--accent-text);
}

body.pm .pm-chip {
	display: inline-flex;
	align-items: center;
	height: 22px;
	padding: 0 8px;
	border-radius: 999px;
	border: 1px solid #DDE2E9;
	background: #F7F9FB;
	color: #35435A;
	font-size: 11px;
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
}
body.pm .pm-chip-todo { background: #F1F3F6; color: #35435A; border-color: #DDE2E9; }
body.pm .pm-chip-progress { background: #E4F2EC; color: #186B4E; border-color: #A9D3C1; }
body.pm .pm-chip-review { background: #E8F1FB; color: #184E8B; border-color: #B5CDE8; }
body.pm .pm-chip-hold { background: #FFF6E5; color: #8A5A00; border-color: #E8D2A2; }
body.pm .pm-chip-clarif { background: #FFF4F0; color: #C2410C; border-color: #F5C4B4; }
body.pm .pm-chip-done { background: #EEF2F6; color: #47566A; border-color: #D5DCE5; }
body.pm .pm-chip-cancel { background: #FDECEA; color: #9A2A18; border-color: #F0C4BE; }
body.pm .pm-chip-high { background: #FDECEA; color: #9A2A18; border-color: #F0C4BE; }
body.pm .pm-chip-mid { background: #FFF6E5; color: #8A5A00; border-color: #E8D2A2; }
body.pm .pm-chip-low { background: #F1F3F6; color: #6B7A90; border-color: #DDE2E9; }
body.pm .pm-chip-muted { background: #F7F9FB; color: #6B7A90; border-color: #E4E7EC; }

body.pm .pm-bar {
	position: relative;
	height: 22px;
	min-width: 88px;
	background: #EEF1F4;
	border-radius: 999px;
	overflow: hidden;
}
body.pm .pm-bar-fill {
	display: block;
	height: 100%;
	background: #186B4E;
	border-radius: inherit;
}
body.pm .pm-bar-label {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	font-weight: 600;
	color: #101A2B;
	font-variant-numeric: tabular-nums;
}

body.pm .pm-list td.nm a { color: #101A2B; font-weight: 600; }
body.pm .pm-list-sub {
	margin-top: 4px;
	font-size: 12px;
	font-weight: 400;
	color: #6B7A90;
	white-space: normal;
	max-width: 42ch;
}
body.pm .pm-empty { text-align: center; padding: 28px 16px; }
body.pm .pm-empty .es-title,
body.pm .is-empty .es-title { display: block; font-weight: 600; color: #35435A; margin-bottom: 4px; }
body.pm .pm-empty .es-hint,
body.pm .is-empty .es-hint { display: block; color: #7C8AA0; margin-bottom: 12px; }
body.pm .pm-active-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }

body.pm .cell-working-status { box-shadow: inset 3px 0 0 #186B4E; }
body.pm .cell-nexttask-status { box-shadow: inset 3px 0 0 #C2410C; }
body.pm .cell-inprogress-higlighted-status { box-shadow: inset 3px 0 0 #A9D3C1; }
body.pm .cell-onreview-higlighted-status { box-shadow: inset 3px 0 0 #184E8B; }
body.pm .pm-shortname-label {
	margin-left: 8px;
	font-size: 11px;
	font-weight: 600;
	color: #6B7A90;
	font-variant-numeric: tabular-nums;
}
body.pm .pm-shortname-label-completed { text-decoration: line-through; }

body.pm .pm-files {
	margin-top: 18px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 18px 20px;
}
body.pm .pm-files-head {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 12px;
}
body.pm .pm-files-head h3 {
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	color: #101A2B;
}
body.pm .pm-files-count {
	min-width: 18px;
	padding: 0 6px;
	border-radius: 999px;
	background: #F1F3F6;
	font-size: 11px;
	font-weight: 600;
	color: #47566A;
	line-height: 18px;
	text-align: center;
}

/* The page-form card itself is the shared recipe up in §the add-form block -- PM is listed
   there rather than repeating the five declarations here. What IS PM's own is the reset
   below: .pm-form-main already draws the card, so a nested .adminform_form inside it must
   not draw a second one. */
body.pm-form-page .pm-form-main .adminform_form {
	background: transparent;
	border: 0;
	padding: 0;
}
body.pm-form-page .cf-side-card {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 18px 20px;
	position: sticky;
	top: 16px;
}
body.pm-form-page .cf-side-card h4 {
	margin: 0 0 8px;
	font-size: 14px;
	font-weight: 600;
	color: #101A2B;
}
body.pm-form-page .cf-side-card p {
	margin: 0 0 10px;
	font-size: 13px;
	line-height: 1.5;
	color: #47566A;
}

body.pm .pm-task {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: 22px;
	align-items: start;
}
body.pm .pm-task-main,
body.pm .pm-task-side > section {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 18px 20px;
}
body.pm .pm-task-side { display: flex; flex-direction: column; gap: 14px; }
body.pm .pm-task-desc {
	color: #35435A;
	line-height: 1.55;
	margin-bottom: 18px;
}
body.pm .pm-task-desc:empty { display: none; }
body.pm .pm-task h3 {
	margin: 0 0 12px;
	font-size: 14px;
	font-weight: 600;
	color: #101A2B;
}
body.pm .pm-task .project-actions-section .adminbuttons {
	justify-content: flex-start;
	flex-wrap: wrap;
}
body.pm .pm-dl {
	display: grid;
	grid-template-columns: 120px minmax(0, 1fr);
	gap: 8px 12px;
	margin: 0;
}
body.pm .pm-dl dt { color: #6B7A90; font-size: 12px; font-weight: 600; }
body.pm .pm-dl dd { margin: 0; color: #101A2B; font-size: 13px; }

body.pm .draggable-wrapper {
	margin: 0 0 18px;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 12px;
}
body.pm .pipeline-action-buttons { display: none; }

@media (max-width: 1100px) {
	body.pm .pm-task { grid-template-columns: minmax(0, 1fr); }
}

/* 45.10 The Content tab reserves a 700px slab for a grid that may not be there.
   `.campaignslist` carries `min-height:700px` so the campaign tiles have somewhere to land.
   That was invisible while the tab sat on the page's grey; inside the card it became 700px of
   blank white below the empty state, making the card nine hundred pixels tall to say one
   sentence. Collapse it exactly when the empty state is what we are showing. */
body.employee_details .profilesidebarright .block-content-outer:has(> .profile-tab-empty) .campaignslist { min-height: 0; }
body.employee_details .profilesidebarright .block-content-outer:has(> .profile-tab-empty) .campainsection { min-height: 0; }

/* The inner sub-tab strip is a floated bootstrap column; without this the card closes above
   it and the float hangs outside the white. */
body.employee_details .profilesidebarright .block-content-outer::after { content: ""; display: table; clear: both; }

/* 45.11 THE GREY STUB AFTER THE LAST TAB.
   stylesheets.css:559 draws `.profilesidebarright .nav:after` as a #dbdce0 bar meant to be the
   strip's 2px underline -- but its `height: 2px` is COMMENTED OUT in that rule. Without a
   height the pseudo-element becomes a display:table box that takes the line's full height and
   whatever width the floated tabs left over, so it paints a 39px grey rectangle after the last
   tab. Measured here: 322.96px wide by 39.28px tall, which is exactly 1015 - 692, the strip
   width minus the tabs.
   Proved it was this and not a stray element by painting the page ground magenta: everything
   turned magenta except that rectangle.
   The bar is still the strip's float clear, so it keeps display:table and loses only its
   height and its colour. Section 45.6 already draws the real underline as a border-bottom. */
body.employee_details .profilesidebarright .nav:after {
	height: 0;
	background: transparent;
	top: 0;
}

/* ==========================================================================================
   47. THE CALENDAR FILTER BAR, AND LATENESS THAT DOES NOT EAT THE COLOUR
   ==========================================================================================

   The grid used to repaint every overdue event a single red. Measured on brand 1, seven of nine
   events were overdue, so the month was almost entirely one colour and the legend beneath it --
   which named four sources by colour -- described something that was not on screen. Colour now
   always means the SOURCE; lateness is a red rail down the left of the chip, which stacks with
   the colour instead of replacing it.

   The legend became the filter. A person reading a key is already asking a question about one
   of the sources ("which of these are deals?"), so the key is where to answer it.
   ------------------------------------------------------------------------------------------ */

.cal-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0 0 14px;
}
.cal-filters-label {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: #8B98AB;
	margin-right: 2px;
}

/* The chip carries its source colour in --chip, so one rule styles every type and a new type
   added to UpcomingService::Types() needs no CSS at all. */
.cal-chip {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	height: 30px;
	padding: 0 11px;
	border: 1px solid #DDE3EB;
	border-radius: 15px;
	background: #FFF;
	color: #5A6779;
	font-size: 12px;
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
}
.cal-chip i {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var(--chip, #98A2B3);
	flex: 0 0 9px;
}
.cal-chip-n {
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 9px;
	background: #EEF1F5;
	color: #5A6779;
	font-size: 11px;
	font-weight: 600;
	line-height: 18px;
	text-align: center;
}
.cal-chip:hover { border-color: #C3CCD9; color: #35435A; }

/* ON is the resting state -- everything is shown until you say otherwise -- so OFF has to be
   the one that looks different, not the other way round. */
.cal-chip[aria-pressed="false"] { background: #F7F8FA; color: #A6B0BF; border-color: #E9EDF2; }
.cal-chip[aria-pressed="false"] i { background: #CBD2DC; }
.cal-chip[aria-pressed="false"] .cal-chip-n { background: #EEF1F5; color: #A6B0BF; }

.cal-chip--overdue i { background: #9A2A18; }
.cal-chip--overdue[aria-pressed="true"] { border-color: #9A2A18; color: #9A2A18; background: #FDECE8; }
.cal-chip--reset { border-style: dashed; color: #8B98AB; }
.cal-chip--reset:hover { color: #35435A; }

/* 47.1 Lateness as a rail, not a repaint. */
.fc .cal-ev.is-overdue {
	box-shadow: inset 3px 0 0 #9A2A18;
	filter: saturate(0.85);
}
.fc .cal-ev.is-today { box-shadow: inset 3px 0 0 rgba(255, 255, 255, 0.85); }

/* 47.2 The chips in the grid: readable at 11px, and never taller than the row needs. */
.fc .cal-ev {
	border-radius: 4px;
	font-size: 11px;
	line-height: 1.35;
	padding: 1px 4px;
}

/* 47.3 "Coming up" -- WHAT is due, not only how much.
   Three totals cannot distinguish a week of twelve appointments from a week of twelve deals
   slipping, and those call for opposite responses. Each pill carries its source colour in
   --kind and deep-links into the calendar pre-filtered to that type. Sits between the totals
   and the next-up list: the counts answer "how bad", the pills answer "what of", the list
   answers "which ones". */
.up-kinds {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	padding: 10px 14px 0;
}
.up-kind {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 24px;
	padding: 0 8px;
	border: 1px solid #E9EDF2;
	border-radius: 12px;
	background: #FFF;
	color: #5A6779;
	font-size: 11px;
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
}
.up-kind i {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--kind, #98A2B3);
	flex: 0 0 7px;
}
.up-kind b { color: #101A2B; font-weight: 700; }
.up-kind:hover,
.up-kind:focus {
	border-color: var(--kind, #C3CCD9);
	color: #35435A;
	text-decoration: none;
}

/* The widget is narrow; past four or five pills it must wrap rather than stretch the card. */
@media (max-width: 1400px) {
	.up-kind span { max-width: 92px; overflow: hidden; text-overflow: ellipsis; }
}

/* 47.4 A type with no events keeps its chip but steps back.
   Eight sources means eight chips, and on a quiet week most of them are zero. Removing the
   empty ones would change the bar's shape between brands and between weeks -- a control that
   moves under you is worse than one with a few greyed entries -- so they stay put and lose
   contrast instead. */
.cal-chip.is-empty { opacity: 0.55; }
.cal-chip.is-empty:hover { opacity: 1; }

/* 47.5 Room for a sentence.
   Bootstrap caps a tooltip at 200px, which turns the longer filter hints into a six-line
   column the width of a chip. These explanations are the reason the filter bar is usable by
   someone who did not build it, so they get a readable measure. */
.cal-filters + .tooltip .tooltip-inner,
body.customers_list_section .tooltip .tooltip-inner,
.tooltip .tooltip-inner { max-width: 320px; }
.tooltip .tooltip-inner {
	padding: 8px 11px;
	border-radius: 7px;
	font-size: 12px;
	line-height: 1.45;
	text-align: left;
}

/* =========================================================================================
   35d. PROJECTS -- KANBAN CARD

   The card used to be six label:value rows ("Title:", "Created:", "Assigned User:",
   "Status:"). That is a form, not a card: at a glance you read the labels, not the work.
   Two of those rows were also redundant -- the status is already said by the column the card
   sits in, and nobody acts on a created date.

   What remains is ordered the way the card is actually scanned: the id, the title, then who
   holds it and when it is due. Colour is spent in ONE place -- an overdue date -- following
   the rule already set for the glance tiles (.cal-stat.is-over): if every card is coloured,
   no card is urgent.
   ========================================================================================= */
body.pm .leadcontainer > .pm-card {
	position: relative;
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 10px;
	box-shadow: 0 1px 2px rgba(16, 26, 43, .04);
	margin: 0 0 10px;
	padding: 12px 14px;
}
body.pm .leadcontainer > .pm-card:hover { border-color: #CBD3DE; }

body.pm .pm-card-top { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
body.pm .pm-card-id {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .04em;
	color: #7C8AA0;
	font-variant-numeric: tabular-nums;
}
body.pm .pm-card .name { margin: 0; }
body.pm a.pm-card-title {
	display: block;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
	color: #101A2B;
	text-decoration: none;
}
body.pm a.pm-card-title:hover { color: var(--accent-text); }

body.pm .pm-card-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 10px;
	margin: 8px 0 0;
	font-size: 12px;
	color: #6B7A90;
}
body.pm .pm-card-due { font-variant-numeric: tabular-nums; }
/* The one place this card spends colour. */
body.pm .pm-card.is-overdue .pm-card-due { color: #9A2A18; font-weight: 600; }
body.pm .pm-card.is-overdue { border-color: #F0C7BF; }

/* The row action lives top-right, out of the reading path. */
body.pm .pm-card > .delete_edit_lead { position: absolute; top: 8px; right: 8px; }

/* The board track: 280px columns fit five without a scrollbar on a normal screen; wider
   status sets still scroll, which is honest rather than cramped. */
body.pm .pm-board-track .headerstep,
body.pm .pm-board-track .leadcontainer { padding-left: 10px; padding-right: 10px; }
body.pm .pm-board-track .headerstep {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #6B7A90;
}

/* =========================================================================================
   35e. PROJECTS -- TASK ROWS

   The task tables inherited the EMPTY-STATE treatment on every populated cell, because
   `td[colspan]` matches the colspan="1" the grid writes on ordinary cells: centred text,
   44px of vertical padding, muted colour, and a magnifier disc drawn by ::before above every
   value. A one-task list read as five empty states side by side and the task itself was the
   least visible thing on the row. Those selectors are now scoped with :not([colspan="1"]).

   What follows is the row itself: a scannable line, with the title carrying the weight.
   ========================================================================================= */
body.pm table.admintable > tbody > tr > td { vertical-align: middle; }

/* The task id belonged to the title, but `pull-right` floated it to the far edge of a 550px
   cell -- an id stranded in whitespace, a hand-span away from the thing it identifies. */
/* !important is not decoration here: bootstrap.css declares `.pull-right { float: right
   !important }`, so no amount of specificity on our side wins. Overriding a utility class
   that carries !important is the one case that needs one back. */
body.pm table.admintable .pm-shortname-label.pull-right {
	float: none !important;
	display: inline-block;
	vertical-align: baseline;
}

body.pm table.admintable > tbody > tr > td:first-child a {
	font-weight: 600;
	color: #101A2B;
	text-decoration: none;
}
body.pm table.admintable > tbody > tr > td:first-child a:hover { color: var(--accent-text); }

/* A hover band is what makes a wide row scannable -- at 1600px the eye loses the line
   between the title and the status chip seven columns away. */
body.pm table.admintable > tbody > tr:hover > td { background: #F7F9FB; }

/* =========================================================================================
   35f. PROJECTS -- STATUS FILTER CHIPS

   The row read as heavy because it was not a pill row at all: `.pm-filter` carried
   `.ab-button`'s declarations token for token -- 1px #DDE2E9, radius 7px, #FFFFFF ground,
   #35435A at 13px/600 -- just 6px taller. Eight of those side by side is a button toolbar,
   and the eye reads eight equally-weighted actions instead of one filter.

   The app already had an answer for this exact job. `.gs-page-scope` (search results) and
   `.cal-chip` (calendar) were written in different sections by different hands and landed on
   byte-identical metrics: 30px tall, radius 15px (half the height), 1px #DDE3EB, #5A6779 at
   12px/500, hover #C3CCD9. Two independent authors converging is the closest thing this
   stylesheet has to a specification, so that is what the status filters become.

   SELECTED STAYS TINTED, NOT FILLED, even though the level-2 nav directly above uses a solid
   green fill. The two rows are not peers: the nav CHANGES ROUTE (d=mytasks / d=mypostedtasks
   / d=overdue) while this row REFINES the list that route produced. Filling both would stack
   two identical-weight bars and flatten the hierarchy. identity.css:1373 already states the
   rule -- "Segmented / current state: tinted, not filled, so the fill stays reserved for
   priority" -- and `.pm-filter.is-on` happens to be the only correctly-tokenised selected
   state in this file, measured at 4.60:1 against the 4.5:1 AA floor.

   SCOPED TO .pm-filters ON PURPOSE. `.pm-viewswitch` (Table / Status board / Priority board)
   shares the `.pm-filter` class but is an either/or VIEW SWITCH sitting inside `.ct-toolbar`,
   where the 42px height is what keeps it level with `.ct-add`. It keeps the button chassis.
   ========================================================================================= */
body.pm .pm-filters {
	/* The row had no margin at all and sat flush against the grid beneath it. */
	margin: 0 0 14px;
	gap: 6px;
}
body.pm .pm-filters .pm-filter {
	height: 30px;
	padding: 0 13px;
	border: 1px solid #DDE3EB;
	border-radius: 15px;
	color: #5A6779;
	font-size: 12px;
	font-weight: 500;
	/* The sticky .tab-nav is top:48px with min-height:52px, so a pill tabbed to after the
	   page scrolls would otherwise land underneath it. WCAG 2.2 SC 2.4.11. */
	scroll-margin-top: 104px;
}
body.pm .pm-filters .pm-filter:hover {
	background: #FFFFFF;
	border-color: #C3CCD9;
	color: #35435A;
}
body.pm .pm-filters .pm-filter.is-on {
	background: var(--accent-tint);
	border-color: var(--accent);
	color: var(--accent-text);
	font-weight: 600;
}

/* =========================================================================================
   35g. COLLAPSED SIDEBAR -- THE ICONS WERE 1 PIXEL WIDE

   In the 68px rail every nav icon rendered as a 1x16 sliver, so the rail read as a column of
   faint dots with no way to tell Home from Deals.

   THE CHAIN. The icon SVG lives INSIDE `<span class="main-menu-text">`, next to the label --
   so identity.css:1030 (`body.nav-toggle ... .main-menu-text { display: none }`) would hide
   the icon along with the text. styles/style.css:1755 overrides that back to
   `display: flex; width: 40px; padding: 10px`, which restores the icon but turns the span
   into a 20px flex CONTENT box. The SVG is then a flex ITEM with the initial `flex-shrink: 1`
   and no width in CSS -- `width="16"` is only a presentation attribute, which flexbox is free
   to override -- and style.css:1744 gives it `display: table`, which blockifies it and drops
   any intrinsic width flexbox might otherwise have honoured. With `overflow: hidden` on the
   parent there is nothing to stop the shrink, so it lands at 1px.

   THE FIX is to stop it being shrinkable and give it a real size, rather than to unpick that
   override chain across two stylesheets. `flex: 0 0 auto` is the load-bearing declaration.

   Scoped to body.nav-toggle, so the expanded sidebar is untouched.
   ========================================================================================= */
body.nav-toggle .navigation .luna-nav.nav li a > div .main-menu-text svg {
	display: block;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	margin: 0 auto;
}
body.nav-toggle .navigation .luna-nav.nav li a > div .main-menu-text {
	box-sizing: border-box;
	justify-content: center;
}

/* A default scrollbar takes ~11px of a 68px rail -- a sixth of it -- and pushed the icons
   off centre. The rail still scrolls; the bar is just thin and unobtrusive. */
body.nav-toggle .navigation { scrollbar-width: thin; }
body.nav-toggle .navigation::-webkit-scrollbar { width: 4px; }
body.nav-toggle .navigation::-webkit-scrollbar-thumb {
	background: rgba(255, 255, 255, .18);
	border-radius: 2px;
}
body.nav-toggle .navigation::-webkit-scrollbar-track { background: transparent; }

/* =========================================================================================
   DASHBOARDS (Ticket 10) -- index.php?m=dashboards, the second tab of Home.

   Scoped to body.dashboards throughout. dashboard.css is deliberately NOT loaded on this
   route (it carries a bare `.row { margin: 0 }` reset and a global `.dropdown-item` shim),
   so the period pills and the "showing" sentence are restated here rather than borrowed.

   Charts are server-rendered: bars are CSS widths inside a track, the pie and the line are
   inline SVG. The `db-*` vocabulary mirrors the Reports `tr-*` / `rev-row` rules above --
   same hairline grid, 2px round-capped line, r=4 dots with a surface ring, CSS-only
   crosshair -- so the two pages read as one system. Colour tokens are the live green set
   (the second :root); the orange named in older comments is dead.
   ========================================================================================= */

/* ---- the control card: board tabs + actions above, the filters beneath ---------------
   One white card instead of a bare row of links. The top row is the board switcher and the
   actions; the filter row sits on a sunk surface so the two read as different kinds of
   control -- "which board" versus "which slice of it". */
body.dashboards .db-hero {
	margin: 0 0 18px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 12px;
	box-shadow: var(--sh-1);
	overflow: visible;           /* the dropdown menus hang below it */
}
body.dashboards .db-hero-top {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px 12px;
	padding: 12px 16px;
}
body.dashboards .db-hero-top > .ct-actions {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: 8px;
	margin-left: auto;
	flex: 1 1 auto;
	min-width: 0;
}
body.dashboards .db-hero-top > .ct-actions .ab-button { white-space: nowrap; }

/* Board tabs: underlined tabs rather than pills, so they read as "which board" and do not
   compete with the filter chips beneath. The active one carries the accent underline. */
body.dashboards .db-boards {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
	flex: 0 1 auto;
	min-width: 0;
}
body.dashboards .db-boards > a {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	height: 36px;
	padding: 0 12px;
	border-radius: 8px;
	color: var(--text-muted);
	font-size: var(--fs-md);
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color .12s ease, color .12s ease;
}
body.dashboards .db-boards > a svg { flex: 0 0 auto; opacity: .8; }
body.dashboards .db-boards > a:hover { background: var(--surface-mute); color: var(--ink); }
body.dashboards .db-boards > a.is-on {
	color: var(--ink);
	font-weight: 600;
	background: var(--accent-tint);
}
body.dashboards .db-boards > a.is-on::after {
	content: '';
	position: absolute;
	left: 12px; right: 12px; bottom: -13px;
	height: 3px;
	border-radius: 3px 3px 0 0;
	background: var(--accent-fill);
}
body.dashboards .db-boards > a.is-on svg { opacity: 1; color: var(--accent-text); }
body.dashboards .db-boards .db-star { display: inline-flex; color: #D9A21B; }

/* One-button POST forms sit inline with the links around them. */
body.dashboards .db-inline-form { display: inline; margin: 0; }
body.dashboards .db-inline-form button.ab-button { font-family: inherit; }

/* The filter row. */
body.dashboards .db-hero-filters {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px 14px;
	padding: 10px 16px;
	border-top: 1px solid var(--line);
	background: var(--surface-sunk);
	border-radius: 0 0 12px 12px;
}

/* The window as a segmented control: one bordered track, the active segment filled with the
   accent and labelled in --accent-on-fill (white on this green fails AA). */
body.dashboards .db-seg {
	display: inline-flex;
	align-items: center;
	height: 34px;
	padding: 3px;
	border: 1px solid var(--line-strong);
	border-radius: 9px;
	background: var(--surface);
	gap: 2px;
}
body.dashboards .db-seg-ico {
	display: inline-flex;
	align-items: center;
	padding: 0 6px 0 7px;
	color: var(--text-soft);
}
body.dashboards .db-seg-i {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	height: 26px;
	padding: 0 11px;
	border-radius: 6px;
	color: var(--text);
	font-size: var(--fs-sm);
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color .12s ease, color .12s ease;
}
body.dashboards .db-seg-i:hover { background: var(--surface-mute); color: var(--ink); text-decoration: none; }
body.dashboards .db-seg-i.is-on {
	background: var(--accent-fill);
	color: var(--accent-on-fill);
	font-weight: 650;
}
body.dashboards .db-seg-i.is-on:hover { background: var(--accent-hot); color: var(--accent-on-fill); }
body.dashboards .db-seg-custom { position: relative; display: inline-flex; }
body.dashboards .db-seg-custom .db-custom { min-width: 400px; left: auto; right: 0; top: 34px; padding: 20px; }
body.dashboards .db-seg-custom .db-custom label { font-size: var(--fs-sm); color: var(--text-muted); }
@media (max-width: 600px) {
	body.dashboards .db-seg-custom .db-custom { position: fixed; left: 16px; right: 16px; top: auto; min-width: 0; width: auto; }
}

/* The user picker chip, and the brand chips beside it. */
body.dashboards .db-pick-wrap { position: relative; }
body.dashboards .db-pick {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	height: 34px;
	padding: 0 11px 0 10px;
	border: 1px solid var(--line-strong);
	border-radius: 9px;
	background: var(--surface);
	color: var(--text);
	font-size: var(--fs-sm);
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
}
body.dashboards .db-pick svg:first-child { color: var(--text-soft); }
body.dashboards a.db-pick:hover { border-color: #C3CCD9; color: var(--ink); text-decoration: none; }
body.dashboards .db-pick.is-on { border-color: var(--accent-fill); background: var(--accent-tint); color: var(--accent-text); }
body.dashboards .db-pick.is-on svg { color: var(--accent-text); }
body.dashboards .db-pick.is-static { cursor: default; background: var(--surface-mute); border-color: var(--line); }
body.dashboards .db-pick-menu {
	padding: 6px 0;
	max-height: 320px;
	overflow-y: auto;
	min-width: 220px;
}
body.dashboards .db-pick-menu .dropdown-item {
	display: block;
	padding: 8px 14px;
	font-size: var(--fs-md);
	color: var(--text);
	text-decoration: none;
	white-space: nowrap;
}
body.dashboards .db-pick-menu .dropdown-item.active,
body.dashboards .db-pick-menu .dropdown-item:hover { background: var(--surface-mute); color: var(--ink); }

body.dashboards .db-brandbar {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
}
body.dashboards .db-brandbar-l {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--text-soft);
	margin-right: 2px;
}
body.dashboards .db-brandbar .cal-chip { text-decoration: none; }
body.dashboards .db-brandbar .cal-chip[aria-pressed="true"] {
	border-color: var(--accent-fill);
	background: var(--accent-tint);
	color: var(--accent-text);
}

/* The summary at the row's end: what the board is showing, in words. */
body.dashboards .db-showing {
	margin: 0 0 0 auto;
	font-size: var(--fs-sm);
	color: var(--text-muted);
	white-space: nowrap;
}
body.dashboards .db-showing strong { color: var(--ink); font-weight: 600; }
@media (max-width: 900px) {
	body.dashboards .db-showing { margin-left: 0; white-space: normal; flex-basis: 100%; }
}

/* ---- the grid of cards ---------------------------------------------------------------- */
body.dashboards .db-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
	gap: 16px;
	margin-bottom: 24px;
}
@media (max-width: 900px) {
	body.dashboards .db-grid { grid-template-columns: 1fr; }
}

body.dashboards .db-card {
	display: flex;
	flex-direction: column;
	min-width: 0;
	padding: 16px 18px 14px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 12px;
	box-shadow: var(--sh-1);
}
body.dashboards .db-card:target { border-color: var(--accent-fill); }
body.dashboards .db-card-head {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	margin-bottom: 12px;
}
body.dashboards .db-card-main { min-width: 0; flex: 1 1 auto; }
body.dashboards .db-card-title {
	margin: 0;
	font-size: var(--fs-lg);
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
body.dashboards .db-card .stat-scope {
	margin: 2px 0 0;
	font-size: var(--fs-sm);
	color: var(--text-muted);
	line-height: 1.45;
}
body.dashboards .db-card-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 0 0 auto;
	font-size: var(--fs-sm);
}
body.dashboards .db-link,
body.dashboards button.db-link {
	background: none;
	border: 0;
	padding: 0;
	font: inherit;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--accent-text);
	cursor: pointer;
	text-decoration: none;
}
body.dashboards .db-link:hover { text-decoration: underline; }
body.dashboards .db-link-danger { color: var(--danger); }
body.dashboards button.db-icon-btn {
	width: 26px;
	height: 26px;
	padding: 0;
	border: 1px solid var(--line);
	border-radius: 6px;
	background: var(--surface);
	color: var(--text-muted);
	font-size: 13px;
	line-height: 1;
	cursor: pointer;
}
body.dashboards button.db-icon-btn:hover { border-color: #C3CCD9; color: var(--ink); }

body.dashboards .db-card-body { min-height: 120px; }

body.dashboards .db-notes {
	margin: 10px 0 0;
	padding: 0;
	list-style: none;
	font-size: var(--fs-xs);
	color: var(--text-soft);
	line-height: 1.5;
}
body.dashboards .db-notes li::before { content: '\2013\00a0'; }

body.dashboards .db-warn {
	padding: 10px 14px;
	border: 1px solid rgba(138, 90, 24, .25);   /* --warning at a quarter */
	border-radius: 8px;
	background: var(--warning-tint);
	color: var(--warning);
	font-size: var(--fs-sm);
	line-height: 1.5;
}
body.dashboards .db-empty {
	padding: 28px 16px;
	text-align: center;
	color: var(--text-soft);
	font-size: var(--fs-sm);
}
body.dashboards .db-empty b { display: block; color: var(--text); font-weight: 600; margin-bottom: 4px; }
body.dashboards .db-empty span { display: block; }

body.dashboards .db-empty-page {
	padding: 56px 24px;
	text-align: center;
	background: var(--surface);
	border: 1px dashed #D6DCE5;
	border-radius: 12px;
}
body.dashboards .db-empty-page .es-title { font-size: var(--fs-lg); font-weight: 600; color: var(--ink); margin-bottom: 6px; }
body.dashboards .db-empty-page .es-hint { max-width: 520px; margin: 0 auto 18px; color: var(--text-muted); font-size: var(--fs-base); line-height: 1.5; }

/* ---- bars ----------------------------------------------------------------------------- */
body.dashboards .db-legend {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 16px;
	margin-bottom: 10px;
}
body.dashboards .db-key {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-size: var(--fs-sm);
	color: var(--text-muted);
}
body.dashboards .db-key i { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }

body.dashboards .db-row {
	display: grid;
	grid-template-columns: minmax(110px, 170px) minmax(0, 1fr) 42px minmax(60px, 96px);
	align-items: center;
	gap: 12px;
	padding: 7px 0;
	border-bottom: 1px solid #F1F3F6;
}
body.dashboards .db-row:last-child { border-bottom: 0; }
body.dashboards .db-row-name {
	font-size: var(--fs-md);
	font-weight: 600;
	color: var(--ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
/* The track is the full width; the bar inside is --w of it; the segments split the bar.
   A 2px gap between segments is the spacer the mark spec asks for. */
body.dashboards .db-row-bar {
	height: 10px;
	border-radius: 999px;
	background: var(--surface-well);
	overflow: hidden;
	display: flex;
	gap: 2px;
	width: var(--w, 0%);
	min-width: 4px;
}
body.dashboards .db-row-bar .db-seg { display: block; height: 100%; }
body.dashboards .db-row-bar .db-seg:first-child { border-radius: 999px 0 0 999px; }
body.dashboards .db-row-bar .db-seg:last-child { border-radius: 0 999px 999px 0; }
body.dashboards .db-row-bar .db-seg:only-child,
body.dashboards .db-row-bar .db-seg.is-solid { border-radius: 999px; }
body.dashboards .db-row-n,
body.dashboards .db-row-v {
	font-variant-numeric: tabular-nums;
	text-align: right;
	color: var(--ink);
}
body.dashboards .db-row-n { font-weight: 700; }
body.dashboards .db-row-v { font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 560px) {
	/* Name and count share the first line; the bar takes the second. Placed explicitly
	   because the DOM order is name, bar, count -- left to auto-placement the count lands
	   under the bar on its own line. */
	body.dashboards .db-row { grid-template-columns: minmax(0, 1fr) 40px; row-gap: 4px; }
	body.dashboards .db-row-name { grid-row: 1; grid-column: 1; }
	body.dashboards .db-row-n    { grid-row: 1; grid-column: 2; }
	body.dashboards .db-row-bar  { grid-row: 2; grid-column: 1 / -1; width: var(--w, 0%); }
	body.dashboards .db-row-v    { display: none; }
}

/* ---- pie ------------------------------------------------------------------------------ */
body.dashboards .db-pie-wrap {
	display: flex;
	align-items: center;
	gap: 18px;
	flex-wrap: wrap;
}
body.dashboards .db-pie { width: 180px; height: 180px; flex: 0 0 auto; }
body.dashboards .db-slice { stroke: var(--surface); stroke-width: 0; }
body.dashboards .db-slice:hover { opacity: .85; }
body.dashboards .db-slice-label {
	fill: var(--ink);
	font-size: 11px;
	font-weight: 700;
	font-family: inherit;
	pointer-events: none;
	paint-order: stroke;
	stroke: var(--surface);
	stroke-width: 3px;
	stroke-linejoin: round;
}
body.dashboards .db-pie-total { fill: var(--ink); font-size: 22px; font-weight: 700; font-family: inherit; }
body.dashboards .db-pie-total-l { fill: var(--text-soft); font-size: 10px; font-family: inherit; letter-spacing: .08em; text-transform: uppercase; }
body.dashboards .db-pie-legend {
	list-style: none;
	margin: 0;
	padding: 0;
	flex: 1 1 200px;
	min-width: 0;
}
body.dashboards .db-pie-legend li {
	display: grid;
	grid-template-columns: 10px minmax(0, 1fr) auto auto;
	align-items: center;
	gap: 8px;
	padding: 4px 0;
	font-size: var(--fs-sm);
	color: var(--text);
	border-bottom: 1px solid #F1F3F6;
}
body.dashboards .db-pie-legend li:last-child { border-bottom: 0; }
body.dashboards .db-pie-legend li i { width: 10px; height: 10px; border-radius: 3px; }
body.dashboards .db-pie-legend li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.dashboards .db-pie-legend li b { color: var(--ink); font-variant-numeric: tabular-nums; }
body.dashboards .db-pie-legend li em { font-style: normal; color: var(--text-soft); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }

/* ---- line: three layers ------------------------------------------------------------
   .db-line-plot is stretched (viewBox 100x100, preserveAspectRatio none) and holds only
   the grid and the path with non-scaling strokes; .db-line-ov is the same box unstretched,
   everything in it positioned in percentages, so dots stay round and the readout keeps its
   glyphs; ticks and x labels are HTML. */
body.dashboards .db-line-wrap { width: 100%; }
body.dashboards .db-line-box {
	position: relative;
	height: 170px;
	margin-right: 34px;      /* the tick gutter */
}
body.dashboards .db-line-plot,
body.dashboards .db-line-ov {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	overflow: visible;
}
body.dashboards .db-gridline { stroke: #EEF1F4; stroke-width: 1; }
body.dashboards .db-path { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
body.dashboards .db-dot { stroke: var(--surface); stroke-width: 2; }
body.dashboards .db-line-ticks span {
	position: absolute;
	right: -32px;
	transform: translateY(-50%);
	font-size: var(--fs-xs);
	color: var(--text-muted);
	font-variant-numeric: tabular-nums;
}
body.dashboards .db-line-x {
	display: flex;
	justify-content: space-between;
	margin: 6px 34px 0 0;
	font-size: var(--fs-xs);
	color: var(--text-muted);
}
body.dashboards .db-hit { cursor: crosshair; }
body.dashboards .db-cross { stroke: #C9D2DE; stroke-width: 1; opacity: 0; }
body.dashboards .db-read { fill: var(--ink); font-size: 11.5px; font-family: inherit; opacity: 0; pointer-events: none; }
body.dashboards .db-hit:hover .db-cross,
body.dashboards .db-hit:focus .db-cross,
body.dashboards .db-hit:hover .db-read,
body.dashboards .db-hit:focus .db-read { opacity: 1; }
body.dashboards .db-hit:focus { outline: none; }
body.dashboards .db-hit:focus-visible .db-cross { stroke: var(--accent-text); stroke-width: 2; }
@media (max-width: 760px) { body.dashboards .db-line-box { height: 140px; } }

/* ---- the table every chart carries -------------------------------------------------- */
body.dashboards .db-table { margin-top: 10px; }
body.dashboards .db-table > summary {
	cursor: pointer;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--accent-text);
	list-style: none;
}
body.dashboards .db-table > summary::-webkit-details-marker { display: none; }
body.dashboards .db-table > summary::before { content: '\25B8 '; }
body.dashboards .db-table[open] > summary::before { content: '\25BE '; }
body.dashboards .db-table .table-responsive { margin-top: 8px; }
body.dashboards .db-tbl th.db-c-num,
body.dashboards .db-tbl td.db-c-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---- the widget form's brand chips -------------------------------------------------- */
body.dashboards .db-chips { display: flex; flex-wrap: wrap; gap: 6px; }
body.dashboards .db-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 30px;
	padding: 0 11px;
	border: 1px solid var(--line);
	border-radius: 15px;
	background: var(--surface);
	font-size: var(--fs-sm);
	font-weight: 500;
	color: var(--text);
	cursor: pointer;
}
body.dashboards .db-chips-l {
	margin: 0 0 6px;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--ink);
}
body.dashboards .db-chip:has(input:checked) { border-color: var(--accent-fill); background: var(--accent-tint); color: var(--accent-text); }
body.dashboards .db-chip input { margin: 0; }

/* ---- notices, help copy, the Cancel foot ----------------------------------------------
   The shapes lineitems.css gives the sibling modules, restated here because that sheet is
   not loaded on this route. */
body.dashboards .db-flash { border-radius: 8px; padding: 10px 14px; font-size: var(--fs-md); margin-bottom: 14px; }
body.dashboards .db-flash-ok  { background: var(--success-tint); color: var(--success); }
body.dashboards .db-flash-err { background: var(--danger-tint);  color: var(--danger); }
body.dashboards .db-help { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--text-soft); line-height: 1.5; }
body.dashboards .db-foot { margin-top: 10px; font-size: var(--fs-sm); color: var(--text-soft); }
body.dashboards .db-foot a { color: var(--accent-text); font-weight: 600; }

/* "won" / "lost" said next to a stage label, so the status colour is never alone. */
body.dashboards .db-state {
	font-style: normal;
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	margin-left: 6px;
	color: var(--text-soft);
}
body.dashboards .db-state.is-won  { color: var(--success); }
body.dashboards .db-state.is-lost { color: var(--danger); }

body.dashboards .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;
}

/* ---- the KPI strip (Sales summary) and the wide card it lives in ---------------------
   Six-or-more tiles across on a wide screen, halving as the width drops; each tile carries
   its own scope caption so a snapshot and a window figure can sit side by side honestly. */
body.dashboards .db-card--wide { grid-column: 1 / -1; }
body.dashboards .db-tiles {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 10px;
}
body.dashboards .db-tile {
	padding: 12px 14px 10px;
	background: var(--surface-sunk);
	border: 1px solid var(--line);
	border-left: 3px solid #C9D2DE;
	border-radius: 10px;
	min-width: 0;
}
body.dashboards .db-tile.is-won  { border-left-color: var(--accent-fill); }
body.dashboards .db-tile.is-lost { border-left-color: #D8776A; }
body.dashboards .db-tile-k {
	font-size: var(--fs-xs);
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--text-soft);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
body.dashboards .db-tile-v {
	margin-top: 4px;
	font-size: 24px;
	font-weight: 700;
	line-height: 1.1;
	color: var(--ink);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
/* A money figure is longer than a count; it steps down rather than truncating. */
body.dashboards .db-tile-v.is-long { font-size: 18px; letter-spacing: -.01em; }
body.dashboards .db-tile-s {
	margin-top: 4px;
	font-size: var(--fs-sm);
	color: var(--text);
	line-height: 1.35;
	overflow-wrap: anywhere;
}
body.dashboards .db-tile-scope {
	margin-top: 6px;
	font-size: var(--fs-xs);
	color: var(--text-faint);
}
body.dashboards .db-legend .db-key b { color: var(--ink); font-variant-numeric: tabular-nums; margin-left: 2px; }

/* =========================================================================================
   48. INBOX -- Email, SMS and Calls on one three-pane shell (2026-09-18)

   The page title band stays; below it three panes fill the viewport and scroll on their own,
   so the document never scrolls. Panes are divided by hairlines, not nested cards. The one
   place colour is spent is the OUTCOME rail: the product's outcome vocabulary (Interested ->
   Meeting booked -> Won / Lost ...) is what makes this an outreach inbox rather than a mail
   client, so the rail reads as a funnel -- progress blue climbs to a win green, waiting is
   amber, closed is slate. Every hue below is >= 4.5:1 as text on white.

   Class prefix `ib-`. Legacy `rd-dash-*` hooks are kept on a few elements only because the
   reply editor's own inline script and the SMS image picker look for them.

   --ib-chrome is what sits above the content at desktop width: top bar 60 + identity row 49 +
   level-2 strip 53 + the 10px gap (measured 2026-09-18 at 1440x900). section.content carries
   a 30px bottom padding, so the panes stop 30px above the viewport edge.
   ========================================================================================= */
:root {
	--ib-progress:      #1F5FBF;
	--ib-progress-tint: #E8F0FC;
	--ib-win:           #186B4E;
	--ib-win-tint:      #E8F3EC;
	--ib-waiting:       #8A5A18;
	--ib-waiting-tint:  #FDF1E3;
	--ib-closed:        #5B6B82;
	--ib-closed-tint:   #EEF1F4;
	--ib-rail-w:        208px;
	--ib-list-w:        336px;
	--ib-head-h:        58px;
	--ib-chrome:        172px;
}

.ib { display: flex; flex-direction: column; min-height: 0; }
.ib-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 12px; min-height: var(--ib-head-h); padding: 4px 0 14px; }
.ib-head h2 { margin: 0; font-size: var(--fs-xl); font-weight: 600; color: var(--ink); line-height: 28px; }
.ib-head p { margin: 0; color: var(--text-muted); font-size: var(--fs-md); }

.ib-panes {
	display: grid;
	grid-template-columns: var(--ib-rail-w) var(--ib-list-w) minmax(520px, 1fr);
	height: calc(100vh - var(--ib-chrome) - var(--ib-head-h) - 30px);
	min-height: 480px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
	overflow: hidden;
}
.ib-rail, .ib-list-pane, .ib-thread-pane { min-height: 0; min-width: 0; display: flex; flex-direction: column; }
.ib-rail { border-right: 1px solid var(--line); background: var(--surface-sunk); overflow-y: auto; }
.ib-list-pane { border-right: 1px solid var(--line); }
.ib-list { flex: 1 1 auto; overflow-y: auto; }
.ib-thread-pane { position: relative; }
.ib-thread { flex: 1 1 auto; overflow-y: auto; padding: 16px 20px 24px; }

/* rail */
.ib-rail-inner { padding: 14px 10px 18px; }
.ib-rail-title { padding: 0 8px 8px; font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); }
.ib-rail-list { list-style: none; margin: 0; padding: 0; }
.ib-rail-list li { margin: 0; padding: 0; }
.ib-rail-system { margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--line); }
.ib-rail-item {
	display: flex; align-items: center; gap: 8px;
	height: 32px; padding: 0 8px; border-radius: var(--r-sm);
	color: var(--text); font-size: var(--fs-md); text-decoration: none;
}
.ib-rail-item:hover { background: var(--surface-mute); color: var(--ink); text-decoration: none; }
.ib-rail-item.is-active { background: var(--surface); color: var(--ink); font-weight: 600; box-shadow: inset 0 0 0 1px var(--line); }
.ib-rail-item:focus-visible { outline: var(--focus-ring); outline-offset: -2px; }
.ib-rail-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; background: var(--text-faint); }
.hue-progress .ib-rail-dot { background: var(--ib-progress); }
.hue-win .ib-rail-dot      { background: var(--ib-win); }
.hue-waiting .ib-rail-dot  { background: var(--ib-waiting); }
.hue-closed .ib-rail-dot   { background: var(--ib-closed); }
.hue-all .ib-rail-dot      { background: var(--ink); }
.ib-rail-label { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ib-rail-count { min-width: 22px; padding: 0 6px; height: 18px; line-height: 18px; text-align: center; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600; background: var(--surface-well); color: var(--text); font-variant-numeric: tabular-nums; }
.ib-rail-item.is-active .ib-rail-count { background: var(--ink); color: #fff; }
.ib-rail-note { margin: 18px 8px 0; padding-top: 12px; border-top: 1px solid var(--line); font-size: var(--fs-sm); color: var(--text-muted); }
.ib-rail-note p { margin: 8px 0 0; line-height: 1.45; }
.ib-rail-note a { color: var(--accent-text); }
.ib-rail-stat b { display: block; font-size: var(--fs-lg); color: var(--ink); font-weight: 600; }

/* list */
.ib-list-tools { padding: 10px 12px; border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 8px; min-height: 52px; }
.ib-list-count { font-size: var(--fs-sm); color: var(--text-muted); }
.ib-search { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; height: 32px; margin: 0; padding: 0 10px; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--surface); color: var(--text-muted); font-weight: 400; }
.ib-search:focus-within { border-color: var(--ink); }
.ib-search input { flex: 1 1 auto; min-width: 0; height: 28px; border: 0; outline: 0; box-shadow: none; padding: 0; margin: 0; background: transparent; font: inherit; font-size: var(--fs-md); color: var(--ink); }
.ib-search input::placeholder { color: var(--text-faint); }
.ib-row {
	display: flex; align-items: flex-start; gap: 10px;
	padding: 12px 12px 12px 14px; border-bottom: 1px solid var(--line);
	cursor: pointer; position: relative; color: var(--text);
}
.ib-row:hover { background: var(--surface-alt); }
.ib-row.is-active { background: var(--surface-sunk); }
.ib-row.is-active::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--surface-ink); }
.ib-row:focus-visible { outline: var(--focus-ring); outline-offset: -2px; }
.ib-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ib-row-top { display: flex; align-items: baseline; gap: 8px; }
.ib-row-name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: var(--fs-base); color: var(--ink); font-weight: 500; }
.ib-row.is-unread .ib-row-name { font-weight: 700; }
.ib-row-time { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--text-soft); white-space: nowrap; }
.ib-row-preview { font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ib-row.is-unread .ib-row-preview { color: var(--text); }
.ib-row.is-unread .ib-row-name::after { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--ib-progress); margin-left: 6px; vertical-align: middle; }
.ib-unread { flex: 0 0 auto; min-width: 18px; height: 18px; line-height: 18px; padding: 0 5px; border-radius: var(--r-pill); background: var(--ib-progress); color: #fff; font-size: var(--fs-xs); font-weight: 600; text-align: center; }
.ib-row-actions { display: none; position: absolute; right: 8px; bottom: 8px; gap: 2px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 2px; }
.ib-row:hover .ib-row-actions, .ib-row:focus-within .ib-row-actions { display: flex; }
.ib-list-foot { padding: 8px 12px; border-top: 1px solid var(--line); text-align: center; }
.ib-list-foot:has(#ib-more[style*="none"]) { display: none; }
.ib-more { font-size: var(--fs-md); color: var(--accent-text); font-weight: 500; }
.ib-page { display: contents; }

/* avatars */
.ib-avatar { flex: 0 0 36px; width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--surface-ink); color: #fff; font-size: var(--fs-sm); font-weight: 600; text-decoration: none; letter-spacing: .02em; }
.ib-avatar:hover { color: #fff; text-decoration: none; }
.ib-avatar.is-company { background: var(--surface-well); color: var(--ink); border-radius: var(--r-md); }
.ib-avatar.is-company:hover { color: var(--ink); }
.ib-avatar.is-staff { background: var(--accent-tint); color: var(--accent-text); }
.ib-avatar.is-staff:hover { color: var(--accent-text); }
.ib-avatar.is-lg { flex-basis: 44px; width: 44px; height: 44px; font-size: var(--fs-base); }

/* contact header */
.ib-contact { flex: 0 0 auto; border-bottom: 1px solid var(--line); background: var(--surface); position: relative; z-index: 1; }
.ib-contact:empty { display: none; }
.ib-contact-inner { display: flex; align-items: center; gap: 12px; padding: 12px 20px; }
.ib-contact-id { flex: 1 1 auto; min-width: 0; }
.ib-contact-name { font-size: var(--fs-lg); font-weight: 600; color: var(--ink); line-height: 22px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ib-contact-link { font-size: var(--fs-sm); color: var(--accent-text); }
.ib-contact-actions { flex: 0 0 auto; }
.ib-contact-actions .main_buttons { display: flex; gap: 4px; margin: 0; }
.ib-contact-actions .main_buttons .btn { width: 34px; height: 34px; padding: 0; margin: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-sm); border: 1px solid transparent; background: transparent; box-shadow: none; line-height: 1; }
.ib-contact-actions .main_buttons .btn:hover { background: var(--surface-mute); border-color: var(--line); }
.ib-contact-actions .main_buttons .btn svg { width: 18px; height: 18px; }
.ib-contact-actions .main_buttons .btn svg[stroke="#F05B3A"], .ib-contact-actions .main_buttons .btn svg path[stroke="#F05B3A"] { stroke: var(--ink); }
.ib-contact-actions .main_buttons .btn svg[fill="#F05B3A"], .ib-contact-actions .main_buttons .btn svg path[fill="#F05B3A"] { fill: var(--ink); }
.ib-back { display: none; width: 32px; height: 32px; flex: 0 0 32px; align-items: center; justify-content: center; border-radius: var(--r-sm); border: 1px solid var(--line); color: var(--ink); text-decoration: none; }
.ib-back::before { content: ''; width: 8px; height: 8px; border-left: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); margin-left: 3px; }

/* generic bits */
.ib-icon-btn { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-sm); color: var(--text-muted); border: 0; background: transparent; cursor: pointer; padding: 0; line-height: 1; }
.ib-icon-btn:hover { background: var(--surface-mute); color: var(--ink); text-decoration: none; }
.ib-icon-btn.is-sm { width: 24px; height: 24px; }
.ib-icon-btn.is-danger:hover { color: var(--danger); background: var(--danger-tint); }
.ib-chip { display: inline-block; padding: 0 7px; height: 18px; line-height: 18px; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; }
.ib-chip.is-single { background: var(--surface-well); color: var(--text); }
.ib-chip.is-campaign { background: var(--ib-waiting-tint); color: var(--ib-waiting); }
.ib-status-wrap { position: relative; display: inline-block; }
.ib-status-menu { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 8px; border-radius: var(--r-pill); border: 1px dashed var(--line-strong); font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); text-decoration: none; white-space: nowrap; }
.ib-status-menu::after { content: ''; width: 0; height: 0; border-left: 3px solid transparent; border-right: 3px solid transparent; border-top: 4px solid currentColor; }
.ib-status-menu:hover { color: var(--ink); border-color: var(--ink); text-decoration: none; }
.ib-status-menu.is-set { border-style: solid; border-color: transparent; background: var(--ib-progress-tint); color: var(--ib-progress); }
.ib-status-dropdown { min-width: 180px; padding: 6px; margin-top: 4px; border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--sh-2); background: var(--surface); }
.ib-status-dropdown li a { display: block; padding: 7px 10px; border-radius: var(--r-sm); font-size: var(--fs-md); color: var(--text); white-space: nowrap; }
.ib-status-dropdown li a:hover { background: var(--surface-mute); color: var(--ink); text-decoration: none; }
.ib-link-quiet { font-size: var(--fs-sm); color: var(--text-muted); }
.ib-primary { display: inline-flex; align-items: center; height: 32px; padding: 0 14px; border-radius: var(--r-md); background: var(--accent-fill); color: var(--accent-on-fill); font-weight: 600; font-size: var(--fs-md); text-decoration: none; white-space: nowrap; }
.ib-primary:hover { background: var(--accent-hot); color: var(--accent-on-fill); text-decoration: none; }
.ib-muted { color: var(--text-muted); }
.ib-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 180px; padding: 24px; text-align: center; color: var(--text-muted); }
.ib-empty .es-title { font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.ib-empty .es-hint { font-size: var(--fs-md); }
.ib-empty.is-error .es-title { color: var(--danger); }
.ib-retry { margin-top: 8px; color: var(--accent-text); font-weight: 600; }
.ib .is-loading { position: relative; min-height: 48px; }
.ib .is-loading::after { content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, rgba(16,26,43,.05), transparent); animation: ib-shimmer 1.1s infinite; pointer-events: none; }
@keyframes ib-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
.ib-toast { position: sticky; top: 0; z-index: 2; padding: 8px 12px; margin-bottom: 10px; border-radius: var(--r-sm); font-size: var(--fs-md); }
.ib-toast.is-error { background: var(--danger-tint); color: var(--danger); }
.ib-pane-loading { padding: 16px; color: var(--text-muted); font-size: var(--fs-sm); }

/* SMS thread */
.ib-bubbles { display: flex; flex-direction: column; gap: 14px; max-width: 760px; }
.ib-msg { display: flex; gap: 10px; align-items: flex-start; }
.ib-msg.is-out { flex-direction: row-reverse; }
.ib-msg-body { max-width: min(78%, 560px); display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ib-msg.is-out .ib-msg-body { align-items: flex-end; }
.ib-msg-meta { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--text-muted); }
.ib-msg-who { font-weight: 600; color: var(--text); }
.ib-msg-route { color: var(--text-muted); }
.ib-bubble { padding: 9px 13px; border-radius: 14px; font-size: var(--fs-base); line-height: 1.5; color: var(--ink); background: var(--surface-well); word-wrap: break-word; overflow-wrap: anywhere; }
.ib-msg.is-in .ib-bubble { border-top-left-radius: 4px; }
.ib-msg.is-out .ib-bubble { border-top-right-radius: 4px; background: var(--surface-ink); color: #fff; }
.ib-msg.is-out .ib-bubble a { color: #fff; }
.ib-msg-foot { display: flex; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--text-soft); }
.ib-msg-tools { display: inline-flex; align-items: center; gap: 4px; }
.ib-msg .ib-icon-btn { opacity: 0; }
.ib-msg:hover .ib-icon-btn, .ib-msg:focus-within .ib-icon-btn { opacity: 1; }
.ib-attachment { display: inline-block; margin-top: 6px; font-size: var(--fs-sm); color: var(--accent-text); }
.ib-msg.is-out .ib-attachment { color: #fff; text-decoration: underline; }

/* composer */
.ib-composer { flex: 0 0 auto; border-top: 1px solid var(--line); background: var(--surface); padding: 10px 16px 12px; margin: 0; }
.ib-composer .imageplaceholder:empty { display: none; }
.ib-composer .imageplaceholder { padding: 0 0 8px; }
.ib-composer .rd-dash-conversation-answer { display: flex; align-items: flex-end; gap: 8px; margin: 0; border: 1px solid var(--line-strong); border-radius: 12px; padding: 6px 6px 6px 12px; background: var(--surface); }
.ib-composer .rd-dash-conversation-answer:focus-within { border-color: var(--ink); }
.ib-textarea { flex: 1 1 auto; min-width: 0; border: 0; outline: 0; box-shadow: none; resize: none; font: inherit; font-size: var(--fs-base); line-height: 20px; padding: 6px 0; margin: 0; height: 40px; max-height: 160px; color: var(--ink); background: transparent; }
.ib-textarea:focus, .ib-textarea:focus-visible { outline: 0 !important; box-shadow: none !important; border: 0 !important; }
/* Record pages carry their own textarea rules (min-height, resize grip); the composer's box is
   the control, the textarea inside it is not resizable and autosizes from 40px. */
.ib .ib-textarea { resize: none !important; min-height: 0 !important; box-shadow: none !important; border: 0 !important; }
.ib-composer-actions { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.ib-send { display: inline-flex; align-items: center; height: 32px; padding: 0 14px; margin-left: 4px; border: 0; border-radius: var(--r-md); background: var(--accent-fill); color: var(--accent-on-fill); font-weight: 600; font-size: var(--fs-md); cursor: pointer; }
.ib-send:hover { background: var(--accent-hot); }
.ib-send[disabled], .ib-send.is-busy { opacity: .6; cursor: default; }

/* email cards */
.ib-card { border: 1px solid var(--line); border-radius: var(--r-md); margin-bottom: 10px; background: var(--surface); }
.ib-card.is-unread { border-left: 3px solid var(--ib-progress); }
.ib-card-head { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; }
.ib-card-summary { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; color: var(--text); text-decoration: none; }
.ib-card-summary:hover { text-decoration: none; color: var(--ink); }
.ib-card-route { font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ib-card-route b { color: var(--ink); font-weight: 600; }
.ib-addr { color: var(--text-faint); }
.ib-card-subject { font-size: var(--fs-base); color: var(--ink); font-weight: 500; overflow-wrap: anywhere; }
.ib-card.is-unread .ib-card-subject { font-weight: 700; }
.ib-count { display: inline-block; min-width: 18px; padding: 0 5px; height: 18px; line-height: 18px; border-radius: var(--r-pill); background: var(--surface-well); font-size: var(--fs-xs); font-weight: 600; text-align: center; vertical-align: middle; }
.ib-card-side { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.ib-card-side-top, .ib-card-side-bottom { display: flex; align-items: center; gap: 6px; }
.ib-card-time { font-size: var(--fs-xs); color: var(--text-soft); white-space: nowrap; }
.ib-opens { font-size: var(--fs-xs); color: var(--ib-win); white-space: nowrap; }
.ib-reply-btn { display: inline-flex; align-items: center; height: 24px; padding: 0 10px; border-radius: var(--r-pill); border: 1px solid var(--line-strong); font-size: var(--fs-xs); font-weight: 600; color: var(--ink); text-decoration: none; white-space: nowrap; }
.ib-reply-btn:hover { background: var(--ink); color: #fff; border-color: var(--ink); text-decoration: none; }
.ib-card-body { border-top: 1px solid var(--line); padding: 4px 14px 14px; }
.ib-mail { padding: 12px 0; }
.ib-mail.is-reply { border-top: 1px dashed var(--line); }
.ib-mail.is-unread .ib-mail-subject { font-weight: 700; }
.ib-mail-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; font-size: var(--fs-sm); color: var(--text-muted); }
.ib-mail-head a, .ib-mail-who { color: var(--ink); font-weight: 600; }
.ib-mail-to { color: var(--text-muted); }
.ib-mail-time { margin-left: auto; color: var(--text-soft); font-size: var(--fs-xs); }
.ib-mail-subject { margin: 6px 0 8px; font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.ib-mail-body { max-width: 720px; font-size: var(--fs-base); line-height: 1.55; color: var(--text); overflow-wrap: anywhere; }
.ib-mail-body img { max-width: 100%; height: auto; }
.ib-attachments { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.ib-attachments .ib-attachment { margin: 0; padding: 3px 9px; border: 1px solid var(--line); border-radius: var(--r-pill); font-size: var(--fs-xs); color: var(--ink); background: var(--surface-alt); }
.ib-reply-slot:empty { display: none; }
.ib-reply-slot { margin-top: 10px; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-alt); }
.ib-reply-slot .adminform_savebutton input[type="submit"] { border-radius: var(--r-md); }
/* The reply editor is the legacy two-column adminform (label column 210px, field column the rest).
   Inside a 500px slot that leaves 214px for the Subject box. One column here: empty label cells
   collapse, fields run full width, the paperclip loses its inline float. */
.ib-reply-slot .adminform_form .form-group { display: block !important; margin: 0 0 10px; }
.ib-reply-slot .adminform_form .form-group:has(> div > .error-messages:empty):not(:has(input, textarea, select, a)) { display: none !important; }
.ib-reply-slot .adminform_form .form-group > div { width: 100% !important; max-width: none !important; float: none !important; padding: 0 !important; }
.ib-reply-slot .adminform_form .form-group > div:first-child:empty,
.ib-reply-slot .adminform_form .form-group label:empty { display: none; }
.ib-reply-slot .adminform_form .form-control { width: 100% !important; max-width: none !important; }
.ib-reply-slot .adminform_form .display-t.w-100 { display: flex; justify-content: flex-end; gap: 10px; margin-bottom: 4px; }
.ib-reply-slot .adminform_form .display-t.w-100 > a { float: none !important; margin: 0 !important; font-size: var(--fs-sm); }
.ib-reply-slot .adminform_form textarea.form-control, .ib-reply-slot .adminform_form textarea { min-height: 140px; }
.ib-reply-slot .adminform_savebutton { display: flex; align-items: center; gap: 12px; padding: 4px 0 0; margin: 0; }
.ib-reply-slot .upload-attachments-form { float: none !important; position: static !important; margin: 0 !important; top: auto !important; display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: var(--fs-sm); }
.ib-reply-slot .upload-attachments-form:hover { color: var(--ink); }
.ib-reply-slot .adminform_form .form-group > div > div:not([class]) { font-size: var(--fs-sm); color: var(--text-muted); margin: 8px 0 4px; }
.ib-card-foot { display: flex; align-items: center; gap: 12px; padding-top: 10px; }

/* status-filter view: the list pane is removed from the grid (display:none takes it out of
   the flow), so the template must have TWO tracks -- a 0px middle track would swallow the
   thread pane, which then wrapped one word per line. */
.ib.is-status-view .ib-panes { grid-template-columns: var(--ib-rail-w) minmax(520px, 1fr); }
.ib.is-status-view .ib-list-pane { display: none; }

/* calls */
.ib-calls-bar { display: flex; align-items: center; gap: 14px; margin-left: auto; }
.ib-seg { display: inline-flex; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--surface); padding: 2px; }
.ib-seg-item { display: inline-flex; align-items: center; height: 28px; padding: 0 12px; border-radius: 6px; font-size: var(--fs-md); color: var(--text); text-decoration: none; white-space: nowrap; }
.ib-seg-item:hover { background: var(--surface-mute); color: var(--ink); text-decoration: none; }
.ib-seg-item.is-active { background: var(--ink); color: #fff; font-weight: 600; }
.ib-seg-item.is-active:hover { background: var(--ink); color: #fff; }
.ib-toggle { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-md); color: var(--text); text-decoration: none; white-space: nowrap; }
.ib-toggle:hover { color: var(--ink); text-decoration: none; }
.ib-toggle-knob { width: 32px; height: 18px; border-radius: var(--r-pill); background: var(--line-strong); position: relative; transition: background .15s; }
.ib-toggle-knob::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; transition: transform .15s; }
.ib-toggle.is-on .ib-toggle-knob { background: var(--accent-fill); }
.ib-toggle.is-on .ib-toggle-knob::after { transform: translateX(14px); }
.ib-dir { display: inline-block; width: 10px; height: 10px; margin-right: 6px; vertical-align: -1px; border-radius: 2px; background: var(--ib-progress); }
.ib-call-row.is-incoming .ib-dir { background: var(--ib-win); }
.ib-call-row.is-voicemail .ib-dir { background: var(--ib-waiting); }
.ib-rec { display: inline-block; width: 8px; height: 8px; margin-left: 6px; border-radius: 50%; background: var(--danger); vertical-align: 0; }
.ib-call { max-width: 760px; }
.ib-call .ib-contact-inner { padding: 0 0 14px; border-bottom: 1px solid var(--line); }
.ib-call-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 20px; margin: 16px 0 0; }
.ib-call-facts div { display: flex; flex-direction: column; gap: 2px; }
.ib-call-facts dt { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 500; }
.ib-call-facts dd { margin: 0; font-size: var(--fs-base); color: var(--ink); font-weight: 500; overflow-wrap: anywhere; }
.ib-call-facts dd.is-incoming { color: var(--ib-win); }
.ib-call-facts dd.is-voicemail { color: var(--ib-waiting); }
.ib-call-section-title { margin: 20px 0 8px; font-size: var(--fs-md); font-weight: 600; color: var(--ink); }
.ib-call-recording audio { width: 100%; max-width: 520px; display: block; }
.ib-call-transcript-body { font-size: var(--fs-base); line-height: 1.6; color: var(--text); white-space: pre-wrap; }

/* level-2 strip: the settings cluster on the right */
.tab-nav .secondary-nav > li.tabnav-spacer { flex: 1 1 auto; min-width: 12px; }
.tab-nav .secondary-nav > li.tabnav-settings > a { color: var(--text-muted); }
.tab-nav .secondary-nav > li.tabnav-settings.active > a { color: var(--accent-on-fill); }

/* responsive */
@media (max-width: 1279px) {
	:root { --ib-rail-w: 56px; }
	.ib-rail-title, .ib-rail-label, .ib-rail-note { display: none; }
	.ib-rail-item { justify-content: center; padding: 0; gap: 4px; }
	.ib-rail-count { min-width: 0; }
	.ib-panes { grid-template-columns: var(--ib-rail-w) 272px minmax(0, 1fr); }
	.ib.is-status-view .ib-panes { grid-template-columns: var(--ib-rail-w) minmax(0, 1fr); }
	/* A 1024px screen with the app sidebar open leaves ~400px for the thread: the card's
	   right-hand cluster goes under the summary instead of beside it. */
	.ib-card-head { flex-wrap: wrap; }
	.ib-card-summary { flex-basis: calc(100% - 48px); }
	.ib-card-side { flex: 1 0 100%; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; padding-left: 48px; }
	.ib-thread { padding: 12px 14px 20px; }
}
@media (max-width: 959px) {
	.ib-head { min-height: 0; }
	.ib-calls-bar { margin-left: 0; width: 100%; flex-wrap: wrap; }
	.ib-panes { display: block; height: auto; min-height: 0; border: 0; border-radius: 0; background: transparent; overflow: visible; }
	.ib-rail { flex-direction: row; overflow-x: auto; border-right: 0; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); margin-bottom: 12px; }
	.ib-rail-inner { display: flex; gap: 4px; padding: 8px; }
	.ib-rail-list { display: flex; gap: 4px; }
	.ib-rail-item { height: 30px; padding: 0 10px; gap: 6px; }
	.ib-rail-label { display: inline; }
	.ib-rail-system { margin: 0; padding: 0; border: 0; }
	.ib-list-pane, .ib-thread-pane { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
	.ib-list-pane .ib-list { max-height: calc(100vh - 300px); }
	.ib-thread-pane { display: none; }
	.ib.has-thread .ib-list-pane { display: none; }
	.ib.has-thread .ib-thread-pane { display: flex; }
	.ib-thread { max-height: calc(100vh - 300px); }
	.ib-back { display: inline-flex; }
	.ib-contact-inner { padding: 10px 12px; }
	.ib-contact-actions .main_buttons .btn { width: 30px; height: 30px; }
	.ib-msg-body { max-width: 88%; }
	.ib-card-head { flex-wrap: wrap; }
	.ib-card-side { align-items: flex-start; width: 100%; }
	.ib-call-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tab-nav .secondary-nav > li.tabnav-spacer { display: none; }
}
@media (prefers-reduced-motion: reduce) {
	.ib .is-loading::after { animation: none; }
	.ib-toggle-knob, .ib-toggle-knob::after { transition: none; }
}

/* ---- 48b. Reminder message -- one card, tag chips, live preview, character budget ---- */
body.reminder_message_page .embed_grid .socialsharewrap { max-width: 760px; }
.rm-tags { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 10px 0 0; font-size: var(--fs-sm); color: var(--text-muted); }
.rm-tag { height: 24px; padding: 0 10px; border-radius: var(--r-pill); border: 1px solid var(--line-strong); background: var(--surface); font-size: var(--fs-xs); font-weight: 600; color: var(--ink); cursor: pointer; }
.rm-tag:hover { background: var(--surface-mute); }
.rm-preview { margin-top: 16px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-alt); }
.rm-preview-title { font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); margin-bottom: 6px; }
.rm-preview-body { font-size: var(--fs-base); color: var(--ink); line-height: 1.5; overflow-wrap: anywhere; }
.rm-count { margin-top: 8px; font-size: var(--fs-xs); color: var(--text-muted); }
.rm-count.is-over { color: var(--danger); font-weight: 600; }

/* ---- 48c. Templates -- the five sub-pages as one segmented control, categories as a rail ---- */
body.templates_section .additional-buttons-section > .buttons { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 2px; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--surface); }
body.templates_section .additional-buttons-section > .buttons .ab-button { display: inline-flex; align-items: center; gap: 6px; border: 0; border-radius: 6px; height: 30px; margin: 0; padding: 0 12px; box-shadow: none; background: transparent; color: var(--text); font-size: var(--fs-md); font-weight: 500; }
body.templates_section .additional-buttons-section > .buttons .ab-button:hover { background: var(--surface-mute); color: var(--ink); }
body.templates_section .additional-buttons-section > .buttons .ab-button.active { background: var(--ink); color: #fff; }
body.templates_section .additional-buttons-section > .buttons .ab-button.active svg { color: #fff; fill: currentColor; }
body.templates_section .additional-buttons-section > .buttons .ab-button svg { width: 15px; height: 15px; }
body.templates_section .categoriest-list-section { border: 0; box-shadow: none; background: transparent; padding: 0 16px 0 0; }
body.templates_section .categoriest-list-section ul.category { list-style: none; margin: 0; padding: 0; }
body.templates_section .categoriest-list-section ul.category li { border-radius: var(--r-sm); margin: 0 0 2px; }
body.templates_section .categoriest-list-section ul.category li.active { background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
body.templates_section .categoriest-list-section ul.category li .flex { align-items: center; }
body.templates_section .categoriest-list-section ul.category li .edit { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; height: 34px; padding: 0 10px; color: var(--text); font-size: var(--fs-md); }
body.templates_section .categoriest-list-section ul.category li .edit:hover { color: var(--ink); text-decoration: none; }
body.templates_section .categoriest-list-section ul.category li.active .edit { color: var(--ink); font-weight: 600; }
body.templates_section .categoriest-list-section ul.category li .edit span { margin-left: auto; min-width: 22px; height: 18px; line-height: 18px; padding: 0 6px; border-radius: var(--r-pill); background: var(--surface-well); color: var(--text); font-size: var(--fs-xs); font-weight: 600; text-align: center; }
body.templates_section .categoriest-list-section ul.category li.active .edit span { background: var(--ink); color: #fff; }
body.templates_section .categoriest-list-section .category-item-featured { padding: 0 4px 0 8px; color: var(--text-faint); }
body.templates_section .categoriest-list-section .category-item-featured.is-featured { color: var(--ib-waiting); }

/* ---- 48d. Embedded thread on the contact / company record pages ----
   Same partials, same script; only #ib-thread (+ the composer) exists. The thread keeps a
   bounded height so a long chat scrolls inside its box and the newest message sits by the
   composer, as it does in the Inbox. */
.ib.is-embedded { display: block; }
.ib.is-embedded .ib-thread-pane { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); overflow: hidden; }
.ib.is-embedded .ib-thread { max-height: calc(100vh - 360px); min-height: 220px; }
.ib.is-embedded .ib-bubbles, .ib.is-embedded .ib-mail-body { max-width: none; }
.ib-embedded-tools { display: flex; justify-content: flex-end; margin: 0 0 10px; }

/* ---- 48e. Templates type switcher: chips on the Templates pages, the select elsewhere ---- */
.tf-chips { display: none; }
body.templates_section .tf-chips { display: inline-flex; gap: 4px; padding: 2px; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--surface); margin-right: 10px; }
body.templates_section .templates-dropdowns { display: none !important; }
.tf-chip { display: inline-flex; align-items: center; height: 28px; padding: 0 12px; border-radius: 6px; font-size: var(--fs-md); color: var(--text); text-decoration: none; }
.tf-chip:hover { background: var(--surface-mute); color: var(--ink); text-decoration: none; }
.tf-chip.is-active { background: var(--ink); color: #fff; font-weight: 600; }
.tf-chip.is-active:hover { background: var(--ink); color: #fff; }

/* ---- 48f. Channel switcher under the thread header, and the per-record filter chip on Calls ---- */
.ib-channels { display: flex; gap: 4px; padding: 0 20px 10px; }
.ib-channel { display: inline-flex; align-items: center; height: 24px; padding: 0 10px; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); text-decoration: none; border: 1px solid transparent; }
.ib-channel:hover { color: var(--ink); background: var(--surface-mute); text-decoration: none; }
.ib-channel.is-active { color: var(--ink); background: var(--surface-well); }
.ib-filter-chip { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; height: 24px; padding: 0 6px 0 10px; border-radius: var(--r-pill); background: var(--ib-progress-tint); color: var(--ib-progress); font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; }
.ib-filter-clear { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; color: inherit; text-decoration: none; font-size: 14px; line-height: 1; }
.ib-filter-clear:hover { background: rgba(31,95,191,.12); color: inherit; text-decoration: none; }

/* Parent-company search, shown when a workspace has too many companies for one dropdown. */
.hier-find { display: flex; gap: 8px; margin: 0 0 10px; flex-wrap: wrap; }
.hier-find input[type="search"] {
	flex: 1 1 260px;
	min-height: 36px;
	padding: 6px 11px;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-md);
	font-size: var(--fs-md);
}
.pr-count { margin-left: 6px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--accent-text); }

/* Date range on the Contacts / Companies / Deals directories (GS\Common\DateRange).
   One bordered group so "which date · when · from · to" reads as a single question rather than
   four loose controls; it wraps to its own line on narrow screens like the property filters. */
.ct-search .dr-group {
	display: inline-flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 6px;
	padding: 3px 6px;
	min-height: 42px;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
}
.ct-search .dr-group.is-on { border-color: #17803D; box-shadow: 0 0 0 3px rgba(63, 191, 60, .10); }
.ct-search .dr-group select,
.ct-search .dr-group .nice-select { min-height: 34px; border-color: transparent; background: transparent; max-width: 160px; }
.ct-search .dr-label { font-size: 13px; font-weight: 600; color: #35435A; padding: 0 6px; }
.ct-search .dr-date { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 12px; font-weight: 500; color: #7C8AA0; }
.ct-search .dr-date input[type="date"] {
	min-height: 34px;
	padding: 4px 8px;
	border: 1px solid #E4E7EC;
	border-radius: 6px;
	background: #FAFBFC;
	font-size: 13px;
	color: #101A2B;
	font-variant-numeric: tabular-nums;
}
.ct-search .dr-date input[type="date"]:focus { outline: none; border-color: #17803D; background: #FFFFFF; }
.dr-notice { margin: -6px 0 14px; font-size: var(--fs-sm); color: #5A6A80; }
.dr-notice strong { color: #101A2B; font-weight: 600; }
@media (max-width: 767px) {
	.ct-search .dr-group { width: 100%; }
	.ct-search .dr-date { flex: 1 1 140px; }
	.ct-search .dr-date input[type="date"] { width: 100%; }
}
.ct-panel .hs-all { margin-top: 14px; border-top: 1px solid var(--line); }


/* ==========================================================================================
   51. SUPPORT WORKSPACE
   The ticket queue, the client list, and the create/edit forms. Same rhythm as Contacts,
   Companies and Deals: the page title stands alone, the next row is one toolbar, the list
   is the shared table card, and a form is a white card with the label above the control.
   ========================================================================================== */

body.support-workspace .block > .body-wrapper > .block-content-outer {
	padding-top: 0;
}

body.support-workspace .support-toolbar {
	display: flex;
	align-items: center;
	flex-wrap: nowrap;
	gap: 8px;
	margin: 0 0 16px;
	min-height: 0;
	padding-bottom: 0;
}

/* `.buttons-section` is width:100% app-wide, which shoved All Tickets / Create Ticket /
   Clients / Export onto a row of their own and left the filters on a second row with a
   blank stretch out to the view icons. The filters lead; the actions sit at the far edge. */
body.support-workspace .support-toolbar .buttons-section,
body.support-workspace .support-toolbar > .buttons {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	width: auto;
	order: 5;
	margin-left: auto;
}
body.support-workspace .support-toolbar .support-dropdowns { order: 1; }
body.support-workspace .support-toolbar .vr { order: 2; flex: none; }
body.support-workspace .support-toolbar .filter-wrapper { order: 3; }
body.support-workspace .support-toolbar .flex-1 { display: none; }
body.support-workspace .support-toolbar .right-wrapper {
	order: 4;
	margin-left: 4px;
	flex: none;
}
body.support-workspace .support-toolbar .nice-select,
body.support-workspace .support-toolbar .icon-button {
	height: 36px;
	min-height: 36px;
	box-sizing: border-box;
}

body.support-workspace .support-toolbar .adminbuttons {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
}

body.support-workspace .support-toolbar .ab-button,
body.support-workspace .support-toolbar .adminbuttons a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 36px;
	margin: 0;
	padding: 0 14px;
	border-radius: 8px;
	white-space: nowrap;
}

/* Create Ticket and New Article are the one primary action, in the same place as Add Contact / New deal. */
body.knowledge-base .support-toolbar a[href*="d=add&"],
body.support-workspace .support-toolbar a[href*="addticket"] {
	background: var(--accent-fill);
	border-color: var(--accent-fill);
	color: var(--text-invert);
	font-weight: 600;
}
body.knowledge-base .support-toolbar a[href*="d=add&"]:hover,
body.support-workspace .support-toolbar a[href*="addticket"]:hover {
	background: var(--accent-hot);
	border-color: var(--accent-hot);
	color: var(--text-invert);
}
body.support-workspace .support-toolbar a.ct-add {
	margin-left: 0;
}

body.support-workspace .support-toolbar .filter-wrapper,
body.support-workspace .support-toolbar .buttons-section + * {
	display: flex;
	align-items: center;
	gap: 8px;
}

/* The queue's empty row uses the same quiet centre as the other directories. */
body.support_clients table.admintable td[colspan]:not([colspan="1"]),
body.support_list table.admintable td[colspan]:not([colspan="1"]) {
	padding: 44px 16px;
}

/* ---- create / edit ticket and add client, as a page ----------------------------------- */

body.support-form-page .block > .body-wrapper > .block-content-outer {
	padding-top: 0;
}
body.support-form-page .cf-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 300px;
	gap: 22px;
	align-items: start;
}
body.support-form-page .support-form-main {
	min-width: 0;
}
body.support-form-page .adminform_form .adminform_table,
body.support-form-page .adminform_form .adminform_savebutton {
	max-width: none;
}
body.support-form-page .adminform_form .adminform_table {
	border-radius: 12px;
	padding: 14px 20px 4px;
	column-gap: 16px;
	row-gap: 0;
}
/* common_adminform.css sets `.form-group { display:table; margin-bottom:15px }`.
   Label sits 6px above its control; the next field starts 14px later. */
body.support-form-page .adminform_form .form-group {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 6px;
	margin: 0 0 14px;
	padding: 0;
	border-bottom: 0;
	width: auto;
	height: auto;
	float: none;
}
body.support-form-page .adminform_form .form-group > div:first-child {
	padding-top: 0;
	min-height: 0;
}
/* Client and Company are inserted templates that already print their own label.
   The form row's caption cell is empty and was a blank band above the real label. */
body.support-form-page .adminform_form .form-group:is(:has(.assignclient), :has(.organizations-select)) > div:first-child:has(> label:empty) {
	display: none;
}
/* Department, assignee, priority, status, due date and channel are short.
   They share a row. Client, company, tags, subject, question and the file stay full width. */
body.support-form-page .adminform_table > .form-group:has(select[name$="department"]),
body.support-form-page .adminform_table > .form-group:has(select[name$="user"]),
body.support-form-page .adminform_table > .form-group:has(select[name$="priority"]),
body.support-form-page .adminform_table > .form-group:has(select[name$="status"]),
body.support-form-page .adminform_table > .form-group:has(input[name$="duedate"]),
body.support-form-page .adminform_table > .form-group:has(select[name$="channel"]) {
	grid-column: span 3;
}
body.support-form-page .adminform_form .form-group label {
	font-weight: 500;
}
body.support-form-page .adminform_form input[type="text"],
body.support-form-page .adminform_form select,
body.support-form-page .adminform_form textarea,
body.support-form-page .nice-select,
body.support-form-page .assignclient select,
body.support-form-page .organizations-select select {
	min-height: 42px;
}
body.support-form-page .assignclient,
body.support-form-page .organizations-select {
	margin: 0;
}
body.support-form-page .assignclient > div:first-child label,
body.support-form-page .organizations-select label {
	display: block;
	margin: 0 0 6px;
	font-size: 13px;
	font-weight: 500;
	color: #35435A;
}
body.support-form-page .assignclient .flex,
body.support-form-page .organizations-select .flex {
	display: flex;
	align-items: center;
	gap: 8px;
}
body.support-form-page .assignclient .flex > select,
body.support-form-page .assignclient .flex .nice-select,
body.support-form-page .organizations-select .flex-1,
body.support-form-page .organizations-select .nice-select {
	flex: 1 1 auto;
	min-width: 0;
}
body.support-form-page .assignclient .flex > a,
body.support-form-page .organizations-select .flex > a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	margin: 0;
	float: none;
	border: 1px solid #DDE2E9;
	border-radius: 8px;
	background: #FFFFFF;
	color: #35435A;
	flex: none;
}
body.support-form-page .assignclient .flex > a:hover,
body.support-form-page .organizations-select .flex > a:hover {
	background: #F1F3F6;
	color: #101A2B;
}
body.support-form-page .cf-side {
	position: sticky;
	top: 16px;
}
body.support-form-page .cf-side-card {
	background: #FFFFFF;
	border: 1px solid #E4E7EC;
	border-radius: 12px;
	padding: 16px 18px;
}
body.support-form-page .cf-side-card h4 {
	margin: 0 0 8px;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #7C899B;
}
body.support-form-page .cf-side-card p {
	margin: 0 0 9px;
	font-size: 13px;
	line-height: 1.55;
	color: #5A6A80;
}
body.support-form-page .cf-side-card p:last-child { margin-bottom: 0; }
body.support-form-page .adminform_savebutton {
	margin-top: 8px;
	padding-top: 16px;
	border-top: 1px solid #EDEFF3;
}

@media (max-width: 1100px) {
	body.support-form-page .cf-layout { grid-template-columns: minmax(0, 1fr); }
	body.support-form-page .cf-side { position: static; }
	body.support-form-page .adminform_table > .form-group:has(select[name$="department"]),
	body.support-form-page .adminform_table > .form-group:has(select[name$="user"]),
	body.support-form-page .adminform_table > .form-group:has(select[name$="priority"]),
	body.support-form-page .adminform_table > .form-group:has(select[name$="status"]),
	body.support-form-page .adminform_table > .form-group:has(input[name$="duedate"]),
	body.support-form-page .adminform_table > .form-group:has(select[name$="channel"]) {
		grid-column: span 6;
	}
	body.support-workspace .support-toolbar { flex-wrap: wrap; }
	body.support-workspace .support-toolbar .buttons-section,
	body.support-workspace .support-toolbar > .buttons { margin-left: 0; }
}

/* =========================================================================================
   SIGN-IN

   Logged-out pages get body:has(.auth-stage). The old login was a 400px grey card with a
   "Not Registered?" button under the form. This is one centered card on the sidebar navy,
   with the brand mark, the account chooser, and the credential form. The register control
   is gone from this screen; the register route itself is unchanged.

   The chooser JS in themes/default/manageaccount.js still keys off
   .view-choose-account-block, .view-login-block and .user-choose-account-another.
   .view-login-block stays display:none in account.css until that script (or a wrong
   password) shows it — do not set display on those classes here.
   ========================================================================================= */
body:has(.auth-stage) {
	background: #101A2B;
	min-height: 100vh;
	overflow: auto;
}
body:has(.auth-stage) .wrapper {
	min-height: 100vh;
}
body:has(.auth-stage) .content,
body:has(.auth-stage) .content:before,
body:has(.auth-stage) section.content {
	background: #101A2B;
	min-height: 100vh;
	height: auto;
	padding-bottom: 0;
}
body:has(.auth-stage) .auth-stage {
	min-height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 40px 20px;
	background:
		radial-gradient(880px 460px at 12% -8%, rgba(240, 91, 58, 0.34), transparent 62%),
		radial-gradient(640px 420px at 100% 108%, rgba(255, 255, 255, 0.07), transparent 58%),
		#101A2B;
}
body:has(.auth-stage) .auth-card {
	width: 100%;
	max-width: 420px;
	padding: 36px 32px 28px;
	background: #FFFFFF;
	border-radius: 20px;
	box-shadow: 0 24px 60px rgba(8, 14, 28, 0.38);
}
body:has(.auth-stage) .auth-brand {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	margin-bottom: 22px;
}
body:has(.auth-stage) .auth-mark {
	width: 72px;
	height: 72px;
	padding: 14px;
	object-fit: contain;
	background: #F3F6FA;
	border-radius: 20px;
	box-shadow: inset 0 0 0 1px #E4E7EC;
}
body:has(.auth-stage) .auth-wordmark {
	font-family: var(--font-ui);
	font-size: 18px;
	font-weight: 600;
	letter-spacing: -0.02em;
	color: var(--ink);
}
body:has(.auth-stage) .auth-copy h1 {
	margin: 0 0 6px;
	font-family: var(--font-ui);
	font-size: 26px;
	font-weight: 600;
	letter-spacing: -0.03em;
	line-height: 1.15;
	color: var(--ink);
}
body:has(.auth-stage) .auth-copy p {
	margin: 0 0 22px;
	font-size: 14px;
	line-height: 1.45;
	color: var(--text);
}
body:has(.auth-stage) .auth-form .form-group {
	margin-bottom: 16px;
}
body:has(.auth-stage) .auth-card label {
	display: block;
	margin-bottom: 6px;
	font-size: 13px;
	font-weight: 600;
	color: var(--ink-2);
}
body:has(.auth-stage) .auth-card .form-control {
	height: 46px;
	padding: 10px 14px;
	font-size: 15px;
	color: var(--ink);
	background: var(--surface-sunk);
	border: 1px solid var(--line);
	border-radius: 12px;
	box-shadow: none;
}
body:has(.auth-stage) .auth-card .form-control:focus {
	background: #FFFFFF;
	border-color: var(--accent-fill);
	box-shadow: 0 0 0 3px var(--accent-tint);
	outline: none;
}
body:has(.auth-stage) .auth-code {
	font-size: 22px;
	letter-spacing: 0.35em;
	text-align: center;
	font-variant-numeric: tabular-nums;
}
body:has(.auth-stage) .auth-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin: 4px 0 18px;
}
body:has(.auth-stage) .auth-remember {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	font-weight: 500;
	color: var(--text);
	cursor: pointer;
}
body:has(.auth-stage) .auth-remember input {
	width: 16px;
	height: 16px;
	margin: 0;
	accent-color: var(--accent-fill);
	cursor: pointer;
}
body:has(.auth-stage) .auth-forgot,
body:has(.auth-stage) .auth-foot a {
	font-size: 13px;
	font-weight: 600;
	color: var(--accent-text);
	text-decoration: none;
}
body:has(.auth-stage) .auth-forgot:hover,
body:has(.auth-stage) .auth-foot a:hover {
	color: var(--accent-hot);
}
body:has(.auth-stage) .auth-submit.btn-accent {
	display: block;
	width: 100%;
	height: 46px;
	margin-top: 4px;
	padding: 0 16px;
	font-size: 15px;
	font-weight: 600;
	letter-spacing: 0.01em;
	color: #FFFFFF !important;
	background: var(--accent-fill) !important;
	border: 0 !important;
	border-radius: 12px;
}
body:has(.auth-stage) .auth-submit.btn-accent:hover,
body:has(.auth-stage) .auth-submit.btn-accent:focus {
	background: var(--accent-hot) !important;
	color: #FFFFFF !important;
}
body:has(.auth-stage) .auth-error {
	margin: 0 0 16px;
	padding: 10px 12px;
	font-size: 13px;
	line-height: 1.4;
	color: var(--danger);
	background: var(--danger-tint);
	border-radius: 10px;
}
body:has(.auth-stage) .auth-chooser {
	display: flex;
	flex-direction: column;
	gap: 8px;
}
body:has(.auth-stage) .auth-chooser .user-choose-account {
	margin: 0;
	border: 1px solid var(--line);
	border-radius: 14px;
	background: var(--surface-sunk);
	overflow: hidden;
}
body:has(.auth-stage) .auth-chooser .user-choose-account a {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px 14px;
	color: var(--ink);
	text-decoration: none;
}
body:has(.auth-stage) .auth-chooser .user-choose-account a:hover {
	background: #FFFFFF;
}
body:has(.auth-stage) .auth-chooser .user-choose-account .col-xs-2,
body:has(.auth-stage) .auth-chooser .user-choose-account .col-xs-10 {
	float: none;
	width: auto;
	padding: 0;
}
body:has(.auth-stage) .auth-chooser .user-choose-account h5 {
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	color: var(--ink);
}
body:has(.auth-stage) .auth-chooser .user-choose-account p {
	margin: 2px 0 0;
	font-size: 12px;
	color: var(--text-muted);
}
body:has(.auth-stage) .auth-chooser .user-choose-account-another {
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	margin: 4px 0 0;
	padding: 12px 14px;
	font-size: 14px;
	font-weight: 600;
	color: var(--ink);
	text-align: left;
	background: transparent;
	border: 1px dashed var(--line);
	border-radius: 14px;
	cursor: pointer;
}
body:has(.auth-stage) .auth-chooser .user-choose-account-another:hover {
	background: var(--surface-alt);
	border-color: var(--text-faint);
}
body:has(.auth-stage) .auth-plus {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	font-size: 20px;
	line-height: 1;
	color: var(--accent-fill);
	background: var(--accent-tint);
	border-radius: 50%;
}
body:has(.auth-stage) .auth-foot {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	margin-top: 18px;
	padding-top: 16px;
	border-top: 1px solid var(--line);
}
@media (max-width: 480px) {
	body:has(.auth-stage) .auth-card { padding: 28px 20px 22px; }
	body:has(.auth-stage) .auth-row { flex-wrap: wrap; }
}

/* MFA set-up and the code step share the sign-in stage. The layout still prints
   the page title in .blocktitlesection; this screen already has it in the card. */
body:has(.auth-stage) .block-header,
body:has(.auth-stage) .blocktitlesection { display: none; }
body:has(.auth-stage) .block,
body:has(.auth-stage) .body-wrapper,
body:has(.auth-stage) .block-content-outer {
	background: transparent;
	border: 0;
	box-shadow: none;
	margin: 0;
	padding: 0;
}
body:has(.auth-stage) .auth-card-mfa { max-width: 440px; }
body:has(.auth-stage) .auth-lead {
	margin: -8px 0 18px;
	font-size: 14px;
	line-height: 1.45;
	color: var(--text);
}
body:has(.auth-stage) .auth-qr {
	display: flex;
	justify-content: center;
	margin: 0 0 18px;
}
body:has(.auth-stage) .auth-qr svg {
	width: 196px;
	height: 196px;
	padding: 10px;
	background: #FFFFFF;
	border-radius: 16px;
	box-shadow: inset 0 0 0 1px var(--line);
}
body:has(.auth-stage) .auth-keyline {
	margin: 0 0 6px;
	font-size: 13px;
	color: var(--text-muted);
}
body:has(.auth-stage) .auth-secret {
	display: block;
	margin: 0 0 18px;
	padding: 10px 12px;
	font-size: 13px;
	line-height: 1.4;
	letter-spacing: 0.03em;
	word-break: break-all;
	user-select: all;
	color: var(--ink);
	background: var(--surface-sunk);
	border-radius: 10px;
}
body:has(.auth-stage) .auth-mfa .auth-foot { justify-content: flex-start; }

/* Recovery codes are shown after sign-in, inside the workspace. They do not use the
   signed-out stage, which painted navy over the sidebar content and left the codes
   as dark chips. */
body:has(.mfa-sheet) .blocktitlesection { display: none; }
.mfa-sheet {
	max-width: 520px;
	margin: 4px 0 32px;
	padding: 28px 28px 24px;
	background: #FFFFFF;
	border: 1px solid var(--line);
	border-radius: 16px;
}
.mfa-sheet h1 {
	margin: 0 0 8px;
	font-size: 22px;
	font-weight: 600;
	letter-spacing: -0.02em;
	line-height: 1.2;
	color: var(--ink);
}
.mfa-lead {
	margin: 0 0 18px;
	font-size: 14px;
	line-height: 1.5;
	color: var(--text);
}
.mfa-codes {
	display: grid;
	grid-template-columns: 1fr;
	gap: 8px;
	margin: 0 0 20px;
	padding: 0;
	list-style: none;
}
.mfa-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
}
.mfa-dismiss-form {
	margin: 0;
	display: inline;
}
.mfa-save-secondary {
	color: var(--ink);
	background: #F4F7FB;
	border: 1px solid var(--line);
	cursor: pointer;
	font-family: inherit;
}
.mfa-save-secondary:hover,
.mfa-save-secondary:focus {
	color: var(--ink);
	background: #E8EDF3;
}
.mfa-download {
	text-decoration: none;
}
.mfa-codes li { margin: 0; }
.mfa-codes code {
	display: block;
	padding: 10px 12px;
	font-size: 14px;
	letter-spacing: 0.04em;
	color: var(--ink);
	background: #F4F7FB;
	border-radius: 8px;
	user-select: all;
}
.mfa-save {
	display: inline-flex;
	align-items: center;
	height: 40px;
	padding: 0 16px;
	font-size: 14px;
	font-weight: 600;
	color: #FFFFFF;
	background: var(--accent-fill);
	border-radius: 10px;
	text-decoration: none;
}
.mfa-save:hover,
.mfa-save:focus {
	color: #FFFFFF;
	background: var(--accent-hot);
}
@media (max-width: 640px) {
	.mfa-codes { grid-template-columns: 1fr; }
	.mfa-sheet { padding: 22px 18px 18px; }
}

/* =========================================================================================
   52. COMPANY-PAGE AUDIT LEFTOVERS (P1.3, 2026-09-27) -- findings #30, #39, #41 of the
   2026-09-01 company surface audit (docs/agent-context/bugs/company-surface-audit.md).
   ========================================================================================= */

/* 52.1 (#39) The DETAILS panel's dropdowns. nice-select floats left and nothing cleared it, so a
   field holding one collapsed to its label's height and the control hung over the next field.
   flow-root contains the float; the control itself stops floating and fills its field. Also on
   the Contact and Deal pages, which render the same .pr-panel. */
.pr-panel .pr-field { display: flow-root; }
.pr-panel .pr-field .nice-select { float: none; width: 100%; max-width: 420px; }

/* 52.2 (#41) `.kindchip` -- the small label on company links ("Full access" / "Company only"), deal
   types and workspace status -- had only an `.is-full` colour rule and rendered as bare text. The
   base look matches .bt-chip in a neutral grey, so `.is-full` still reads as the stronger state. */
.kindchip {
	display: inline-block;
	padding: 2px 9px;
	border: 1px solid #DDE2E9;
	border-radius: 999px;
	background: #F4F6F9;
	color: #35435A;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
}

/* 52.3 (#30) The directory toolbars (Contacts, Companies, Deals). The date-range group is ~680px of
   fixed controls, so once it was added the Search button wrapped onto a row of its own. The group
   may now shrink and wrap inside itself, and the button never shrinks, so it stays on the row it
   submits. */
.ct-search .dr-group { flex: 1 1 360px; min-width: 0; }
.ct-search > button[type="submit"] { flex: 0 0 auto; }


/* ==========================================================================================
   53. THE DIRECTORY FILTER BAR -- Contacts, Companies, Deals (GS\Common\FilterBar, 2026-09-28)

   Sections 15, 27, 44, 52.3 and the date-range block each patched `.ct-search` for one symptom,
   and the result was a single wrapping row of identical 42px boxes: search, pipeline, every
   property filter, four date controls and two buttons, all at the same weight. At 1440px the date
   group split over two lines and the primary action fell onto a row of its own.

   The bar is now one card with two tiers, and it has NEW class names so that none of those
   earlier rules reach it -- it is styled here and only here:
     .fb-head     context (Deals' pipeline), search, the primary action   -- what you are looking at
     .fb-filters  one key/value chip per filter, the date range, Apply    -- how you narrowed it

   Hierarchy by shape: the card is 12px, fields are 8px, filters are pills. A chip keeps its
   property name after a value is chosen ("Brand  Dev"), which the old "Brand: any" select lost the
   moment it was used. Engaged means green tint, the same "this is on" language as section 44.2.

   niceSelect (luna.js:30) replaces every <select> with a `div.nice-select` next to it; each rule
   below sizes BOTH, because the <select> is what renders before the script runs.
   ========================================================================================= */

/* 53.1 The card. No overflow:hidden -- the dropdown lists hang below it. */
.fb {
	margin: 0 0 16px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-lg);
	box-shadow: var(--sh-1);
}
.fb form { margin: 0; }
.fb .nice-select { float: none; min-width: 0; }
.fb .nice-select .current { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb .nice-select .list {
	z-index: 40;
	width: auto;
	min-width: 100%;
	max-width: 320px;
	max-height: 320px;
	overflow-y: auto;
	margin-top: 6px;
	padding: 4px;
	border-radius: 10px;
	box-shadow: 0 0 0 1px var(--line), var(--sh-3);
}
.fb .nice-select .option {
	min-height: 34px;
	padding: 0 12px;
	border-radius: 6px;
	font-size: var(--fs-md);
	font-weight: 400;
	line-height: 34px;
	color: var(--ink);
}
.fb .nice-select .option:hover,
.fb .nice-select .option.focus { background: var(--surface-mute); }
.fb .nice-select .option.selected { font-weight: 600; color: var(--accent-text); background: var(--accent-tint); }

/* 53.2 The head: [pipeline] [search ............] [+ New]. */
.fb-head {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
	padding: 14px 16px;
}
.fb-search {
	position: relative;
	display: flex;
	align-items: center;
	flex: 1 1 320px;
	max-width: 620px;
	min-width: 0;
	height: 40px;
	margin: 0;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-md);
	background: var(--surface-sunk);
	cursor: text;
	transition: border-color .15s, background-color .15s, box-shadow .15s;
}
.fb-search:hover { border-color: #C7D0DA; }
.fb-search:focus-within {
	border-color: var(--accent-text);
	background: var(--surface);
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.fb-search svg {
	position: absolute;
	left: 12px;
	width: 16px;
	height: 16px;
	fill: none;
	stroke: var(--text-soft);
	stroke-width: 1.8;
	stroke-linecap: round;
	pointer-events: none;
}
.fb-search input[type="search"] {
	width: 100%;
	height: 38px;
	padding: 0 12px 0 38px;
	border: 0;
	background: transparent;
	font-size: var(--fs-base);
	color: var(--ink);
	box-shadow: none;
}
.fb-search input[type="search"]:focus { outline: none; box-shadow: none; }
.fb-search input[type="search"]::placeholder { color: var(--text-soft); }
.fb-action { margin-left: auto; }
.fb-action .ab-button {
	display: inline-flex;
	align-items: center;
	min-height: 40px;
	margin: 0;
	white-space: nowrap;
}

/* The Deals pipeline picker as the head's lead: one bordered field reading "Pipeline  Sales ▾".
   It was an ALL-CAPS eyebrow beside a 240px box (section 27.2). */
.fb-head .deal-pipe-bar {
	display: inline-flex;
	align-items: center;
	flex: 0 1 auto;
	min-width: 0;
	height: 40px;
	margin: 0;
	padding-left: 12px;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-md);
	background: var(--surface);
	transition: border-color .15s, box-shadow .15s;
}
.fb-head .deal-pipe-bar:hover { border-color: #C7D0DA; }
.fb-head .deal-pipe-bar:focus-within {
	border-color: var(--accent-text);
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.fb-head .deal-pipe-bar > label {
	margin: 0;
	font-size: var(--fs-md);
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--text-muted);
	white-space: nowrap;
}
.fb-head .deal-pipe-bar .nice-select,
.fb-head .deal-pipe-bar select {
	flex: 0 1 auto;
	width: auto;
	max-width: 260px;
	height: 38px;
	padding: 0 34px 0 8px;
	border: 0;
	border-radius: var(--r-md);
	background: transparent;
	box-shadow: none;
	font-size: var(--fs-base);
	font-weight: 600;
	line-height: 38px;
	color: var(--ink);
}
.fb-head .deal-pipe-bar .nice-select:focus { outline: none; }

/* 53.3 The filter tier: [Filters 2] [chips ... date] [Clear all] [Apply]. A shade darker than the
   head so the two tiers read as two jobs without a second card. */
.fb-filters {
	display: flex;
	align-items: flex-start;
	gap: 10px 14px;
	padding: 10px 16px;
	border-top: 1px solid var(--line);
	border-radius: 0 0 var(--r-lg) var(--r-lg);
	background: var(--surface-sunk);
}
.fb-title {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 34px;
	font-size: var(--fs-md);
	font-weight: 600;
	color: var(--ink-2);
	white-space: nowrap;
}
.fb-title svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.fb-count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: var(--r-pill);
	background: var(--accent-tint);
	box-shadow: inset 0 0 0 1px rgba(23, 128, 61, .3);
	font-size: var(--fs-xs);
	font-weight: 700;
	color: var(--accent-text);
	font-variant-numeric: tabular-nums;
}
.fb-chips {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	flex: 1 1 auto;
	min-width: 0;
}
.fb-end {
	display: flex;
	align-items: center;
	gap: 14px;
	flex: 0 0 auto;
	height: 34px;
}
.fb-clear { font-size: var(--fs-md); font-weight: 500; color: var(--text-muted); text-decoration: none; white-space: nowrap; }
.fb-clear:hover,
.fb-clear:focus { color: var(--ink); text-decoration: underline; }
.fb .fb-apply {
	display: inline-flex;
	align-items: center;
	min-height: 34px;
	margin: 0;
	padding: 0 16px;
	transition: border-color .15s, color .15s, box-shadow .15s;
}
/* Something in the bar was edited and not applied yet (filterbar.js). */
.fb.is-dirty .fb-apply {
	border-color: var(--accent-text);
	color: var(--accent-text);
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.fb.is-busy { cursor: progress; }
.fb.is-busy .fb-filters,
.fb.is-busy .fb-head { opacity: .6; pointer-events: none; }

/* 53.4 A filter chip: "Key  Value ▾". The niceSelect div is taken out of positioning (static) so
   its list and caret anchor to the whole pill, and its ::before stretches over the pill so a click
   on the key opens the menu too. */
.fb-chip {
	position: relative;
	display: inline-flex;
	align-items: center;
	max-width: 100%;
	height: 34px;
	padding-left: 12px;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-pill);
	background: var(--surface);
	transition: border-color .15s, background-color .15s, box-shadow .15s;
}
.fb-chip:hover { border-color: #C7D0DA; }
.fb-chip:focus-within {
	border-color: var(--accent-text);
	box-shadow: 0 0 0 3px rgba(63, 191, 60, .14);
}
.fb-chip-key {
	padding-right: 6px;
	font-size: var(--fs-md);
	font-weight: 500;
	color: var(--text-muted);
	white-space: nowrap;
}
.fb-chip .nice-select,
.fb-chip select {
	position: static;
	flex: 0 1 auto;
	width: auto;
	max-width: 200px;
	height: 32px;
	min-height: 0;
	padding: 0 30px 0 0;
	border: 0;
	border-radius: var(--r-pill);
	background: transparent;
	box-shadow: none;
	font-size: var(--fs-md);
	font-weight: 600;
	line-height: 32px;
	color: var(--ink);
}
.fb-chip .nice-select::before { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.fb-chip .nice-select::after { right: 13px; }
.fb-chip .nice-select:focus { outline: none; }
.fb-chip .nice-select .list { left: -1px; top: 100%; }

.fb-chip.is-on {
	border-color: rgba(23, 128, 61, .45);
	background: var(--accent-tint);
}
.fb-chip.is-on .fb-chip-key { color: var(--accent-text); }
.fb-chip.is-on .nice-select::after { border-color: var(--accent-text); }

/* The chip's x. Present only on an engaged chip, and only once filterbar.js is running. It takes
   the caret's place, so an engaged chip offers "remove" where an idle one offers "open". */
.fb-chip-x { display: none; }
.fb.is-js .fb-chip-x {
	position: relative;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 22px;
	height: 22px;
	margin: 0 5px 0 -26px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--accent-text);
	cursor: pointer;
}
.fb.is-js .fb-chip-x:hover { background: rgba(23, 128, 61, .12); }
.fb.is-js .fb-chip-x:focus-visible { outline: var(--focus-ring); outline-offset: 1px; }
.fb-chip-x svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.fb.is-js .fb-chip.is-on .nice-select::after { display: none; }

/* 53.5 The date range as one pill: "[cal] Created ▾  Any time ▾ | From [date] To [date]".
   GS\Common\DateRange draws the same markup it always did; only its skin is new here. */
.fb .dr-group {
	display: inline-flex;
	align-items: center;
	flex-wrap: nowrap;
	gap: 2px;
	max-width: 100%;
	height: 34px;
	padding: 0 6px 0 34px;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-pill);
	background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236B7A90' stroke-width='1.6' stroke-linecap='round'%3E%3Crect x='3' y='4.5' width='14' height='12.5' rx='2'/%3E%3Cpath d='M3 8.5h14M7 2.5v4M13 2.5v4'/%3E%3C/svg%3E") no-repeat 12px 50% / 15px 15px;
	transition: border-color .15s, background-color .15s, box-shadow .15s;
}
.fb .dr-group:hover { border-color: #C7D0DA; }
.fb .dr-group:focus-within { border-color: var(--accent-text); box-shadow: 0 0 0 3px rgba(63, 191, 60, .14); }
.fb .dr-group.is-on { border-color: rgba(23, 128, 61, .45); background-color: var(--accent-tint); }
.fb .dr-group .nice-select,
.fb .dr-group select {
	flex: 0 0 auto;
	width: auto;
	max-width: 170px;
	height: 30px;
	min-height: 0;
	padding: 0 26px 0 6px;
	border: 0;
	border-radius: 6px;
	background: transparent;
	box-shadow: none;
	font-size: var(--fs-md);
	font-weight: 600;
	line-height: 30px;
	color: var(--ink);
}
.fb .dr-group .nice-select::after { right: 10px; }
.fb .dr-group .nice-select:hover,
.fb .dr-group .nice-select.open { background: rgba(16, 26, 43, .04); }
.fb .dr-group .nice-select:focus { outline: none; }
/* "Created" names WHICH date, so it reads as the key; the preset beside it is the value. */
.fb .dr-group select[name="dr"] + .nice-select,
.fb .dr-group select[name="dr"] { font-weight: 500; color: var(--text-muted); }
.fb .dr-group.is-on select[name="dr"] + .nice-select { color: var(--accent-text); }
.fb .dr-label { padding: 0 6px; font-size: var(--fs-md); font-weight: 500; color: var(--text-muted); white-space: nowrap; }
.fb .dr-date {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin: 0;
	padding-left: 8px;
	font-size: var(--fs-sm);
	font-weight: 500;
	color: var(--text-muted);
	white-space: nowrap;
}
/* One hairline between "when" and the explicit dates: they are the two ways to answer it. */
.fb .dr-group > .nice-select + .dr-date,
.fb .dr-group > select + .dr-date { margin-left: 4px; border-left: 1px solid var(--line); }
.fb .dr-date input[type="date"] {
	width: 128px;
	height: 26px;
	padding: 0 6px;
	border: 1px solid transparent;
	border-radius: 6px;
	background: transparent;
	font-size: var(--fs-md);
	color: var(--ink);
	font-variant-numeric: tabular-nums;
}
.fb .dr-date input[type="date"]:hover { background: rgba(16, 26, 43, .04); }
.fb .dr-date input[type="date"]:focus { outline: none; border-color: var(--accent-text); background: var(--surface); }

/* 53.6 Narrow screens. The head stacks (lead, search, action each a full row); every chip and the
   date range take a full row of their own, and the date pill becomes a rounded box that wraps. */
@media (max-width: 767px) {
	.fb-head { padding: 12px; }
	.fb-head .deal-pipe-bar,
	.fb-search { flex: 1 1 100%; max-width: none; }
	.fb-head .deal-pipe-bar .nice-select,
	.fb-head .deal-pipe-bar select { flex: 1 1 auto; max-width: none; }
	.fb-action { flex: 1 1 100%; margin-left: 0; }
	.fb-action .ab-button { justify-content: center; width: 100%; }

	.fb-filters { flex-wrap: wrap; padding: 10px 12px 12px; }
	.fb-chips { flex: 1 1 100%; }
	.fb-chip { flex: 1 1 100%; }
	.fb-chip .nice-select,
	.fb-chip select { flex: 1 1 auto; max-width: none; }
	.fb .dr-group {
		flex: 1 1 100%;
		flex-wrap: wrap;
		height: auto;
		padding: 4px 8px 4px 34px;
		border-radius: var(--r-lg);
		background-position: 12px 12px;
	}
	.fb .dr-group > .nice-select + .dr-date,
	.fb .dr-group > select + .dr-date { margin-left: 0; border-left: 0; }
	.fb .dr-date { padding-left: 6px; }
	.fb-end { flex: 1 1 100%; justify-content: flex-end; }
}

@media (prefers-reduced-motion: reduce) {
	.fb-search, .fb-chip, .fb .dr-group, .fb-head .deal-pipe-bar, .fb .fb-apply { transition: none; }
}

/* =========================================================================================
   54. MRR forecast (P1.5, 28 Sep 2026) -- Reports > Revenue, under "Pipeline by stage".
   Open deals by expected close month, weighted by stage win probability. Reuses the funnel card
   (.rev-funnel); the table is the only new shape. Numbers right-aligned and tabular so the eye
   runs down a column; the run-rate column is the answer, so it is the one set in bold.
   ========================================================================================= */
.platformstats .rev-forecast { margin-top: 16px; }
.platformstats .fc-warn {
	background: #FFF7E6;
	border: 1px solid #F3D9A4;
	color: #7A4B00;
	border-radius: 8px;
	padding: 8px 12px;
	font-size: 13px;
	margin: 0 0 12px;
}
.platformstats .fc-warn a { color: #7A4B00; text-decoration: underline; }
.platformstats .fc-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.platformstats .fc-table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 560px; }
.platformstats .fc-table th, .platformstats .fc-table td { padding: 7px 10px; border-bottom: 1px solid var(--line); text-align: left; white-space: nowrap; }
.platformstats .fc-table thead th { font-size: 12px; font-weight: 600; color: #5B6B80; }
.platformstats .fc-table .n { text-align: right; font-variant-numeric: tabular-nums; }
.platformstats .fc-table .fc-run { font-weight: 700; color: var(--ink); }
.platformstats .fc-table tr.is-zero td { color: #9AA6B6; }
.platformstats .fc-table tbody th { font-weight: 600; color: var(--ink); }
.platformstats .fc-table tbody.fc-other th { font-weight: 600; color: #5B6B80; }
.platformstats .fc-table tbody.fc-other tr:first-child th, .platformstats .fc-table tbody.fc-other tr:first-child td { border-top: 2px solid var(--line); }

/* 53.7 Dropdown lists that open upward (luna.js adds `drop-up` when there is no room below), and a
   cap on long lists inside a filter dialog so a 13-person Owner list scrolls within itself instead
   of running off the dialog. */
.nice-select.drop-up .list {
	top: auto;
	bottom: 100%;
	margin-top: 0;
	margin-bottom: 4px;
	transform-origin: 50% 100%;
}
.xs-body .nice-select .list {
	max-height: 260px;
	overflow-y: auto;
}
/* Create Task pop-up, Due Date row: the date input (40px) and the three skinned selects (45px) floated side by side
   at different heights with uneven gaps. One flex row, one height, even gaps -- on every page that opens the pop-up. */
.addtask_form div:has(> #schedule) { display: flex !important; flex-wrap: wrap; align-items: center; gap: 8px; }
.addtask_form div:has(> #schedule) > #schedule,
.addtask_form div:has(> #schedule) > .nice-select {
	float: none !important; margin: 0 !important; height: 44px !important; min-height: 44px !important; line-height: 42px !important;
	box-sizing: border-box; border-radius: 8px !important;
}
.addtask_form div:has(> #schedule) > #schedule { width: 140px !important; flex: 0 0 140px; padding: 0 12px !important; }
.addtask_form div:has(> #schedule) > .nice-select { width: 78px !important; flex: 0 0 78px; display: flex !important; align-items: center; }
/* Deal forms: searchable contact / company pickers (dealpicker.js). */
.deal-pick .selectize-control.multi .selectize-input { min-height: 44px; border-radius: 8px; padding: 6px 8px; }
.deal-pick .selectize-control.multi .selectize-input > div, .dlg .selectize-control.multi .selectize-input > div { background: #EEF7F0; color: #1E7B34; border: 1px solid #CDEFD3; border-radius: 6px; padding: 2px 6px; }
.dp-opt { display: flex; flex-direction: column; padding: 6px 10px; }
.dp-opt-title { color: #1F2937; font-size: 13.5px; }
.dp-opt-sub { color: #6B778A; font-size: 12px; }
.dp-none { color: #6B778A; }
.deal-search-hint { margin-top: 6px; color: #6B778A; font-size: 12px; }
.deal-pick-col .selectize-dropdown, .dlg .selectize-dropdown { max-height: 320px; }
/* The columns were a 340px scroll box for the old checkbox list; with a search box inside, that clipped the results
   dropdown. Let it overflow, and give the box and the dropdown room. */
.deal-pick-col { overflow: visible !important; max-height: none !important; }
.deal-pick-col .selectize-control { margin: 10px 12px 4px; }
.deal-pick-col .deal-search-hint { margin: 0 12px 10px; }
.deal-pick-col .selectize-dropdown, .dlg .selectize-dropdown { z-index: 1050; box-shadow: 0 8px 24px rgba(16,24,40,.12); border-radius: 8px; }
.deal-pick-col .selectize-dropdown .dp-opt { border-bottom: 1px solid #F1F4F8; }
.deal-pick-col .selectize-dropdown .active .dp-opt, .dlg .selectize-dropdown .active .dp-opt { background: #F3FBF4; }

/* Deal form: the Details (custom properties) panel is a block like the picker and Line Items -- full width, no empty
   label cell, and its fields two per row so the long HubSpot groups are not one narrow column. */
body.deals .adminform_form .pr-panel { width: 100%; margin: 4px 0 0; }
body.deals .adminform_form .pr-panel .pr-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 24px; }
@media (max-width: 900px) { body.deals .adminform_form .pr-panel .pr-grid { grid-template-columns: minmax(0, 1fr); } }
/* Picker columns: keep the search box and hint off the column edges. */
body.deals .deal-pick-col .selectize-control { margin: 10px 12px 4px !important; }
body.deals .deal-pick-col .deal-search-hint { padding: 0 12px 10px; margin: 0; }
/* CR-21: Lifecycle Stage in the company header. */
.company-details-wrapper .lc-control { display: flex; align-items: center; gap: 8px; }
.company-details-wrapper .lc-control .nice-select, .company-details-wrapper .lc-select { min-width: 190px; height: 34px !important; line-height: 32px !important; border-radius: 8px !important; font-size: 13px; }
.company-details-wrapper .lc-status { font-size: 12px; color: #6B778A; }
.company-details-wrapper .lc-status.is-ok { color: #1E7B34; }
.company-details-wrapper .lc-status.is-bad { color: #B42318; }
.company-details-wrapper .lc-pill { display: inline-block; background: #EEF4FF; color: #2F55B5; border-radius: 999px; padding: 2px 10px; font-size: 13px; }
.company-details-wrapper .lc-empty { color: #9AA4B2; }
/* Lifecycle Stage: the save message goes under the dropdown, on one line -- it was squeezed into a ~10px column. */
.company-details-wrapper .lc-control { flex-direction: column; align-items: flex-start; gap: 4px; }
.company-details-wrapper .lc-status { display: block; width: auto; white-space: normal; word-break: normal; min-height: 0; }
/* CF-3: Client Type labels in the company header. */
.company-details-wrapper .ct-pills { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.company-details-wrapper .ct-pill { display: inline-block; background: #F1F4F8; color: #374151; border: 1px solid #E3E8EF; border-radius: 999px; padding: 2px 10px; font-size: 12.5px; }
.company-details-wrapper .ct-edit { font-size: 12.5px; color: #2F6FDE; text-decoration: none; }
/* Sofia's field mapping: deal "Key fields" strip, and the Key fields block on the deal form. */
.deal-key-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px 24px; background: #fff; border: 1px solid #E3E8EF; border-radius: 12px; padding: 14px 18px; margin: 12px 0; }
.deal-key-fields .kf-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6B778A; margin-bottom: 4px; }
.deal-key-fields .kf-value { color: #1F2937; font-size: 14px; word-break: break-word; }
body.deals .adminform_form .adminform_table > .form-group:has(.pr-pinned) { grid-column: span 6; grid-template-columns: minmax(0, 1fr); }
body.deals .adminform_form .form-group:has(.pr-pinned) > div:first-child { display: none; }
body.deals .adminform_form .pr-pinned { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 24px; margin: 0; }
body.deals .adminform_form .pr-pinned > .pr-field { width: auto; padding: 0; }

/* Owner 2026-10-07: header fields always show; an empty one is a muted dash (a link to Edit when the viewer may edit). */
.kf-empty, a.kf-empty { color: #A3A3A3 !important; font-weight: 400; text-decoration: none; }
a.kf-empty:hover, a.kf-empty:focus { color: #1C839D !important; text-decoration: underline; }
.customer-phone .kf-empty { font-style: italic; }

/* ==========================================================================================
   Deal page header (owner 2026-10-07): chips + actions, the stage bar, the figures.
   ========================================================================================== */
body.deals .deal-head.dh { display: block; padding: 18px 20px 16px; }
.dh-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.dh-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.dh-chip {
	display: inline-flex; align-items: center; height: 24px; padding: 0 10px; border-radius: 999px;
	font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
	background: #F1F4F8; color: #4A5568; border: 1px solid #E3E8EF; white-space: nowrap;
}
.dh-chip-pipe { background: #FFFFFF; color: var(--ink); }
.dh-status.is-open { background: #EAF2FF; color: #1D4ED8; border-color: #CFE0FF; }
.dh-status.is-won  { background: #E7F8E6; color: #1E7B1C; border-color: #C6EDC4; }
.dh-status.is-lost { background: #FDECEA; color: #B3261E; border-color: #F7CFCB; }
.dh-pipe-btn svg { flex-shrink: 0; }

/* The stage bar: chevrons, done = tinted, current = filled, won/lost = their colour. */
.dh-stages { display: flex; list-style: none; margin: 16px 0 0; padding: 0; gap: 3px; overflow-x: auto; }
.dh-step {
	flex: 1 1 0; min-width: 92px; position: relative; height: 34px; display: flex; align-items: center; justify-content: center;
	padding: 0 18px; font-size: 12px; font-weight: 600; color: #6B778A; background: #F1F4F8;
	clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%, 10px 50%);
}
.dh-step:first-child { clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%); border-radius: 6px 0 0 6px; }
.dh-step:last-child { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 10px 50%); border-radius: 0 6px 6px 0; }
.dh-step span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-step.is-done    { background: #E3F5E2; color: #1E7B1C; }
.dh-step.is-current { background: var(--accent-fill); color: var(--accent-on-fill, #0E1A3C); }
.dh-step.is-won     { background: #2E9E2B; color: #FFFFFF; }
.dh-step.is-lost    { background: #B3261E; color: #FFFFFF; }
.dh-step.is-closed  { background: #F7F8FA; color: #A3A3A3; font-weight: 500; }

/* Figures and people. */
.dh-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px 24px; margin-top: 16px; padding-top: 14px; border-top: 1px solid #EEF1F5; }
.dh-stat-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6B778A; margin-bottom: 4px; }
.dh-stat-value { font-size: 14px; color: #1F2937; word-break: break-word; }
.dh-stat-value a { color: inherit; text-decoration: underline; text-decoration-color: #C9D2DE; text-underline-offset: 2px; }
.dh-stat-value a:hover { color: #1C839D; }
.dh-after-board { margin-top: 18px; }

/* The card the deal page sent you to. */
body.deals .li-pipe-card.is-focus { border-color: var(--accent-fill) !important; box-shadow: 0 0 0 3px rgba(63, 191, 60, .28) !important; }
body.deals .li-pipe-card.is-focus { scroll-margin: 120px; }

@media (max-width: 720px) {
	.dh-top { align-items: flex-start; }
	.dh-top .deal-head-actions { width: 100%; flex-wrap: wrap; }
	.dh-step { min-width: 110px; }
}

/* Deal header: Sofia's Key fields inside the header (owner 2026-10-07), same cell look as the figures above them. */
.dh-keys { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px 24px; margin-top: 12px; padding-top: 12px; border-top: 1px dashed #EEF1F5; }
.dh-keys .kf-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6B778A; margin-bottom: 4px; }
.dh-keys .kf-value { font-size: 14px; color: #1F2937; word-break: break-word; }
a.dh-chip-pipe { text-decoration: none; cursor: pointer; }
a.dh-chip-pipe:hover { border-color: var(--accent-fill); color: var(--ink); }
/* "View pipeline" jumps to the deal's board below; clear the sticky top bar and glide there. */
.dh-board-anchor { scroll-margin-top: 90px; }
html:has(body.deals) { scroll-behavior: smooth; }

/* Logged activity (GS\Activity\ActivityLog, 2026-10-07): the shared form, the deal Activity panel, contact rows. */
.activity-log-box { margin: 0 0 16px; }
.activity-log-box [hidden] { display: none !important; }
.activity-log-form [data-alf-call][hidden] { display: none !important; }
.deal-activity { background: #fff; border: 1px solid #E3E8EF; border-radius: 12px; padding: 16px 20px; margin: 12px 0; scroll-margin-top: 90px; }
.deal-activity .da-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px 10px; margin-bottom: 12px; }
.deal-activity .da-head h3 { margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); }
.deal-activity .da-count { font-size: 12px; font-weight: 600; color: #4A5568; background: #F1F4F8; border-radius: 999px; padding: 1px 8px; }
.deal-activity .da-sub { flex-basis: 100%; margin: 0; font-size: 13px; color: #6B778A; }
.deal-activity .da-list { list-style: none; margin: 0; padding: 0; }
/* Deal Files (GS\Deals\DealFiles, 2026-10-07): contracts and documents of the deal, same card as Activity. */
.deal-files { background: #fff; border: 1px solid #E3E8EF; border-radius: 12px; padding: 16px 20px; margin: 12px 0; scroll-margin-top: 90px; }
.deal-files .df-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.deal-files .df-head h3 { margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); }
.deal-files .df-count { font-size: 12px; font-weight: 600; color: #4A5568; background: #F1F4F8; border-radius: 999px; padding: 1px 8px; }
.deal-files .df-up { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin: 0 0 12px; }
.deal-files .df-up input[type="file"] { font-size: 13px; max-width: 100%; }
.deal-files .df-hint { flex-basis: 100%; font-size: 12.5px; color: #6B778A; }
.deal-files .df-empty { margin: 0; font-size: 13px; color: #6B778A; }
.deal-files .df-list { list-style: none; margin: 0; padding: 0; }
.deal-files .df-list li { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; padding: 9px 0; border-top: 1px solid #EEF1F5; }
.deal-files .df-name { flex: 1 1 220px; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.deal-files .df-name a { color: #2563EB; }
.deal-files .df-meta { font-size: 12.5px; color: #6B778A; }
.deal-files .df-del { margin: 0; }
.deal-files .df-x { padding: 0; border: 0; background: none; color: #B3261E; font-size: 12.5px; cursor: pointer; }
.deal-files .df-x:hover { text-decoration: underline; }
.deal-activity .da-item { display: flex; gap: 12px; padding: 12px 0; border-top: 1px solid #EEF1F5; }
.deal-activity .da-item:first-child { border-top: 0; }
.deal-activity .da-icon { flex: 0 0 32px; height: 32px; border-radius: 50%; background: #F4F6FA; display: flex; align-items: center; justify-content: center; }
.deal-activity .da-main { min-width: 0; flex: 1; }
.deal-activity .da-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.deal-activity .da-date { margin-left: auto; font-size: 12px; color: #6B778A; }
.deal-activity .da-meta { font-size: 12px; color: #6B778A; }
.deal-activity .da-body { margin-top: 4px; font-size: 14px; color: #1F2937; word-break: break-word; }
.act-logged-chip { display: inline-block; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #1D4ED8; background: #EAF2FF; border-radius: 999px; padding: 1px 8px; margin-right: 4px; }
.act-logged-body { white-space: normal; word-break: break-word; }
.act-logged-meta, .log-company-with { font-size: 12px; color: #6B778A; margin-top: 3px; }

/* Reports → Team activity (2026-10-07). Reuses the Dashboards hero, chips, tiles and cards; these are its own bits. */
body.teamactivity .ta-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
body.teamactivity .ta-intro { margin: 0; color: #4A5568; font-size: 14px; }
body.teamactivity .ta-unassigned { margin-left: 4px; }
body.teamactivity .ta-tiles { margin: 14px 0; }
body.teamactivity .ta-grid { margin-bottom: 14px; }
body.teamactivity .ta-sub { font-size: 12px; color: #6B778A; }
body.teamactivity .ta-table-wrap { overflow-x: auto; }
body.teamactivity .ta-table { width: 100%; border-collapse: collapse; font-size: 13px; }
body.teamactivity .ta-table th, body.teamactivity .ta-table td { padding: 8px 10px; border-bottom: 1px solid #EEF1F5; text-align: left; white-space: nowrap; }
body.teamactivity .ta-table thead th { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6B778A; background: #F7F8FA; }
body.teamactivity .ta-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
body.teamactivity .ta-table td.is-zero { color: #A3A3A3; }
body.teamactivity .ta-table tr.ta-total th, body.teamactivity .ta-table tr.ta-total td { border-top: 2px solid #E3E8EF; font-weight: 600; }
body.teamactivity .ta-table td.is-empty { text-align: center; color: #7C8AA0; padding: 28px; }
body.teamactivity .ta-notes { margin: 10px 0 24px; padding-left: 18px; font-size: 12px; color: #6B778A; }
body.teamactivity .ta-notes li { margin: 2px 0; }
/* Team activity tiles: room for the longer labels ("Deal stage moves", "Logged activities") instead of an ellipsis. */
body.teamactivity .ta-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
body.teamactivity .ta-tiles .db-tile { min-width: 0; }
body.teamactivity .ta-tiles .db-tile-k { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.3; }
body.teamactivity .db-seg { flex-wrap: wrap; }
