/* ============================================================================
   EquipDash Design System v2 - tokens (P0)
   The single source of every color, type size, space, radius, and shadow.
   Nothing outside this file may declare a raw hex for UI chrome.
   Spec: docs/mockups/design-system-v2.html · Plan: docs/DESIGN_SYSTEM_V2_PLAN.md
   ========================================================================== */

:root {
	/* ---- brand ---- */
	--ed-navy-900: #00224a;
	--ed-navy-700: #003264; /* primary actions, the accent */
	--ed-navy-600: #0a4a8c; /* links, hover, focus */
	--ed-navy-200: #dbe4f0; /* soft navy fill + border: comparison bars, lane segments */
	--ed-navy-100: #eaf1f8; /* selected, info chips */

	/* ---- surfaces ---- */
	--ed-canvas: #f5f7fb;   /* app background behind cards */
	--ed-surface: #ffffff;  /* cards */
	--ed-sunken: #f8fafd;   /* wells, hover rows */

	/* ---- text ---- */
	--ed-ink: #22314e;      /* headings, body */
	--ed-muted: #5A7089;    /* secondary (AA-checked; predates v2) */
	--ed-faint: #95a2b6;    /* captions, placeholders */

	/* ---- border ---- */
	--ed-border: #e7ecf3;   /* the ONE border color */

	/* ---- status ---- */
	--ed-success: #1d8a45;
	--ed-success-soft: #e7f4ec;
	--ed-success-border: #bfe3cc; /* border on a success-soft fill */
	--ed-warning: #b45309;
	--ed-warning-soft: #fdf3e7;
	--ed-danger: #c02626;
	--ed-danger-soft: #fbeaea;

	/* ---- AI (Dash surfaces only) ---- */
	--ed-ai: #7C3AED;
	--ed-ai-2: #9d64f2; /* gradient partner for --ed-ai */
	--ed-ai-soft: #f3edfd;

	/* ---- on-accent (text/icons on filled navy, danger, ai) ---- */
	--ed-on-accent: #ffffff;
	--ed-danger-strong: #a81f1f; /* danger hover */
	--ed-setup-border: #d4dcea;  /* dashed border on setup cards */
	--ed-hatch-blocked: repeating-linear-gradient(45deg, #e6ebf3 0 6px, #f3f6fa 6px 12px); /* unavailable timeline segments */

	/* ---- type scale (BRCandor is the one brand face) ---- */
	--ed-font: "BRCandor", sans-serif;
	--ed-display-30: 600 30px/1.2 var(--ed-font);
	--ed-display-24: 600 24px/1.25 var(--ed-font);
	--ed-title-18: 600 18px/1.3 var(--ed-font);
	--ed-subtitle-15: 600 15px/1.4 var(--ed-font);
	--ed-body-14: 400 14px/1.5 var(--ed-font);
	--ed-small-12: 400 12.5px/1.45 var(--ed-font);
	--ed-caption-11: 600 11px/1.3 var(--ed-font); /* + uppercase + .06em spacing */

	/* ---- space (4-base) ---- */
	--ed-s1: 4px;
	--ed-s2: 8px;
	--ed-s3: 12px;
	--ed-s4: 16px;
	--ed-s5: 20px;
	--ed-s6: 24px;
	--ed-s7: 32px;
	--ed-s8: 40px;

	/* ---- radius ---- */
	--ed-r-ctl: 8px;
	--ed-r-card: 12px;
	--ed-r-pill: 999px;

	/* ---- overlay scrim behind modals and drawers ---- */
	--ed-scrim: rgba(0, 34, 74, .35);

	/* ---- shadows ---- */
	--ed-shadow-card: 0 1px 2px rgba(29, 43, 69, .05), 0 8px 24px rgba(29, 43, 69, .07);
	--ed-shadow-pop: 0 12px 40px rgba(29, 43, 69, .18);

	/* ---- motion ---- */
	--ed-fast: 150ms ease;

	/* ---- named z layers ---- */
	--ed-z-nav: 100;
	--ed-z-drawer: 1050;
	--ed-z-modal: 1055;
	--ed-z-toast: 1080;
	--ed-z-tooltip: 1090;
}

/* ============================================================================
   P0 baseline - the modern-feel flip (issue #4085), token-driven.
   Scoped to the portal content area; the widget has its own stylesheet.
   ========================================================================== */

/* Canvas behind the page; white areas below declare their own surface. */
.main-wrapper .content {
	background: var(--ed-canvas);
}

/* Listing tables: the white card holds the table; the spreadsheet grid goes,
   row dividers stay. Column headers become quiet captions. */
.content .table-responsive {
	background: var(--ed-surface);
	border-radius: var(--ed-r-card);
	/* Hairline card, not a floating shadow panel (table-chrome decision,
	   2026-08-28): crisper, and the tinted header band below anchors the
	   columns. */
	border: 1px solid var(--ed-border);
	/* The card now has an opaque background - legacy pages that tuck the
	   pagination strip up against (or slightly under) the table need real
	   separation or the card paints over the "Showing X of Y" line. */
	margin-bottom: var(--ed-s3);
}

/* The calendar's hover popups (.modal-custom) render tables without a
   .table-responsive card - the legacy table border + border-color background
   doubled every edge there too (#4280). Flat inside the popup; the popup
   card is the chrome. Tab strips in popups get the standard compact size
   via the .nav-tabs normalization below. */
.modal-custom .table {
	border-width: 0;
	border-color: var(--ed-border);
	background: transparent;
	border-radius: 0;
}
.modal-custom .nav-tabs .nav-link {
	font-size: 14px !important;
	font-weight: 500 !important;
	line-height: 20px !important;
	padding: 10px 12px !important;
}

/* The horizontal scrollbar's default gutter painted a ~17px dead white strip
   between the last row and the card's bottom edge (#4263). Slim it down and
   tint the thumb so the strip reads as part of the card. */
.content .table-responsive::-webkit-scrollbar {
	height: 8px;
}
.content .table-responsive::-webkit-scrollbar-track {
	background: transparent;
}
.content .table-responsive::-webkit-scrollbar-thumb {
	background: var(--ed-border);
	border-radius: 8px;
}
.content .table-responsive::-webkit-scrollbar-thumb:hover {
	background: var(--ed-faint);
}

/* The help box hugged the section above it on listing pages (#4263). */
.content .help-box {
	margin-top: var(--ed-s6) !important;
}

/* The whole pagination strip (count text + pills) paints above the table
   card on its own canvas background - some legacy pages tuck it up against
   the card, and only the pill list being elevated left the 'Showing X of Y'
   text clipped behind the card's white. */
.content nav:has(.pagination) {
	position: relative;
	z-index: 1;
	background: var(--ed-canvas);
	padding-top: var(--ed-s2);
}

.content .table-bordered > :not(caption) > * > *,
.content .table > :not(caption) > * > * {
	border-width: 0 0 1px 0;
	border-color: var(--ed-border);
}

/* The card's hairline is the ONLY outer border. Legacy .table-bordered also
   paints its own border AND a border-color background on the table element
   (the old grid trick), which read as a double line around every listing
   (#4260/#4263). The wrapper owns the chrome; the table is flat inside it. */
.content .table-responsive .table,
.content .table-responsive table {
	/* Width 0 only - NOT the `border: 0` shorthand, which resets the
	   inheritable border-color to currentColor and paints every row's
	   Bootstrap border near-black (the dark top/bottom lines regression). */
	border-width: 0;
	border-color: var(--ed-border);
	background: transparent;
	border-radius: 0;
}

/* !important: this is the reset layer over a decade of per-page th styles
   (.products.table th, .customers th, ...) that otherwise out-specify it -
   the customers listing kept 13px dark-bold headers. */
.content .table > thead > tr > th {
	font-size: 11px !important;
	font-weight: 600 !important;
	text-transform: uppercase !important;
	letter-spacing: .06em !important;
	color: var(--ed-faint) !important;
	background: var(--ed-sunken) !important;
	padding-top: 12px;
	padding-bottom: 12px;
}

.content .table > tbody > tr > td {
	padding-top: 13px;
	padding-bottom: 13px;
	vertical-align: middle;
	font-variant-numeric: tabular-nums;
}

.content .table > tbody > tr:last-child > td {
	border-bottom: 0;
}

/* Bootstrap's default 1rem table margin painted a dead white strip between
   the last row and the card's bottom edge. */
.content .table {
	margin-bottom: 0;
}

/* A table already sitting inside an elevated container (settings cards,
   Bootstrap cards) must NOT become a second card - flatten it so it reads
   as part of its card, not a card-in-a-card. */
.content .card .table-responsive,
.content .set-section .table-responsive,
.content .set-section-body .table-responsive,
.content .settings-content-wraper .table-responsive,
.content .settings-content-container .table-responsive,
.content .experience-table-header-wrapper .table-responsive {
	background: transparent;
	border-radius: 0;
	box-shadow: none;
	margin-bottom: 0;
	/* The card hairline stays OFF in here too - with radius 0 it painted a
	   hard square box inside the settings card. Width only (not the border
	   shorthand - that resets the inheritable color to near-black). */
	border-width: 0;
}

/* Header captions apply to ANY table in a responsive wrapper - settings
   tables that don't carry .table were keeping their old dark bold headers. */
.content .table-responsive > table > thead > tr > th {
	font-size: 11px !important;
	font-weight: 600 !important;
	text-transform: uppercase !important;
	letter-spacing: .06em !important;
	color: var(--ed-faint) !important;
	padding-top: 12px;
	padding-bottom: 12px;
}

.content .table-responsive > table {
	margin-bottom: 0;
}

/* Horizontal-scroll affordance (Stripe-style): when a table can scroll,
   eq-tables.js stamps these classes on the card and the faded edge says
   "there is more" - it disappears at the end of the scroll. */
.eq-scroll-host {
	position: relative;
}

.eq-scroll-host::before,
.eq-scroll-host::after {
	content: '';
	position: absolute;
	top: 0;
	bottom: 0;
	width: 48px;
	pointer-events: none;
	z-index: 2;
	opacity: 0;
	transition: opacity var(--ed-fast);
}

.eq-scroll-host::before {
	left: 0;
	border-radius: var(--ed-r-card) 0 0 var(--ed-r-card);
	background: linear-gradient(to right, var(--ed-surface) 15%, rgba(255, 255, 255, 0));
}

.eq-scroll-host::after {
	right: 0;
	border-radius: 0 var(--ed-r-card) var(--ed-r-card) 0;
	background: linear-gradient(to left, var(--ed-surface) 15%, rgba(255, 255, 255, 0));
}

.eq-scroll-host.eq-scroll-more-left::before {
	opacity: 1;
}

.eq-scroll-host.eq-scroll-more-right::after {
	opacity: 1;
}

.content .table > tbody > tr:hover > td {
	background: var(--ed-sunken);
}

/* ============================================================================
   P0 baseline, part 2 - the approved global chrome shift. Existing markup
   (Bootstrap buttons, inputs, cards, menus, modals) picks up the approved
   look app-wide without per-page migration. Kit components supersede these
   as pages migrate.
   ========================================================================== */

/* Buttons: token COLORS only - shapes stay whatever each button's own chrome
   defines (drawer canon: btn-cancel/white stays white, btn-confirm navy).
   .white is the site's white-button modifier - never paint it navy. */
.content .btn {
	white-space: nowrap;
	transition: background var(--ed-fast), color var(--ed-fast);
}

.content .btn-primary:not(.white),
.content .btn-confirm {
	background: var(--ed-navy-700);
	border-color: var(--ed-navy-700);
	color: var(--ed-on-accent);
}

.content .btn-primary:not(.white):hover,
.content .btn-primary:not(.white):focus,
.content .btn-confirm:hover {
	background: var(--ed-navy-600);
	border-color: var(--ed-navy-600);
	color: var(--ed-on-accent);
}

.content .btn-primary.white,
.content .btn-cancel {
	background: var(--ed-surface);
	border-color: var(--ed-border);
	color: var(--ed-navy-700);
}

.content .btn-primary.white:hover,
.content .btn-cancel:hover {
	background: var(--ed-sunken);
	color: var(--ed-navy-700);
}

.content .btn-outline-secondary,
.content .btn-secondary {
	background: var(--ed-surface);
	border-color: var(--ed-border);
	color: var(--ed-ink);
}

/* ONE tab strip size everywhere (#4268/#4270): a legacy nested block ships
   18px labels with a 24px bottom pad and a 4px active underline, which made
   booking/quote detail tabs read twice the size of the product-detail strip.
   Normalize every .nav-tabs to the .pd-tab metrics (14px / 500 / 12x16 pad /
   2px underline). The count chip shrinks to match. */
.content .nav-tabs .nav-item .nav-link,
.content .nav-tabs .nav-link {
	font-size: 14px !important;
	font-weight: 500 !important;
	line-height: 20px !important;
	padding: 12px 16px !important;
	color: var(--ed-muted);
}
.content .nav-tabs .nav-item .nav-link.active,
.content .nav-tabs .nav-link.active {
	font-size: 14px !important;
	font-weight: 600 !important;
	border-bottom-width: 2px !important;
	color: var(--ed-ink);
}
.content .nav-tabs .nav-link span {
	font-size: 12px !important;
	line-height: 14px !important;
	padding: 3px 8px !important;
}

/* Filter pills speak navy - every dropdown filter in the one white 40px
   filter-row family shows navy text like Filters / Filter by date. */
.content .btn-outline-secondary.dropdown-toggle,
.content .dropdown-filter .btn,
.content .dropdown-filter-placeholder-text {
	color: var(--ed-navy-700);
}

/* And they all sit on WHITE, matching Filter by date - transparent pills
   (Calendar view, Filters, the column-manager gear) read as broken next to
   the white ones on the same row (#4264). The gear icon speaks the same
   navy as its neighbors' text. */
.content .dropdown-filter > .btn,
.content .bk-filters-trigger,
.content .cm-trigger,
.content .btn-secondary.dropdown-toggle {
	background: var(--ed-surface);
}
.content .cm-trigger {
	color: var(--ed-navy-700);
}

/* Hover stays WHITE too (#4317) - the generic secondary hover painted these
   pills sunken-gray, which read as "the button isn't white anymore" next to
   its always-white neighbors. Feedback comes from the border instead. */
.content .btn-secondary.dropdown-toggle:hover,
.content .btn-outline-secondary.dropdown-toggle:hover,
.content .dropdown-filter > .btn:hover,
.content .bk-filters-trigger:hover,
.content .cm-trigger:hover {
	background: var(--ed-surface);
	border-color: var(--ed-faint);
	color: var(--ed-navy-700);
}

.content .btn-outline-secondary:hover,
.content .btn-secondary:hover {
	background: var(--ed-sunken);
	border-color: var(--ed-border);
	color: var(--ed-ink);
}

.content .btn-danger {
	background: var(--ed-danger);
	border-color: var(--ed-danger);
}

.content .btn-danger:hover {
	background: var(--ed-danger-strong);
	border-color: var(--ed-danger-strong);
}

/* Form controls: one 40px height, control radius, token border, navy focus. */
.content .form-control,
.content .form-select {
	border-color: var(--ed-border);
	border-radius: var(--ed-r-ctl);
	min-height: 40px;
	color: var(--ed-ink);
}

.content .form-control:focus,
.content .form-select:focus {
	border-color: var(--ed-navy-600);
	box-shadow: 0 0 0 1px var(--ed-navy-600);
}

.content .form-control::placeholder {
	color: var(--ed-faint);
}

/* The filter row is ONE white 40px family: the search box matches the
   filter pills (legacy style.css tinted it grey). */
.content .search-input .form-control,
.content .search-input .input-group .form-control,
.content .search-input .input-group {
	background: var(--ed-surface);
}

.content .input-group-text {
	border-color: var(--ed-border);
	background: var(--ed-sunken);
	color: var(--ed-muted);
}

/* Cards: the one chrome (soft shadow, 12px radius, no hard border). */
.content .card {
	border: none;
	border-radius: var(--ed-r-card);
	box-shadow: var(--ed-shadow-card);
}

.content .card .card-header {
	background: var(--ed-surface);
	border-bottom: 1px solid var(--ed-border);
	border-radius: var(--ed-r-card) var(--ed-r-card) 0 0;
}

/* Menus and popovers float on the pop shadow. */
.content .dropdown-menu {
	border: none;
	border-radius: 10px;
	box-shadow: var(--ed-shadow-pop);
	color: var(--ed-ink);
}

.content .dropdown-item:hover,
.content .dropdown-item:focus {
	background: var(--ed-sunken);
	color: var(--ed-ink);
}

/* Modals and drawers: card radius + pop shadow. */
.modal-content {
	border: none;
	border-radius: var(--ed-r-card);
	box-shadow: var(--ed-shadow-pop);
}

.modal-header {
	border-bottom-color: var(--ed-border);
}

.modal-footer {
	border-top-color: var(--ed-border);
}

/* Pagination: quiet pills, navy active. */
.content .pagination .page-link {
	border: none;
	border-radius: var(--ed-r-ctl);
	color: var(--ed-muted);
	margin: 0 2px;
}

.content .pagination .page-item.active .page-link {
	background: var(--ed-navy-700);
	color: var(--ed-on-accent);
}

.content .pagination .page-link:hover {
	background: var(--ed-sunken);
	color: var(--ed-ink);
}

/* Page header bar: white strip over the canvas. */
.content > .title,
.content .title.product-details-header {
	background: var(--ed-surface);
	border-bottom: 1px solid var(--ed-border);
}

/* Nav tabs (legacy pages): the one tab look. */
.content .nav-tabs {
	border-bottom: 1px solid var(--ed-border);
}

.content .nav-tabs .nav-link {
	border: none;
	border-bottom: 2px solid transparent;
	color: var(--ed-muted);
	font-weight: 600;
}

.content .nav-tabs .nav-link.active {
	border-bottom-color: var(--ed-navy-700);
	color: var(--ed-navy-700);
	background: none;
}

/* Drawer/modal scrim: style.css only defines .offcanvas-back NESTED inside
   the page wrapper, so a drawer mounted at layout level (global Quick Book,
   any future global drawer) rendered an INVISIBLE overlay - the page behind
   stayed fully bright. Define the overlay at top level so every drawer dims
   the page, wherever it mounts. */
.offcanvas-back {
	position: fixed;
	inset: 0;
	width: 100%;
	height: 100%;
	background: var(--ed-scrim);
	z-index: calc(var(--ed-z-drawer) - 1);
	display: none;
}

.offcanvas-back.show {
	display: block;
}

/* ============================================================================
   The one toast stack (#4108) - bottom-right, newest on top, max 3.
   Rendered by public/js/eq-toast.js; visuals from the approved v2 spec
   (docs/mockups/design-system-v2.html#feedback).
   ========================================================================== */

.ed-toasts {
	position: fixed;
	right: 16px;
	bottom: 16px;
	z-index: var(--ed-z-toast);
	display: flex;
	flex-direction: column;
	gap: 10px;
	align-items: flex-end;
	pointer-events: none;
}
.ed-toasts > * { pointer-events: auto; }

.ed-toast {
	display: flex;
	gap: 11px;
	align-items: flex-start;
	background: var(--ed-surface);
	border: 1px solid var(--ed-border);
	border-left: 3px solid var(--ed-success);
	border-radius: 11px;
	box-shadow: var(--ed-shadow-pop);
	padding: 12px 14px;
	width: 320px;
	position: relative;
	overflow: hidden;
	animation: ed-toast-in var(--ed-fast);
}
.ed-toast-icon {
	width: 26px;
	height: 26px;
	border-radius: 8px;
	display: grid;
	place-items: center;
	font-size: 12px;
	font-weight: 800;
	flex: 0 0 26px;
}
.ed-toast-body { min-width: 0; }
.ed-toast-title { display: block; font-size: 13px; font-weight: 700; color: var(--ed-ink); }
.ed-toast-msg { font: var(--ed-small-12); color: var(--ed-muted); display: block; }
.ed-toast-action {
	color: var(--ed-navy-600);
	font-weight: 700;
	font-size: 12px;
	margin-top: 3px;
	display: inline-block;
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
}
.ed-toast-x {
	margin-left: auto;
	color: var(--ed-faint);
	background: none;
	border: none;
	font-size: 12px;
	padding: 0;
	cursor: pointer;
	flex: 0 0 auto;
}
.ed-toast-bar {
	position: absolute;
	left: 0;
	bottom: 0;
	height: 2px;
	background: var(--ed-border);
	width: 100%;
}
.ed-toast-bar i {
	display: block;
	height: 100%;
	background: var(--ed-success);
	animation: ed-toast-run 5s linear forwards;
}
.ed-toast.is-success { border-left-color: var(--ed-success); }
.ed-toast.is-success .ed-toast-icon { background: var(--ed-success-soft); color: var(--ed-success); }
.ed-toast.is-warning { border-left-color: var(--ed-warning); }
.ed-toast.is-warning .ed-toast-icon { background: var(--ed-warning-soft); color: var(--ed-warning); }
.ed-toast.is-warning .ed-toast-bar i { background: var(--ed-warning); }
.ed-toast.is-error { border-left-color: var(--ed-danger); }
.ed-toast.is-error .ed-toast-icon { background: var(--ed-danger-soft); color: var(--ed-danger); }
.ed-toast.is-info { border-left-color: var(--ed-navy-600); }
.ed-toast.is-info .ed-toast-icon { background: var(--ed-navy-100); color: var(--ed-navy-600); }
.ed-toast.is-info .ed-toast-bar i { background: var(--ed-navy-600); }

/* The quiet auto-save confirmation. */
.ed-toast-saved {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	background: var(--ed-ink);
	color: #fff;
	border-radius: 999px;
	padding: 7px 14px;
	font-size: 12.5px;
	font-weight: 700;
	box-shadow: var(--ed-shadow-pop);
	animation: ed-toast-in var(--ed-fast);
}

.ed-toast.is-out,
.ed-toast-saved.is-out {
	opacity: 0;
	transform: translateY(6px);
	transition: opacity 180ms ease, transform 180ms ease;
}

@keyframes ed-toast-in { from { opacity: 0; transform: translateY(8px); } }
@keyframes ed-toast-run { from { width: 100%; } to { width: 0; } }

@media (max-width: 640px) {
	.ed-toasts { left: 12px; right: 12px; bottom: 12px; align-items: stretch; }
	.ed-toast { width: auto; }
}

/* Column-manager popover on the token chrome (#4104): pop shadow + the one
   border color, matching every other popover. */
.cm-panel {
	border-color: var(--ed-border);
	box-shadow: var(--ed-shadow-pop);
}
