/* =============================================================================
   IC component primitives — additive layer over ic-theme-base.css.
   Phoenix already styles .btn / .card / .badge / .alert / .form-control /
   .table / .modal / .offcanvas. This file only adds ic-* primitives the
   legacy views rely on: ic-chip, ic-dot, ic-stat-lines, ic-page-header,
   ic-gloss-card, ic-glow-ring, ic-card-hover-glow, ic-btn-glow, ic-mono.
   ============================================================================= */

/* ---------- button sizing token overrides -------------------------------- */
/* Phoenix's .btn / .btn-lg / .btn-sm redefine button tokens at their own
   scope, which beats our :root values.  Rebind at those scopes so the tokens
   flow through to font-size / font-weight. */
.btn {
  --ic-btn-font-weight: 500;
}
.btn-lg,
.btn-group-lg > .btn {
  --ic-btn-font-size: 0.85rem;
  --ic-btn-font-weight: 500;
}
.btn-sm,
.btn-group-sm > .btn {
  --ic-btn-font-size: 0.75rem;
  --ic-btn-font-weight: 500;
}

/* ---------- page header --------------------------------------------------- */
.ic-page-header {
  padding-bottom: 0.75rem;
}
.ic-page-header h1,
.ic-page-header .ic-title {
  margin-top: 1rem;
  margin-bottom: 0.25rem;
}
.ic-page-header p {
  font-size: 13px;
  margin-bottom: 1.5rem;
}
.ic-title {
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* ---------- chip + dot (used in headers) --------------------------------- */
.ic-chip {
  display: inline-flex;
  align-items: center;
  background: color-mix(in srgb, var(--ic-primary) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic-primary) 25%, transparent);
  color: var(--ic-body-color, var(--bs-body-color));
  border-radius: var(--bs-border-radius-pill, 999px);
  padding: 0.35rem 0.75rem;
}
.ic-dot {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ic-neon);
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--ic-neon) 22%, transparent),
    0 0 12px var(--ic-neon);
}

/* ---------- ic-tile (subtle purple-washed chip/tile) --------------------
   Used inside cards for metric pills, progress rows, rules summaries — any
   small inset surface that needs to read as grouped content without a heavy
   border. Replaces the legacy inline `background: rgba(var(--ic-
   primary-rgb), .04)` pattern that appears across vendor / catalog / image
   cards. */
.ic-tile {
  background: color-mix(in srgb, var(--ic-purple) 4%, transparent);
  border-radius: 0.5rem;
}

/* ---------- Tom Select theming -----------------------------------------
   Align the Tom Select bootstrap5 skin with our purple-on-dark palette so
   upgraded <select>s feel like native IC form elements. */
.ts-wrapper.form-select {
  padding: 0;
  height: auto;
  min-height: calc(3.5rem + 2px);
}
.ts-wrapper .ts-control {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding: 1rem 0.75rem !important;
  color: var(--ic-body-color, var(--bs-body-color)) !important;
  min-height: calc(3.5rem + 2px);
}
.ts-wrapper.multi .ts-control > div {
  background: color-mix(in srgb, var(--ic-purple) 22%, transparent) !important;
  color:      color-mix(in srgb, var(--ic-purple) 70%, #fff) !important;
  border: 1px solid color-mix(in srgb, var(--ic-purple) 32%, transparent) !important;
  border-radius: 0.4rem !important;
  font-weight: 500;
}
.ts-wrapper .ts-control > input {
  color: var(--ic-purple) !important;
  caret-color: var(--ic-purple);
}
.ts-wrapper .ts-control > input::placeholder {
  color: color-mix(in srgb, var(--ic-body-color, var(--bs-body-color)) 45%, transparent);
}
.ts-dropdown {
  background: var(--ic-body-bg, var(--bs-body-bg)) !important;
  border: 1px solid var(--ic-border-color, var(--bs-border-color)) !important;
  box-shadow: 0 12px 28px rgba(0,0,0,.35), 0 0 0 1px color-mix(in srgb, var(--ic-purple) 12%, transparent) !important;
  color: var(--ic-body-color, var(--bs-body-color)) !important;
}
.ts-dropdown .option {
  color: var(--ic-body-color, var(--bs-body-color)) !important;
}
.ts-dropdown [data-selectable].option {
  font-size: 13px;
}
.ts-dropdown .option.active,
.ts-dropdown .active {
  background: color-mix(in srgb, var(--ic-purple) 22%, transparent) !important;
  color:      var(--ic-purple) !important;
}
.ts-dropdown .option:hover {
  background: color-mix(in srgb, var(--ic-purple) 14%, transparent) !important;
}
.ts-dropdown .option.selected {
  background: color-mix(in srgb, var(--ic-purple) 18%, transparent) !important;
  color:      var(--ic-purple) !important;
}

/* ---------- ic-badge-pair (two-half pill: label + value) ----------------
   Rendered as one rounded pill split into a muted "label" half on the left
   and a colored "value" half on the right. Reusable for things like
   "Vendor · Foundry Lighting", "Catalog · Test 3", "Status · Draft".

   Variants: add a hue modifier (.ic-badge-pair--purple, --info, --success,
   --warning, --danger) to tint the value half. Default is purple.

   Usage:
     <span class="ic-badge-pair">
         <span class="ic-badge-pair__label">Vendor</span>
         <span class="ic-badge-pair__value">Foundry Lighting</span>
     </span>
-------------------------------------------------------------------------- */
.ic-badge-pair {
  --ic-pair-hue: var(--ic-purple);
  display: inline-flex;
  align-items: stretch;
  border-radius: 0.4rem;
  overflow: hidden;
  font-size: 0.72rem;
  line-height: 1;
  border: 1px solid color-mix(in srgb, var(--ic-pair-hue) 22%, transparent);
  max-width: 100%;
}
.ic-badge-pair__label,
.ic-badge-pair__value {
  padding: 0.35rem 0.6rem;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  min-width: 0;
}
.ic-badge-pair__label {
  background: color-mix(in srgb, var(--ic-body-color, var(--bs-body-color)) 6%, transparent);
  color: color-mix(in srgb, var(--ic-body-color, var(--bs-body-color)) 55%, transparent);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  font-size: 0.62rem;
  border-right: 1px solid color-mix(in srgb, var(--ic-pair-hue) 18%, transparent);
}
.ic-badge-pair__value {
  background: color-mix(in srgb, var(--ic-pair-hue) 12%, transparent);
  color: color-mix(in srgb, var(--ic-pair-hue) 75%, #fff);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  /* Allow long values to wrap onto multiple lines instead of being clipped
     with an ellipsis. Overrides the shared `white-space: nowrap` above so
     the value half breaks naturally on word boundaries (and on long tokens
     like filenames via overflow-wrap). */
  white-space: normal;
  overflow-wrap: anywhere;
}
/* Hue variants */
.ic-badge-pair--info    { --ic-pair-hue: var(--ic-info);    }
.ic-badge-pair--success { --ic-pair-hue: var(--ic-success); }
.ic-badge-pair--warning { --ic-pair-hue: var(--ic-warning); }
.ic-badge-pair--danger  { --ic-pair-hue: var(--ic-danger);  }
.ic-badge-pair--neon    { --ic-pair-hue: var(--ic-neon);    }

/* ---------- ic-avatar-initials -------------------------------------------
   Used everywhere Bootstrap's `.avatar` + `.avatar-name` renders initials
   (catalogs, vendors, resellers, users, ftp). The Bootstrap default
   (bg-primary-subtle + text-primary-emphasis) reads as flat purple-on-purple
   in dark mode — looks like a placeholder, not a brand surface.

   This treatment overrides the Bootstrap utility background/color on the
   same element (specificity wins via `.avatar .ic-avatar-initials`). The
   surface is a soft Phoenix-purple gradient with an inset highlight on the
   top edge for that "lit from above" depth, plus a subtle outer ring.
   `GetInitials` is now capped at 2 letters so the data-length sizing only
   needs to handle 1 and 2 — kept the larger fallback rules for safety in
   case any callsite still passes longer strings.
-------------------------------------------------------------------------- */
.avatar .ic-avatar-initials {
  /* Neutral dark surface with just a hint of purple in the upper-left
     highlight. Reads as a refined card, not a brand badge. */
  background:
    radial-gradient(130% 130% at 28% 18%,
      color-mix(in srgb, var(--ic-body-bg, #0b0b1a) 60%, var(--ic-purple) 18%) 0%,
      color-mix(in srgb, var(--ic-body-bg, #0b0b1a) 78%, #000000 12%) 60%,
      color-mix(in srgb, var(--ic-body-bg, #0b0b1a) 88%, #000000 20%) 100%);
  color: #ffffff;
  font-family: var(--ic-font-sans-serif, var(--bs-body-font-family));
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  border: 1px solid color-mix(in srgb, #ffffff 10%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #ffffff 14%, transparent),
    inset 0 -10px 18px color-mix(in srgb, #000000 22%, transparent),
    0 4px 10px rgba(0, 0, 0, 0.25);
}
/* Length-aware sizing — capped at 2 letters by GetInitials, but the 3+
   rules stay as a safety net for any legacy callsite still passing more. */
.avatar .ic-avatar-initials[data-length="1"] { font-size: 1.25rem; }
.avatar .ic-avatar-initials[data-length="2"] { font-size: 1.05rem; }
.avatar .ic-avatar-initials[data-length="3"] { font-size: 0.85rem; letter-spacing: 0.02em; }
.avatar .ic-avatar-initials[data-length="4"] { font-size: 0.72rem; letter-spacing: 0.01em; }
.avatar .ic-avatar-initials[data-length="5"],
.avatar .ic-avatar-initials[data-length="6"],
.avatar .ic-avatar-initials[data-length="7"],
.avatar .ic-avatar-initials[data-length="8"] { font-size: 0.6rem; letter-spacing: 0; }

/* Truncate modifier — lets the pill shrink below its content's intrinsic
   width when space is tight (e.g. long filenames on mobile). Without this
   the default flex `min-width: auto` pins the pill at full content width
   and `__value`'s ellipsis never activates. Opt-in so other usages keep
   their natural sizing. */
.ic-badge-pair--truncate               { min-width: 0; }
.ic-badge-pair--truncate .ic-badge-pair__label,
.ic-badge-pair--truncate .ic-badge-pair__value { min-width: 0; }

/* ---------- ic-catalog-chip (icon badge for catalog list rows) ----------
   Small rounded-square badge holding a catalog icon, purple-tinted. Sits in
   list rows (assigned-catalogs list, recent-catalog cards, etc.) alongside
   the catalog name + vendor line. */
.ic-catalog-chip,
.ic-reseller-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 0.6rem;
  background: color-mix(in srgb, var(--ic-purple) 12%, transparent);
  color: color-mix(in srgb, var(--ic-purple) 70%, #fff);
  border: 1px solid color-mix(in srgb, var(--ic-purple) 22%, transparent);
  font-size: 1rem;
}
/* Reseller chip leans slightly cyan to visually differentiate from catalog. */
.ic-reseller-chip {
  background: color-mix(in srgb, var(--ic-neon) 10%, transparent);
  color: color-mix(in srgb, var(--ic-neon) 70%, #fff);
  border-color: color-mix(in srgb, var(--ic-neon) 22%, transparent);
}

/* ---------- ic-activity-log__action (oversized badge for log table) -----
   The activity-log table uses fs-9 which squashes .ic-badge below legibility.
   This variant bumps the action badge to a readable size while inheriting
   the color from its ic-badge-{variant} sibling class. */
.ic-activity-log__action {
  font-size: 0.7rem;
  padding: 0.3rem 0.65rem;
  letter-spacing: 0.02em;
  line-height: 1.1;
}

/* ---------- ic-mono (monospace inline) ------------------------------------ */
.ic-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
}

/* Override Phoenix's default .text-primary-emphasis tint */
.text-primary-emphasis {
  color: #46577e !important;
}
.bg-primary-subtle {
  background-color: #292e3c !important;
}

/* Search input left-padding fix: Phoenix reserves room for a search icon.
   When the icon is hidden, reclaim that padding so the placeholder aligns. */
.search-box .search-input,
input.search-input {
  /* padding-left: 0.75rem !important; */
}
.search-box .search-input + .search-box-icon:not(.d-none) ~ .search-input,
.search-box:has(.search-box-icon:not(.d-none)) .search-input {
  padding-left: 2rem !important;
}

/* Filter form alignment — keep the text inside every .form-floating input
   and select flush with its label (both at 0.75rem from the left). Webkit's
   default search appearance can shift the first character right, so zero it
   out explicitly. */
.js-ic-filters .form-floating > .form-control,
.js-ic-filters .form-floating > .form-select {
  /* padding-left: .75rem !important; */
}

.js-ic-filters .form-floating > input[type="search"]::-webkit-search-decoration,
.js-ic-filters
  .form-floating
  > input[type="search"]::-webkit-search-cancel-button,
.js-ic-filters
  .form-floating
  > input[type="search"]::-webkit-search-results-button,
.js-ic-filters
  .form-floating
  > input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none;
  appearance: none;
}

/* Data table headers — make every .table thead row read as a clear header
   band: body-color text, bold weight, a touch more padding, and a subtle
   bottom rule. The common .text-body-secondary small on each th muted the
   columns; we override those here so the header always feels prominent. */
.table > thead > tr > th {
  color: var(--ic-body-color, var(--bs-body-color)) !important;
  font-weight: 600;
  letter-spacing: 0.04em;
  background: color-mix(in srgb, var(--ic-purple) 5%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--ic-purple) 22%, transparent);
  padding-top: 0.65rem;
  padding-bottom: 0.65rem;
}

/* Vertical column separators — every th/td gets a right border so columns
   read as discrete cells. The last cell in each row drops the border. */
.table > thead > tr > th,
.table > tbody > tr > td {
  border-right: 1px solid color-mix(in srgb, var(--ic-purple) 12%, var(--ic-border-color, var(--bs-border-color)));
  padding-left:  0.9rem;
  padding-right: 0.9rem;
}
.table > thead > tr > th:last-child,
.table > tbody > tr > td:last-child {
  border-right: 0;
}

/* Table row hover — subtle purple wash for tables marked .table-hover so
   the interaction matches the .ic-stat-lines hover treatment. */
.table-hover > tbody > tr {
  transition: background 140ms var(--ic-easing, ease);
  cursor: default;
}
.table-hover > tbody > tr:hover > * {
  --bs-table-bg-state: transparent;
  background: color-mix(in srgb, var(--ic-purple) 8%, transparent) !important;
  box-shadow: inset 0 0 0 1px
    color-mix(in srgb, var(--ic-purple) 14%, transparent);
}

/* Selected row — set when a user clicks the row (JS handler in
   ic-forms.js). Stronger purple wash + ring + purple top/bottom rails so
   the selected row stays visible after the hover tint fades. Selection is
   single-row per table. */
.table-hover > tbody > tr.is-selected > * {
  --bs-table-bg-state: transparent;
  background: color-mix(in srgb, var(--ic-purple) 20%, transparent) !important;
  box-shadow: inset 0 0 0 1px
    color-mix(in srgb, var(--ic-purple) 36%, transparent);
  color: color-mix(in srgb, var(--ic-purple) 70%, #fff);
}
.table-hover > tbody > tr.is-selected:hover > * {
  background: color-mix(in srgb, var(--ic-purple) 26%, transparent) !important;
}

/* Mirror scrollbar rendered above a `.table-responsive.ic-scroll-top`, kept
   in sync with the table's own scroll by ic-forms.js. Lets the user drag
   the horizontal scrollbar without scrolling to the bottom of a tall
   table. */
.ic-table-top-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  /* Stick just below the topbar so it's always reachable while scrolling. */
  position: sticky;
  top: var(--ic-topbar-h, 4rem);
  z-index: 3;
  background: var(--ic-body-bg, var(--bs-body-bg));
}
.ic-table-top-scroll__inner {
  height: 1px;
  /* width set to table.scrollWidth by JS */
}


/* Column-label overlay — on hover, each cell reveals its column header in a
   tiny light-weight label at the top-left so the reader never loses column
   context. The label is driven by data-label attributes set in JS
   (ic-forms.js on DOM ready) from the table's thead th text. */
.table-hover > tbody > tr > td {
  position: relative;
  padding-top: 0.9rem;
}
.table-hover > tbody > tr > td[data-label]::before {
  content: attr(data-label);
  position: absolute;
  top: 2px;
  left: 0.5rem;
  font-size: 0.58rem;
  font-weight: 300;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ic-body-color, var(--bs-body-color)) 40%, transparent);
  pointer-events: none;
  opacity: 0;
  transition: opacity 140ms var(--ic-easing, ease);
}
.table-hover > tbody > tr:hover > td[data-label]::before {
  opacity: 1;
}

/* ---------- stat lines ---------------------------------------------------- */
/* ---------- select options + dropdown menu --------------------------------
   Hover / active tint mirrors the sidebar link treatment (purple 14%
   hover, purple 22% active with the purple text color) so every menu-like
   surface reads as the same interaction. */
select.form-select option,
select.form-control option {
  background-color: var(--ic-body-bg, var(--bs-body-bg));
  color: var(--ic-body-color, var(--bs-body-color));
}
select.form-select option:hover,
select.form-control option:hover {
  background-color: color-mix(
    in srgb,
    var(--ic-purple) 22%,
    var(--ic-body-bg, var(--bs-body-bg))
  ) !important;
  color: var(--ic-purple) !important;
}
select.form-select option:checked,
select.form-control option:checked {
  background-color: color-mix(
    in srgb,
    var(--ic-purple) 22%,
    var(--ic-body-bg, var(--bs-body-bg))
  ) !important;
  color: var(--ic-purple) !important;
  font-weight: 600;
}

/* Bootstrap/Phoenix .dropdown-menu items — match the sidebar hover exactly. */
.dropdown-item:hover,
.dropdown-item:focus {
  background-color: color-mix(
    in srgb,
    var(--ic-purple) 22%,
    transparent
  ) !important;
  color: var(--ic-purple) !important;
}
.dropdown-item.active,
.dropdown-item:active {
  background-color: color-mix(
    in srgb,
    var(--ic-purple) 22%,
    transparent
  ) !important;
  color: var(--ic-purple) !important;
  font-weight: 600;
}

.ic-stat-lines {
  display: grid;
  gap: 0.25rem;
}
.ic-stat-lines > div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.4rem 0.5rem;
  border-radius: 0.5rem;
  border-bottom: 1px dashed var(--ic-border-color, rgba(255, 255, 255, 0.08));
  transition:
    background 140ms var(--ic-easing, ease),
    box-shadow 140ms var(--ic-easing, ease);
}
.ic-stat-lines > div:hover {
  background: color-mix(in srgb, var(--ic-purple) 8%, transparent);
  box-shadow: inset 0 0 0 1px
    color-mix(in srgb, var(--ic-purple) 18%, transparent);
  border-bottom-color: transparent;
}
.ic-stat-lines > div:last-child {
  border-bottom: 0;
}
.ic-stat-line-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(
    --ic-text-tertiary,
    var(--ic-secondary-color, var(--bs-secondary-color))
  );
  min-width: 5rem;
}

/* ---------- glossy / glow-ring cards -------------------------------------- */
.ic-glow-ring {
  box-shadow:
    var(--ic-glow-ring), var(--bs-box-shadow, 0 8px 24px rgba(0, 0, 0, 0.15));
}
/* Gloss card — soft pastel wash, very light sheen. No hard border or glow.
   The tinted variants shift the whole surface toward a pastel of the hue. */
.ic-gloss-card {
  position: relative;
  overflow: hidden;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.02) 0%,
    rgba(255, 255, 255, 0) 100%
  );
}
.ic-gloss-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 45%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), transparent);
  pointer-events: none;
  z-index: 0;
  opacity: 0.7;
}
.ic-gloss-card::after {
  content: none;
}
.ic-gloss-card > * {
  position: relative;
  z-index: 1;
}

/* Ultra-transparent glass variants — thin hue border, barely-there fill,
   no heavy shadow; the body bg shows through almost fully. */
.ic-gloss-card--info,
.ic-gloss-card--success,
.ic-gloss-card--warning,
.ic-gloss-card--danger {
  background: transparent;
  border-radius: inherit;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: none;
}
.ic-gloss-card--info {
  --ic-glow: var(--ic-info);
  background-color: color-mix(in srgb, var(--ic-info) 4%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic-info) 32%, transparent);
}
.ic-gloss-card--success {
  --ic-glow: var(--ic-success);
  background-color: color-mix(in srgb, var(--ic-success) 4%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic-success) 32%, transparent);
}
.ic-gloss-card--warning {
  --ic-glow: var(--ic-warning);
  background-color: color-mix(in srgb, var(--ic-warning) 4%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic-warning) 32%, transparent);
}
.ic-gloss-card--danger {
  --ic-glow: var(--ic-danger);
  background-color: color-mix(in srgb, var(--ic-danger) 4%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic-danger) 32%, transparent);
}

.ic-card-hover-glow {
  transition:
    transform var(--ic-motion) var(--ic-easing),
    box-shadow var(--ic-motion) var(--ic-easing),
    border-color var(--ic-motion) var(--ic-easing);
  border: 1px solid color-mix(in srgb, var(--ic-glow) 16%, transparent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ic-glow) 10%, transparent),
    0 6px 18px color-mix(in srgb, var(--ic-glow) 10%, transparent);
}
.ic-card-hover-glow:hover {
  border-color: color-mix(in srgb, var(--ic-glow) 38%, transparent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ic-glow) 22%, transparent),
    0 14px 34px color-mix(in srgb, var(--ic-glow) 18%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* When .ic-card-hover-glow wraps a hue variant (or is itself one), rebind
   --ic-glow at the glow element so its border/shadow layers tint correctly.
   Covers both same-element composition and parent-containing-child markup. */
.ic-card-hover-glow.ic-gloss-card--info,
.ic-card-hover-glow:has(.ic-gloss-card--info),
.ic-card-hover-glow:has(.alert-subtle-info),
.ic-card-hover-glow:has(.ic-alert-info) {
  --ic-glow: var(--ic-info);
}
.ic-card-hover-glow.ic-gloss-card--success,
.ic-card-hover-glow:has(.ic-gloss-card--success),
.ic-card-hover-glow:has(.alert-subtle-success),
.ic-card-hover-glow:has(.ic-alert-success) {
  --ic-glow: var(--ic-success);
}
.ic-card-hover-glow.ic-gloss-card--warning,
.ic-card-hover-glow:has(.ic-gloss-card--warning),
.ic-card-hover-glow:has(.alert-subtle-warning),
.ic-card-hover-glow:has(.ic-alert-warning) {
  --ic-glow: var(--ic-warning);
}
.ic-card-hover-glow.ic-gloss-card--danger,
.ic-card-hover-glow:has(.ic-gloss-card--danger),
.ic-card-hover-glow:has(.alert-subtle-danger),
.ic-card-hover-glow:has(.ic-alert-danger) {
  --ic-glow: var(--ic-danger);
}

/* ---------- button glow adornments (kept subtle) -------------------------- */
.ic-btn-glow {
  box-shadow: var(--ic-glow-ring);
}
.ic-btn-soft {
  background: color-mix(
    in srgb,
    var(--ic-body-color, var(--bs-body-color)) 5%,
    transparent
  ) !important;
  border-color: var(--ic-border-color, var(--bs-border-color)) !important;
  color: var(--ic-body-color, var(--bs-body-color)) !important;
}
.ic-btn-primary-glow {
  box-shadow: 0 4px 14px color-mix(in srgb, var(--ic-primary) 18%, transparent);
}

/* Tame the default Phoenix hover lift — same direction, less intensity */
.btn-subtle-primary:hover,
.btn-primary:hover {
  box-shadow: 0 3px 10px color-mix(in srgb, var(--ic-primary) 16%, transparent);
}
/* btn-subtle-secondary — faint purple tint to match the filter hero bg. */
.btn-subtle-secondary,
.btn-subtle-secondary:visited {
  background-color: color-mix(
    in srgb,
    var(--ic-purple) 10%,
    transparent
  ) !important;
  border-color: color-mix(
    in srgb,
    var(--ic-purple) 18%,
    transparent
  ) !important;
  color: color-mix(in srgb, var(--ic-purple) 75%, #000) !important;
}
.btn-subtle-secondary:hover,
.btn-subtle-secondary:focus {
  background-color: color-mix(
    in srgb,
    var(--ic-purple) 18%,
    transparent
  ) !important;
  border-color: color-mix(
    in srgb,
    var(--ic-purple) 32%,
    transparent
  ) !important;
  color: var(--ic-purple) !important;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ic-purple) 16%, transparent);
}

/* btn-subtle-primary text override — the Phoenix default reads too washed.
   Tint the surface a bit stronger and use the solid primary color for the
   label so contrast is clear on both light and dark backgrounds. */
.btn-subtle-primary,
.btn-subtle-primary:visited {
  background-color: color-mix(
    in srgb,
    var(--ic-primary) 14%,
    transparent
  ) !important;
  border-color: color-mix(
    in srgb,
    var(--ic-primary) 26%,
    transparent
  ) !important;
  color: var(--ic-primary) !important;
}
.btn-subtle-primary:hover,
.btn-subtle-primary:focus {
  background-color: color-mix(
    in srgb,
    var(--ic-primary) 22%,
    transparent
  ) !important;
  border-color: color-mix(
    in srgb,
    var(--ic-primary) 45%,
    transparent
  ) !important;
  color: var(--ic-primary) !important;
}
[data-bs-theme="dark"] .btn-subtle-primary,
[data-bs-theme="dark"] .btn-subtle-primary:visited {
  color: color-mix(in srgb, var(--ic-primary) 60%, #ffffff 40%) !important;
}
[data-bs-theme="dark"] .btn-subtle-primary:hover,
[data-bs-theme="dark"] .btn-subtle-primary:focus {
  color: #ffffff !important;
}

/* btn-ic-primary — solid purple CTA aligned with the app's theme.
   Use on prominent actions (auth submits, key confirmations). */
.btn-ic-primary,
.btn-ic-primary:visited {
  position: relative;
  isolation: isolate;
  background: color-mix(in srgb, var(--ic-purple) 6%, transparent) !important;
  border: 1px solid color-mix(in srgb, var(--ic-purple) 45%, transparent) !important;
  color: var(--ic-purple) !important;
  letter-spacing: 0.01em;
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  backdrop-filter: blur(14px) saturate(180%);
  box-shadow: none;
  transition:
    background 180ms var(--ic-easing, ease),
    border-color 180ms var(--ic-easing, ease),
    color 180ms var(--ic-easing, ease);
}

.btn-ic-primary:hover,
.btn-ic-primary:focus {
  background: color-mix(in srgb, var(--ic-purple) 12%, transparent) !important;
  border-color: color-mix(
    in srgb,
    var(--ic-purple) 65%,
    transparent
  ) !important;
  color: color-mix(in srgb, var(--ic-purple) 70%, #fff) !important;
  box-shadow: none;
}
.btn-ic-primary:active {
  background: color-mix(in srgb, var(--ic-purple) 18%, transparent) !important;
}
.btn-ic-primary:disabled,
.btn-ic-primary.disabled {
  opacity: 0.55;
  box-shadow: none;
}

/* ---------- ic-hero: pastel filter card (warm neutral, not blue) --------- */
.ic-hero {
  background: linear-gradient(
    180deg,
    color-mix(
        in srgb,
        var(--ic-purple) 7%,
        var(--ic-body-bg, var(--bs-body-bg))
      )
      0%,
    color-mix(
        in srgb,
        var(--ic-purple) 2%,
        var(--ic-body-bg, var(--bs-body-bg))
      )
      100%
  );
  border: 1px solid color-mix(in srgb, var(--ic-purple) 14%, transparent);
  border-radius: 1rem;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
}
.ic-hero::before,
.ic-hero::after {
  content: none;
}

/* ic-glow-ring on a filter/hero card is gentle and matches the purple tint */
.ic-hero.ic-glow-ring {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ic-purple) 18%, transparent),
    0 4px 14px color-mix(in srgb, var(--ic-purple) 10%, transparent);
}

/* ---------- filter card always margined from surrounding content --------- */
.js-ic-filters {
  margin-top: 1rem;
  margin-bottom: 1rem;
  display: block;
}
.js-ic-filters > .card {
  margin: 0 !important;
}
.js-ic-filters + * {
  margin-top: 1rem;
}
* + .js-ic-filters {
  margin-top: 1rem;
}

/* ---------- alert gets a gentle colored aura ----------------------------- */
.alert-subtle-info,
.ic-alert-info {
  --ic-glow: var(--ic-info);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ic-info) 10%, transparent);
}
.alert-subtle-success,
.ic-alert-success {
  --ic-glow: var(--ic-success);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ic-success) 10%, transparent);
}
.alert-subtle-warning,
.ic-alert-warning {
  --ic-glow: var(--ic-warning);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ic-warning) 12%, transparent);
}
.alert-subtle-danger,
.ic-alert-danger {
  --ic-glow: var(--ic-danger);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ic-danger) 12%, transparent);
}

/* Hue-tinted subtle buttons — rebind --ic-glow so .ic-card-hover-glow or any
   composed glow utility picks up the button's own color. */
.btn-subtle-info,
.ic-btn-info {
  --ic-glow: var(--ic-info);
}
.btn-subtle-success,
.ic-btn-success {
  --ic-glow: var(--ic-success);
}
.btn-subtle-warning,
.ic-btn-warning {
  --ic-glow: var(--ic-warning);
}
.btn-subtle-danger,
.ic-btn-danger {
  --ic-glow: var(--ic-danger);
}

/* ---------- modal box-shadow border — subtle neon halo, not full bloom -----
   Applies to every Bootstrap modal in the app (alert popup, leave-confirm,
   any future themed modal). The 1px inset glow doubles as a border so we
   don't have to maintain a separate border rule per modal type. --ic-glow
   defaults to var(--ic-neon) but variant modifiers (e.g. text-warning on the
   header) can shift the hue without touching this rule. */
.modal-content {
  /* Phoenix's default --ic-modal-border-radius is 0.375rem (6px), which
     reads as square next to the app's 8-12px card/drawer radii. Bump to
     0.75rem so modals feel like they belong in the same family as the
     surrounding UI, and override the inner-border-radius the same way so
     the header/footer corners don't look clipped. */
  --ic-modal-border-radius: 0.75rem;
  --ic-modal-inner-border-radius: calc(0.75rem - var(--ic-border-width));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ic-glow) 25%, transparent),
    0 0 18px color-mix(in srgb, var(--ic-glow) 18%, transparent),
    0 16px 40px rgba(0, 0, 0, 0.35);
}

/* =============================================================================
   Topbar activity feed — bell dropdown in nav-top, timeline-style list.
   ============================================================================= */
.ic-topbar-activity-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  color: var(--ic-body-color, var(--bs-body-color));
  transition: background-color var(--ic-motion) var(--ic-easing),
              box-shadow var(--ic-motion) var(--ic-easing);
}
.ic-topbar-activity-toggle:hover,
.ic-topbar-activity-toggle:focus-visible {
  background: color-mix(in srgb, var(--ic-purple) 12%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ic-purple) 22%, transparent);
  color: var(--ic-purple);
}
.ic-topbar-activity-toggle__badge {
  position: absolute;
  top: 0.3rem;
  right: 0.35rem;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 999px;
  background: var(--ic-danger);
  box-shadow: 0 0 0 2px var(--ic-body-bg, var(--bs-body-bg));
}

.ic-topbar-activity-card {
  min-width: 26rem;
  max-width: 30rem;
}
.ic-topbar-activity-scroll {
  max-height: 24rem;
  overflow-y: auto;
}

.ic-topbar-activity-list {
  display: grid;
  gap: 0.5rem;
}
.ic-topbar-activity-item {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.75rem 0.85rem;
  border-radius: 0.75rem;
  border: 1px solid var(--ic-border-color-translucent);
  background: color-mix(in srgb, var(--ic-body-color) 8%, var(--ic-body-bg));
  color: inherit;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, transform 0.15s ease-in-out;
}
.ic-topbar-activity-item:hover,
.ic-topbar-activity-item:focus-within {
  background: color-mix(in srgb, var(--ic-body-color) 14%, var(--ic-body-bg));
  border-color: var(--ic-border-color);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
  transform: translateY(-1px);
}

.ic-topbar-activity-icon {
  flex: 0 0 auto;
  width: 2.1rem;
  height: 2.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-size: 0.85rem;
}
.ic-topbar-activity-chip--success  { background: color-mix(in srgb, var(--ic-success) 15%, transparent); color: var(--ic-success); }
.ic-topbar-activity-chip--info     { background: color-mix(in srgb, var(--ic-info) 15%, transparent);    color: var(--ic-info); }
.ic-topbar-activity-chip--warning  { background: color-mix(in srgb, var(--ic-warning) 18%, transparent); color: var(--ic-warning); }
.ic-topbar-activity-chip--primary  { background: color-mix(in srgb, var(--ic-purple) 15%, transparent);  color: var(--ic-purple); }
.ic-topbar-activity-chip--secondary{ background: color-mix(in srgb, var(--ic-body-color, var(--bs-body-color)) 10%, transparent); color: var(--ic-secondary-color, var(--bs-secondary-color)); }

/* Chip variant (small pill) reuses the same color tokens via the shared class */
.ic-topbar-activity-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
  flex: 0 0 auto;
}

.ic-topbar-activity-copy {
  min-width: 0;
  display: grid;
  gap: 0.35rem;
  flex: 1 1 auto;
}
.ic-topbar-activity-copy > .ic-badge-pair {
  display: inline-flex;
  width: fit-content;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
}
.ic-topbar-activity-copy > .ic-badge-pair > .ic-badge-pair__label {
  flex: 0 0 auto;
}
.ic-topbar-activity-copy > .ic-badge-pair > .ic-badge-pair__value {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ic-topbar-activity-headline {
  font-weight: 600;
  font-size: 0.88rem;
  line-height: 1.3;
  color: var(--ic-emphasis-color, var(--ic-body-color));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-bottom: 0.1rem;
}
.ic-topbar-activity-title-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}
.ic-topbar-activity-title {
  font-weight: 600;
  font-size: 0.9rem;
  line-height: 1.35;
  color: var(--ic-emphasis-color, var(--ic-body-color));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1 1 auto;
  min-width: 0;
}
.ic-topbar-activity-meta {
  display: block;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--ic-secondary-color, var(--bs-secondary-color));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ic-topbar-activity-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.15rem;
  min-width: 0;
}
.ic-topbar-activity-time {
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--ic-secondary-color, var(--bs-secondary-color));
  padding-top: 0.2rem;
  text-align: right;
  min-width: 2.5rem;
}

.ic-topbar-activity-empty {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 0.85rem;
  border-radius: 0.75rem;
  background: color-mix(in srgb, var(--ic-body-bg, var(--bs-body-bg)) 94%, transparent);
  border: 1px dashed var(--ic-border-color-translucent);
}
