/* Tabler sets `:root, :host { margin-left: calc(100vw - 100%) }` at >=992px
   (tabler.min.css) -- a scrollbar-compensation trick for layouts with
   elements explicitly sized 100vw (e.g. a fixed-position sidebar), so they
   stay aligned once a scrollbar appears. We don't use any 100vw-sized
   elements anywhere, so this rule has no benefit here -- it was just
   shifting the whole page right by the scrollbar's width whenever one
   appeared, and only on viewports >=992px, which is why the resulting nav
   gap seemed tied to page length rather than viewport width at first. */
:root {
    margin-left: 0 !important;
}

/* Organization/Contact Detail Contact Info cards: truncate a long website/email value with
   an ellipsis instead of overflowing the card -- mainly matters on narrow (mobile)
   viewports where these can be much wider than the card. */
.contact-field-truncate {
    display: flex;
    align-items: center;
    min-width: 0;
}

.contact-field-truncate .contact-field-value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.contact-field-copy {
    cursor: pointer;
    flex-shrink: 0;
    /* #298 (MB-003): the bare icon glyph was well under the 24px CSS px tap-target minimum
       -- an inline-flex box with explicit dimensions grows the hit area without enlarging
       the glyph itself. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
}

/* Lets a long wordmark wrap rather than overflow its row. */
a.navbar-brand {
    white-space: normal;
    text-align: center;
    word-break: break-all;
}

/* Lets the logo (and its wrapping badge group) shrink below its content size instead of
   forcing the hamburger/badge/logo row onto two lines at narrow viewports (#260) --
   flex items default to min-width: auto, which ignores max-width on children otherwise. */
.navbar-brand-group,
.navbar-brand-group .navbar-brand {
    min-width: 0;
    flex-shrink: 1;
}

.navbar-brand-group .navbar-brand img {
    max-width: 100%;
    height: auto;
}

/* MB-004 (#304): below md the collapsed navbar's only other content is the hamburger
   toggler, so the brand block's own right edge is the row's right edge -- at narrow phone
   widths (390/375px) the wordmark sat flush against the viewport edge. */
@media (max-width: 767.98px) {
    .navbar-brand-group {
        padding-right: 0.5rem;
    }
}

.box-shadow {
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}

button.accept-policy {
    font-size: 1rem;
    line-height: inherit;
}

.footer {
    bottom: 0;
    width: 100%;
    white-space: nowrap;
}


/* =====================================================
   TYPOGRAPHY
   ===================================================== */

body {
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.app-brand,
.navbar-brand {
    font-family: Garamond, 'Times New Roman', serif;
    font-weight: 600;
}

/* =====================================================
   UNAUTHENTICATED PAGES
   ===================================================== */

/*
  Tabler's .page/.page-center classes (used in _Layout_NoAuth.cshtml) handle the card's
  horizontal centering and max-width, but not full-viewport vertical centering -- that
  normally comes from Tabler's fuller page-wrapper shell, which this app doesn't adopt
  (top-nav only, no sidebar). This rule supplies just that missing piece.
*/
body.unauthenticated-page {
    background-color: var(--color-secondary);
    display: flex;
    min-height: 100vh;
}

body.unauthenticated-page .page.page-center {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* =====================================================
   HEADINGS
   ===================================================== */

h1,
h2,
h3,
h4,
h5,
h6 {
    margin-top: 1rem;
}

/* Spacing for a status badge rendered inline next to a page-header title
   (PageHeaderModel.TitleBadge, _PageHeader.cshtml). */
.page-title .badge {
    margin-left: 0.5rem;
}

/* =====================================================
   MAIN / DESKTOP MENU
   ===================================================== */

.nav-link {
    color: var(--tblr-nav-link-color) !important;
}

/* =====================================================
   SIDEBAR / MENU (IF APPLICABLE)
   ===================================================== */

.app-menu {
    background-color: var(--tblr-secondary-bg);
    color: var(--tblr-body-color);
}

/* =====================================================
   PAGE LAYOUT: STICKY HEADER + FLEX FOOTER PUSH-DOWN
   ===================================================== */

html,
body {
    height: 100%;
    /* Defense-in-depth against any element overflowing the viewport width (missing
       .table-responsive, an unexpectedly wide fixed-width child, etc.) -- #206 finding #3's
       real fix is wrapping every such element individually, but a single overflowing element
       anywhere on the page doesn't just add a scrollbar: on mobile, it drags the browser's
       whole layout viewport wider than the device, which distorts window.innerWidth/innerHeight
       and breaks any position:fixed element's math (confirmed: the shared confirm modal
       rendered outside the visible area on a page with the pre-existing Diagnostics-runs-table
       overflow, once #219 made a modal-opening action reachable on mobile for the first time).
       overflow-x: hidden here clips that overflow at the document level regardless of its
       source, keeping the layout viewport honest -- it does not fix the underlying missing
       .table-responsive (clipped content still isn't reachable without one), only prevents
       that specific unrelated element from breaking positioning everywhere else on the page. */
    overflow-x: hidden;
}

body {
    margin: 0;
}

/*
  Page shell owns layout, not body.
  This is REQUIRED for reliable sticky behavior.
*/
.page-shell {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

/* Sticky header */
header,
.navbar {
    position: sticky;
    top: 0;
    z-index: 1030;
    /* above content, below modals */
}

/*
  The container between header and footer must grow.
*/
.page-shell>.container {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
}

/* Ensure main participates in vertical flow */
.page-shell main {
    flex: 1 0 auto;
}

/* =====================================================
   NAVBAR -- CONTENT ALIGNS WITH PAGE CONTENT WIDTH
   ===================================================== */

/* The navbar element itself has no width constraint, so its background
   already spans the full viewport edge to edge. Its inner content (logo,
   nav links, avatar) uses the same .container as the page content below,
   so they line up vertically instead of the nav content floating at a
   different width/gutter than everything under it. */

/* =====================================================
   TENANT MENU (second nav row, tenant sites only)
   ===================================================== */

/* Row 1's dropdown menu (position: absolute, z-index scoped to its own
   stacking context) must stay above row 2 -- give row 1's stacking context a
   higher z-index than row 2's so it always wins. Row 2 is wrapped in its own
   <header> (for the mobile-collapse toggle), which also matches the generic
   "header, .navbar { z-index: 1030 }" sticky-header rule below and would
   otherwise create an equal-z-index sibling stacking context to row 1's
   <header> that -- being later in the DOM -- paints on top regardless of
   .navbar-tenant-menu's own z-index. Both the wrapper and the inner .navbar
   need the lower z-index, not just the inner one. */
.navbar-tenant-menu-wrapper {
    position: relative;
    z-index: 1020;
}

.navbar-tenant-menu {
    background-color: var(--color-secondary);
    position: relative;
    z-index: 1020;
}

.navbar-tenant-menu .nav-link {
    color: var(--color-primary) !important;
}

/* =====================================================
   ROW 1 NAV ITEM SPACING (Dev Mode / QA Mode badges, user menu)
   ===================================================== */

.navbar .badge.nav-mode-badge {
    font-size: 0.9rem;
    padding: 0.5rem 0.85rem;
    margin: 0 0.125rem;
}

.navbar .nav-user-menu {
    margin-left: 0.5rem;
}

/* Tabler's navbar-nav dropdown-toggle caret defaults to margin-left: auto, meant for a
   full-width accordion-style side-nav row where the caret should hug the row's trailing
   edge regardless of label length. The mobile user-menu row is exactly that shape (a
   full-width .nav-link inside .navbar-nav), so without this override the caret gets pushed
   all the way to the far edge of the screen instead of sitting next to "Hello, Name". */
.nav-user-menu .nav-link.dropdown-toggle::after {
    margin-left: 0.4rem !important;
}

/* Environment badge (#257): deliberately smaller than the Dev/QA mode badges -- it's
   ambient context next to the logo, not a control. */
.navbar .badge.nav-env-badge {
    font-size: 0.7rem;
    padding: 0.3rem 0.5rem;
}

/* =====================================================
   ERROR PAGE STACK TRACE
   ===================================================== */

/* Tabler renders <pre> with a dark background, where the browser's default text-selection
   highlight is nearly invisible. Scoped to the error pages' stack-trace block only -- a
   light blue selection with dark text reads clearly against the dark background. */
.exception-stack-trace::selection {
    background-color: #9ec5fe;
    color: #052c65;
}

/* =====================================================
   MOBILE NAV MENU -- DEV/QA MODE BADGES + USER (below the nav links,
   shown only below the md breakpoint; see the row-1 counterparts
   above, hidden on mobile in favor of these -- both live in
   _Layout.cshtml, kept in sync manually since one is a link-badge and
   the other a profile-link row, not interchangeable markup).
   ===================================================== */

.mobile-nav-mode-badge {
    font-size: 0.9rem;
    padding: 0.5rem 0.85rem;
}

/* A visible stand-in for .dropdown-divider (see _MobileNavBadgesAndUser.cshtml) -- that
   class's border color is a translucent gray tuned to show against a white dropdown-menu
   background, and is nearly invisible against this flyout's pale blue background (even
   Tabler's solid --tblr-border-color is too close in lightness to read clearly here). Use
   the app's own primary brand color at low opacity instead, for real contrast. */
.nav-flyout-divider {
    border-top: 1px solid rgba(var(--color-primary-rgb), 0.25);
}

/* Tabler strips a .dropdown-menu's background/border/shadow and forces both it and its
   .dropdown-item children to color:inherit whenever nested inside a collapsible navbar menu
   (.navbar-expand-md .navbar-collapse .dropdown-menu/.dropdown-item) -- a deliberate "mega
   menu" pattern so an inline nav dropdown flows with the surrounding menu instead of floating
   as its own popup card. Our user-account dropdown isn't a mega menu though -- it should
   always look like a normal floating popup (own white background, own text colors) even when
   nested in the mobile flyout, or its items become unreadable against whatever's behind them.
   Setting concrete values here (not var(--tblr-dropdown-link-color), whose own default is
   itself literally "inherit") is required to actually break out of that inherit chain.
   Selector specificity (4 classes) deliberately exceeds Tabler's 3-class rule so this wins
   regardless of stylesheet load order. */
.navbar-tenant-menu-wrapper .navbar-tenant-menu .nav-user-menu .dropdown-menu {
    background-color: var(--tblr-dropdown-bg);
    color: var(--tblr-body-color);
    border: var(--tblr-dropdown-border-width) solid var(--tblr-dropdown-border-color);
    box-shadow: var(--tblr-dropdown-box-shadow);
    margin-right: 5px;
}

/* The same mega-menu rule also gives .dropdown-item a large calc()-based padding-left (meant
   for indenting nested mega-menu columns) plus display:flex/width:auto -- for our single-level
   menu this just pushes every item wider than the flyout, causing horizontal overflow/scroll.
   Reset back to the normal single-column dropdown-item box model. */
.navbar-tenant-menu-wrapper .navbar-tenant-menu .nav-user-menu .dropdown-item {
    display: block;
    width: 100%;
    min-width: 0;
    padding-left: var(--tblr-dropdown-item-padding-x);
    color: var(--tblr-body-color);
}

/* =====================================================
   NON-INTERACTIVE .btn (e.g. Engagements filter bar's "current
   filter" chip -- styled like a button but not clickable, so it
   shouldn't hover/cursor like one)
   ===================================================== */

.btn-static {
    pointer-events: none;
}

/* =====================================================
   STATUS PAGES (_StatusPage.cshtml -- Error, AccessDenied)
   ===================================================== */

/* Tabler's .empty-icon and .empty-subtitle.text-secondary both color
   themselves via --tblr-secondary, but this app repurposes --tblr-secondary
   (--color-secondary) as a pale background brand color (#c7d6df) for things
   like the tenant nav row and badges -- as icon/text color on white it's
   nearly invisible. Use Tabler's own --tblr-muted (a real muted-text gray,
   not overridden by this app) instead, scoped to just these two so the many
   other things relying on --tblr-secondary as a background aren't touched. */
.empty-icon {
    color: var(--tblr-muted);
}

.empty-subtitle.text-secondary {
    color: var(--tblr-muted) !important;
}

/* Same --tblr-secondary repurposing collision as above, hitting .dropdown-header this time:
   Tabler's own CSS has a later rule that colors .dropdown-header via --tblr-secondary directly
   (not through the --tblr-dropdown-header-color variable), so any dropdown section heading
   (e.g. _NavUserMenu.cshtml's "Dev Mode Tools"/"QA Mode Tools" headers) renders in this app's
   pale brand blue instead of Tabler's intended muted gray -- low-contrast on white, and
   invisible outright against anything already using --tblr-secondary as a background (e.g.
   the mobile nav flyout). Unscoped since this is a global variable collision, not something
   specific to one dropdown. */
.dropdown-header {
    color: var(--tblr-muted);
}

/* =====================================================
   FOOTER VISUAL STYLING
   ===================================================== */

footer {
    background-color: var(--color-slate);
    color: var(--tblr-body-color);
    padding: 0.25rem 0;
    text-align: center;
    flex-shrink: 0;
}

footer>.container>* {
    padding: 0.125rem 0;
    vertical-align: middle;
}

footer img.footer-logo-mark {
    width: 20px;
}

footer a {
    color: var(--tblr-body-color);
    text-decoration: none;
}

footer a:hover {
    text-decoration: underline;
}


/* =====================================================
   CONTENT LINK UNDERLINE (WCAG 1.4.1 -- links distinguishable without relying
   on color alone). Applies to a plain link floating in body text/prose (e.g.
   a card's "View all" isn't one of these, but inline text mentioning a
   related record could be) -- the underline is dropped on hover, not an
   accessibility concern since the resting state already distinguishes the
   link, with the existing color shift to --tblr-link-hover-color as the
   visible hover cue. See #299.

   Overshot on first landing: nav-links, tabs, links-styled-as-buttons,
   Settings side nav, and the dashboard/#301 list-group panels all picked up
   the underline too, despite already being visually distinct as
   nav/actionable-row elements without one (Scott's manual-testing feedback,
   PR #310 follow-up). None of those are "a link inside text" -- they're
   nav-like or sit inside their own bordered row/box, which is exactly the
   shape entity list rows (Organizations/Contacts/Engagements, #204) already
   use `[data-href]` for instead of an `<a>`, and were correctly unaffected by
   the global rule below. The exclusions here bring nav-link/btn/list-group
   links back to that same "no underline, rely on hover row-highlight" look,
   explicitly rather than by accident of markup choice.
   ===================================================== */

a {
    text-decoration: underline;
}

a:hover {
    text-decoration: none;
}

.nav-link,
.btn,
.list-group-item,
.dropdown-item {
    text-decoration: none;
}

/* Icon-only links (e.g. Contact/Organization social-media icons, the user menu's
   "Quick Access" icon row) shouldn't get the underline treatment either -- there's no
   text for it to sit under, so it just draws a stray line beneath the glyph itself
   (Scott's manual-testing feedback, PR #310 follow-up). Matches any anchor whose only
   child element is an icon, regardless of where it appears, rather than requiring every
   call site to opt out individually. Font Awesome's Kit loader replaces every `<i
   class="fa-...">` with an actual `<svg>` at runtime (leaving an HTML comment in the
   `<i>` tag's place) -- `svg:only-child` is what the selector needs to match against the
   real rendered DOM; `i:only-child` alone would only ever match if that JS replacement
   hadn't run yet (or failed), so both are covered. */
a:has(> i:only-child),
a:has(> svg:only-child) {
    text-decoration: none;
}

/* Dashboard panels (#301), the Tags/{tag} usage list (ByTag.cshtml), and any other
   embedded/secondary list using this same list-group-item-action pattern (e.g. the
   Engagements/Contacts lists on an Organization's detail page) read as clickable
   records rather than navigation -- match the entity list tables' `.table-hover` row
   highlight exactly (same rgba values), so hovering a row is an obvious cue on its own
   now that the underline is gone. Matches Tabler's own selector shape
   (`.list-group-item-action:not(.active):hover` in tabler.min.css) rather than the plainer
   `.list-group-item-action:hover` an earlier revision of this rule used -- that plainer
   selector has lower specificity than Tabler's (the `:not(.active)` argument counts toward
   specificity same as a class), so Tabler's own subtler `--tblr-list-group-action-hover-bg`
   won regardless of load order and made this rule silently do nothing. */
.list-group-item-action:not(.active):hover {
    background-color: rgba(var(--color-primary-rgb), 0.06);
}

/* =====================================================
   ICONS
   ===================================================== */

.bi {
    width: 1em;
    height: 1em;
    vertical-align: -.125em;
    fill: currentcolor;
}

/* =====================================================
   NOT IMPLEMENTED BADGE
   ===================================================== */

.not-implemented {
    background-color: magenta;
    color: orange;
    font-weight: bold;
    padding: 6px 12px;
    border-radius: 4px;
    text-decoration: none;
    display: inline-block;
}

.not-implemented:hover {
    color: yellow;
    text-decoration: none;
}

/* =====================================================
   TABLES
   ===================================================== */

/* Organizations list Industry column (#304, DT-008): Tabler's `.card-table` component
   colors all cell text in the link color by default -- correct for the Name cell (the
   row's real data-href nav target) but backwards for Industry, a plain non-interactive
   value that shouldn't look clickable. Explicit override back to a plain muted color. */
.org-industry-cell {
    color: var(--tblr-muted) !important;
}

.table-sticky-header thead th {
    position: sticky;
    /* Offset below the sticky site header (nav + tenant stripe), whose combined
       height varies with viewport width -- kept in sync by ui-handlers.js. */
    top: var(--sticky-header-height, 0px);
    z-index: 5;
    background-color: var(--tblr-table-bg, #fff);
}

/* Sortable column headers (_SortableColumnHeader.cshtml): sortability is communicated
   only by the caret icon, never by the header text looking different from a plain,
   non-sortable <th> in the same row -- matches Tabler's own sortable-table pattern. */
.table-sort-link {
    color: inherit;
    text-decoration: none;
    /* #298 (MB-003): the link's clickable box was just the text's own line-height (well
       under the 24px CSS px tap-target minimum) -- display:inline-block lets vertical
       padding actually grow the hit area instead of being absorbed by line-height. */
    display: inline-block;
    padding: 5px 0;
}

.table-sort-link:hover,
.table-sort-link:focus {
    color: var(--tblr-primary);
    text-decoration: underline;
}

.table-sort-icon {
    margin-left: 0.25rem;
    font-size: 0.75em;
    opacity: 0.35;
}

.table-sort-icon-active {
    opacity: 1;
}

/* Tag-chip remove button (_Badge.cshtml's BadgeAction, rendered as .btn-close): inheriting
   a badge's small font-size shrinks Bootstrap's 1em-relative default well under the 24px
   CSS px tap-target minimum (#298, MB-001). Fixed px dimensions size the hit area
   correctly regardless of the badge's font-size context; background-size keeps the visible
   glyph itself small so the button doesn't look oversized next to the badge text. */
.badge .btn-close {
    width: 24px;
    height: 24px;
    padding: 0;
    background-size: 10px;
}

/* Clickable table rows (data-href, wired in ui-handlers.js, #213). Cursor styling lives
   here rather than a per-element style.cursor assignment in JS, since rows swapped in by
   htmx after the initial page load need it too. */
[data-href] {
    cursor: pointer;
}

[data-href]:focus-visible {
    outline: 2px solid var(--tblr-primary);
    outline-offset: -2px;
}

/* =====================================================
   MISC DEV MODE STYLES
   ===================================================== */

.color-swatches {
    border: 0.5px solid var(--color-primary);
    background-image: linear-gradient(45deg, #ddd 10%, #eee 10%, #eee 50%, #ddd 50%, #ddd 60%, #eee 60%, #eee);
    background-size: 25px 25px;
}

.color-swatches div {
    border: 0.5px solid var(--color-primary);
    font-size: 0.7rem;
}

/* =====================================================
   BREADCRUMB ICONS (_PageHeader.cshtml)
   ===================================================== */

.breadcrumb-item i {
    margin-right: 0.25rem;
}

/* Breadcrumb links are the one nav-shaped element that DOES want the #299
   underline/remove-on-hover treatment (Scott's manual-testing feedback, PR
   #310 follow-up) -- unlike .nav-link/.btn/.list-group-item above, a
   breadcrumb trail reads as inline text, not an actionable row. Tabler's own
   `.breadcrumb-item a:hover` rule (same 0-2-1 specificity) keeps the
   underline on hover otherwise; this must match that specificity and come
   after it in load order (site.css loads last) to actually win. */
.breadcrumb-item a:hover {
    text-decoration: none;
}

.breadcrumb-icon-img {
    height: 0.875rem;
    width: auto;
    vertical-align: -1px;
}

/* =====================================================
   PHONE/SOCIAL REORDER DRAG-AND-DROP (#228)
   ===================================================== */

.reorder-item.reorder-dragging {
    opacity: 0.4;
}

.reorder-item.reorder-drag-over {
    border-top: 2px solid var(--tblr-primary);
}

.reorder-handle {
    cursor: grab;
    /* Touch dragging is scoped to just this handle (see phone-social-rows.js /
       entity-reorder.js) -- touch-action: none only needs to apply here, not to the whole
       row, so normal page scroll and form-control taps elsewhere in the row are untouched. */
    touch-action: none;
}

/* =====================================================
   SETTINGS-AREA SIDE NAV GROUP HEADINGS
   ===================================================== */

/* Our settings nav uses a transparent list-group (not the Tabler demo's boxed variant), so
   Tabler's default .list-group-header surface background + bottom border read as a stray
   bar here -- keep just the small uppercase muted label. */
.list-group-transparent .list-group-header {
    background: transparent;
    border-bottom: 0;
}

/* =====================================================
   SHARED CONFIRM MODAL
   ===================================================== */

/* #315: showConfirm() (ui-handlers.js) sets this via .textContent, so \n\n between
   paragraphs in a data-confirm message does nothing without pre-line -- the browser default
   (normal) collapses newlines. No other data-confirm message embeds \n today, so this is
   additive: every other confirm dialog renders identically before and after. */
#uiConfirmMessage {
    white-space: pre-line;
}
/* =====================================================
   AVATAR CROP MODAL
   ===================================================== */

/* #319 follow-up: the avatar is stored as a 512x512 square but rendered as a circle
   everywhere it appears (nav, profile header), so a square crop box misrepresents the
   result -- the corners it shows are corners the user never sees. Rounding Cropper's
   selection overlay makes the preview match what actually gets displayed. Purely visual:
   getCroppedCanvas() still exports the full square, so nothing about the stored image
   changes.

   Scoped to #avatarCropModal rather than applied to .cropper-* globally, so any future
   Cropper elsewhere in the app (a non-circular image, say) is unaffected. .cropper-face is
   the draggable fill and .cropper-view-box the outlined window; both need it or the circle
   shows a square edge on one of the two. */
#avatarCropModal .cropper-view-box,
#avatarCropModal .cropper-face {
    border-radius: 50%;
}
