/* Bulletproof: kill the F7 caret-browsing cursor everywhere except real inputs.
   Applies to ALL elements via the universal selector, then opts text fields back in. */
*{
  caret-color: transparent;
}
button, .btn, label, .form-label, .badge, .nav-link, .breadcrumb, .breadcrumb-item,
.menu-title, .card-title, .page-title-box, .page-title-box h4,
th, td, .dropdown-item, .pagination .page-link, .avatar-title, .logo-txt,
.metismenu, .metismenu li, .metismenu a, .metismenu span,
li, ul, ol, p, span, h1, h2, h3, h4, h5, h6, b, strong, small, i {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
/* Allow real inputs to behave normally */
input, textarea, select,
input *, textarea *, select *,
[contenteditable="true"], .editable, .editable * {
  -webkit-user-select: text !important;
  user-select: text !important;
  caret-color: auto !important;
}
/* Table cells: allow text selection (so users can copy data) but no caret */
td, th { user-select: text; -webkit-user-select: text; }

/* ---- Theme-mode form control polish (light + dark) ---- */
/* In dark mode Minia darkens cards/tables; force inputs to use Minia tokens so they don't clash. */
[data-layout-mode="dark"] .form-control,
[data-layout-mode="dark"] .form-select,
[data-layout-mode="dark"] .input-group-text {
  background-color: #2a3042;
  border-color: #32394e;
  color: #c3cbe4;
}
[data-layout-mode="dark"] .form-control::placeholder { color: #74788d; }
[data-layout-mode="dark"] .form-control:focus,
[data-layout-mode="dark"] .form-select:focus {
  background-color: #2a3042;
  border-color: #556ee6;
  color: #fff;
  box-shadow: 0 0 0 .15rem rgba(85,110,230,.25);
}
[data-layout-mode="dark"] .form-control:disabled,
[data-layout-mode="dark"] .form-select:disabled { background-color: #222736; color: #74788d; }
[data-layout-mode="dark"] .modal-content { background-color: #2a3042; color: #c3cbe4; }
[data-layout-mode="dark"] .modal-header, [data-layout-mode="dark"] .modal-footer { border-color: #32394e; }
[data-layout-mode="dark"] .btn-close { filter: invert(.85) }
[data-layout-mode="dark"] .table-light { --bs-table-bg: #2a3042; --bs-table-color: #c3cbe4; }
[data-layout-mode="dark"] .text-body, [data-layout-mode="dark"] .badge.bg-light { color: #c3cbe4 !important; }
[data-layout-mode="dark"] pre.code { background:#0f172a; }
/* Theme button itself */
#themeToggle { color: inherit; }
#themeToggle:hover { background: rgba(255,255,255,.07); }

/* ---- Dropdown menus (Profile/Logout, notifications) in dark mode ---- */
[data-layout-mode="dark"] .dropdown-menu {
  background-color: #2a3042;
  border-color: #32394e;
  color: #c3cbe4;
  box-shadow: 0 4px 14px rgba(0,0,0,.35);
}
[data-layout-mode="dark"] .dropdown-menu .dropdown-item {
  color: #c3cbe4;
}
[data-layout-mode="dark"] .dropdown-menu .dropdown-item:hover,
[data-layout-mode="dark"] .dropdown-menu .dropdown-item:focus {
  background-color: #32394e;
  color: #fff;
}
[data-layout-mode="dark"] .dropdown-menu .dropdown-item.text-danger { color: #f46a6a; }
[data-layout-mode="dark"] .dropdown-menu .dropdown-item.text-danger:hover {
  background-color: #3a2a32;
  color: #ff8a8a;
}
[data-layout-mode="dark"] .dropdown-divider { border-color: #32394e; }
[data-layout-mode="dark"] .dropdown-menu h6 { color: #c3cbe4; }

/* ---- Header-bar dropdown triggers (avatar, notifications, theme toggle) ---- */
/* Bootstrap flips .btn backgrounds to white on focus/active; in dark mode that
   leaves a stark white rectangle behind the avatar + name when the menu opens.
   Force the header-item triggers to stay transparent across every state. */
[data-layout-mode="dark"] .navbar-header .btn.header-item,
[data-layout-mode="dark"] .navbar-header .btn.header-item:hover,
[data-layout-mode="dark"] .navbar-header .btn.header-item:focus,
[data-layout-mode="dark"] .navbar-header .btn.header-item:active,
[data-layout-mode="dark"] .navbar-header .show > .btn.header-item,
[data-layout-mode="dark"] .navbar-header .btn.header-item[aria-expanded="true"] {
  background-color: transparent !important;
  color: #c3cbe4 !important;
  border-color: transparent !important;
  box-shadow: none !important;
}
[data-layout-mode="dark"] .navbar-header .btn.header-item:hover {
  background-color: rgba(255, 255, 255, .05) !important;
}
/* Username label + chevron next to the avatar */
[data-layout-mode="dark"] .navbar-header .btn.header-item .fw-medium,
[data-layout-mode="dark"] .navbar-header .btn.header-item .mdi-chevron-down {
  color: #c3cbe4 !important;
}
/* Notification badge sits over a dark trigger — keep its red but punch through */
[data-layout-mode="dark"] .navbar-header .badge.bg-danger {
  box-shadow: 0 0 0 2px var(--header-bg, #2a3042);
}

/* ===========================================================================
   Fluid-interface pass (Apple: Designing Fluid Interfaces, WWDC 2018)

   Applies to every app-shell page, deliberately: the topbar and sidebar are
   shared partials, so styling them from one page's <style> block would make
   the same chrome behave differently depending on where you stood.
   =========================================================================== */

/* ---- The topbar becomes a material ---------------------------------------
   #page-topbar is position:fixed with a solid fill and no shadow, so scrolled
   content vanished under a hard edge with nothing to say where it went.
   Translucency keeps it faintly visible underneath, which is what makes a
   floating layer read as floating. The bar stays DARKER than the body
   (measured: #2c302e over #313533) because heavier material is what separates
   structural chrome from content.

   The SIDEBAR is deliberately left opaque. Translucency earns its place when
   something passes behind the surface; content scrolls under the topbar, but
   the sidebar is a left rail with the content column beside it, so behind it
   is nothing but flat page background. Blurring that is GPU work per frame
   for no visible result. */
#page-topbar {
  background-color: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
}
[data-layout-mode="dark"] #page-topbar {
  background-color: rgba(44, 48, 46, .72);
}

/* A bright top edge reads as light catching the surface, giving the material
   a thickness the flat fill never had. */
[data-layout-mode="dark"] #page-topbar { border-bottom: 1px solid rgba(255, 255, 255, .06); }
#page-topbar { border-bottom: 1px solid rgba(0, 0, 0, .06); }

/* ---- Scroll edge effect, not a permanent divider ------------------------
   Separation should appear only once content is actually underneath the
   chrome. At the top of the page there is nothing to separate from, so the
   shadow would be decoration. scripts.html toggles .is-scrolled. */
#page-topbar {
  transition: box-shadow .2s ease-out, background-color .2s ease-out;
}
#page-topbar.is-scrolled { box-shadow: 0 1px 12px rgba(0, 0, 0, .10); }
[data-layout-mode="dark"] #page-topbar.is-scrolled { box-shadow: 0 1px 14px rgba(0, 0, 0, .38); }

/* ---- Response: acknowledge the press, not the release -------------------
   Nothing on these pages responded on pointer-down. The tenant cards are the
   primary target on the console and had :hover and .active but no pressed
   state, so a click felt like it did nothing until the panel repainted. */
.org-card:active,
.btn:active,
.card.cursor-pointer:active,
.list-group-item-action:active {
  transform: scale(.99);
}
.btn { transition: transform .1s ease-out, background-color .15s ease-out,
                   border-color .15s ease-out, box-shadow .15s ease-out; }
/* Disabled controls must not pretend to respond. */
.btn:disabled:active, .btn.disabled:active { transform: none; }

/* ---- Typography: tracking is size-specific ------------------------------
   Every heading on the console measured letter-spacing:normal, from 18px
   titles down to 11px uppercase labels. One value cannot be right at both
   ends: large text reads too loose, small uppercase too tight. */
h1, .h1, h2, .h2 { letter-spacing: -.02em; line-height: 1.15; }
h3, .h3, h4, .h4, .font-size-18 { letter-spacing: -.01em; }
h5, .h5, .font-size-16 { letter-spacing: -.005em; }
.text-uppercase.font-size-11,
.text-uppercase.font-size-12,
.badge { letter-spacing: .04em; }
/* Stat counters are large, tabular and compared down a column. */
.card h4.mb-0, .card h5.mb-0 { font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

/* ---- Accessibility preferences -----------------------------------------
   Reduced motion keeps colour and shadow (neither is vestibular) and drops
   only the movement. */
@media (prefers-reduced-motion: reduce) {
  .org-card:active, .btn:active,
  .card.cursor-pointer:active, .list-group-item-action:active { transform: none; }
  .org-card { transition: border-color .15s, box-shadow .15s; }
  .org-card:hover { transform: none; }
}
/* Translucency is the first thing to go — legibility outranks depth. */
@media (prefers-reduced-transparency: reduce) {
  #page-topbar {
    background-color: #fff;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  [data-layout-mode="dark"] #page-topbar { background-color: #2c302e; }
}
/* More contrast: solid ground and a border that actually defines the edge. */
@media (prefers-contrast: more) {
  #page-topbar {
    background-color: #fff;
    -webkit-backdrop-filter: none; backdrop-filter: none;
    border-bottom-color: rgba(0, 0, 0, .5);
  }
  [data-layout-mode="dark"] #page-topbar {
    background-color: #23262a;
    border-bottom-color: rgba(255, 255, 255, .45);
  }
}

/* ---- Soft tone tints: bg-soft-* ----------------------------------------
   These utilities are used 32 times across nine pages and DO NOT EXIST in this
   Minia build. Every one of them silently did nothing, which left an
   `.avatar-title` sitting on its own solid brand-blue background — and where
   the glyph was `text-primary` it was brand blue ON brand blue and simply
   disappeared. Three tiles on the Platform Admin console had no visible icon
   at all. board.html and risk-register.html compose the class from a variable
   (`bg-soft-${tone}`), so they lose whichever tile happens to be primary.

   The recipe is not invented: it matches the badge-soft-* this theme already
   ships — the hue at 18% behind the glyph at full hue — and it is written from
   the --bs-*-rgb custom properties so it tracks the palette instead of
   freezing hex values. Because the tint is alpha over whatever card is behind
   it, light and dark are both correct by construction rather than by a second
   rule.

   !important because these are utilities overriding a component's own
   background, which is the same reason every Bootstrap utility carries it. */
.bg-soft-primary   { --tone: var(--bs-primary);   background-color: rgba(var(--bs-primary-rgb),   .18) !important; }
.bg-soft-secondary { --tone: var(--bs-secondary); background-color: rgba(var(--bs-secondary-rgb), .18) !important; }
.bg-soft-success   { --tone: var(--bs-success);   background-color: rgba(var(--bs-success-rgb),   .18) !important; }
.bg-soft-warning   { --tone: var(--bs-warning);   background-color: rgba(var(--bs-warning-rgb),   .18) !important; }
.bg-soft-danger    { --tone: var(--bs-danger);    background-color: rgba(var(--bs-danger-rgb),    .18) !important; }
.bg-soft-info      { --tone: var(--bs-info);      background-color: rgba(var(--bs-info-rgb),      .18) !important; }

/* Vibrancy: the glyph adapts to the ground it sits on.
   Restoring the tint alone was not enough. `text-primary` on an 18% primary
   tint measures 1.92:1 on a dark card and `text-secondary` 2.52:1 — both hues
   are dark to begin with, so a dark glyph on a barely-lifted dark ground stays
   muddy. Same story inverted in light mode, where warning is the weak one.

   So the disc keeps the hue and the glyph moves away from it: toward white on
   dark, toward black on light. The two percentages are measured, not picked —
   each is the shallowest mix that clears 3.0:1 (WCAG's non-text minimum) for
   ALL SIX hues on that ground, so the glyph keeps as much of its hue identity
   as legibility allows:

     dark  · tone 45% + white -> worst 5.86 (primary)
     light · tone 60% + black -> worst 3.95 (warning)

   Warning is the binding constraint in light mode and it is why this is 60%
   and not 70%: at 70% amber measured exactly 3.00, which is the threshold
   itself rather than a margin. Going deeper still (45%) would clear 6.0 but
   pushes primary to near-black and the tone stops reading as a colour.

   `--tone` is set beside each tint above so this is two rules rather than
   twelve, and the tone stays named rather than re-stated as a hex. Browsers
   without color-mix simply keep the `text-*` colour they have today, so this
   can only improve on the previous behaviour, never break it. */
.avatar-title[class*="bg-soft-"] {
  color: color-mix(in srgb, var(--tone) 60%, #000) !important;
}
[data-layout-mode="dark"] .avatar-title[class*="bg-soft-"] {
  color: color-mix(in srgb, var(--tone) 45%, #fff) !important;
}

/* ---- Stat tile row -----------------------------------------------------
   Seven tiles in `col-xl-2` is six per row and a seventh sitting alone on the
   next one — the kind of ragged layout that reads as carelessness rather than
   as a decision. A grid that sizes from the content fits all seven across at
   desktop width and reflows evenly instead of orphaning one.

   minmax is in rem, not px, so a larger text setting grows the tile with the
   type rather than clipping the number inside it. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  gap: 1rem;
}
/* Small uppercase-ish labels need positive tracking; the number is compared
   down a column, so it is tabular and tightened. */
.stat-grid .stat-label { letter-spacing: .01em; }
.stat-grid .stat-value {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  line-height: 1.15;
}

/* ---- Standing-condition notice ----------------------------------------
   Was `alert alert-danger`: a solid red slab, the loudest thing on the page,
   for a message that is not an error — it states how the screen works
   (every tenant visible at once, BYPASSRLS active, everything audited). A
   standing condition rendered as a failure teaches people to ignore real
   failures, and the translucent topbar was dragging its red across the top of
   the window as content scrolled under the glass.

   Still a caution, and still unmissable, but carried by a tinted surface and
   an edge accent rather than by shouting — form as well as colour, so it
   survives both themes and a contrast preference. */
.pa-notice {
  background-color: rgba(var(--bs-warning-rgb), .12);
  border: 1px solid rgba(var(--bs-warning-rgb), .28);
  border-left: 3px solid var(--bs-warning);
  border-radius: .5rem;
  padding: .75rem 1rem;
  color: var(--bs-body-color);
}
.pa-notice .pa-notice-icon { color: var(--bs-warning); }
@media (prefers-contrast: more) {
  .pa-notice { background-color: transparent; border-width: 2px; border-left-width: 4px; }
}

/* ---- Selectable option card --------------------------------------------
   The checkbox card used by every picker: the taxonomy and library selectors
   on the Platform Admin console, and the tenant selector behind a Master
   Library reach pill. It lives here rather than inline on one page because a
   second copy is a copy that drifts — and this one already carries the press
   response and all three accessibility fallbacks.

   A dense admin grid, so the motion budget is deliberately small: an instant
   press response and a short colour settle. No springs — those earn their
   place on things you can grab and throw, not on checkboxes. */
.tax-group-label { letter-spacing: .06em; }   /* small uppercase needs positive tracking */
.tax-code { letter-spacing: .03em; }
.tax-option {
  display: block; margin: 0; cursor: pointer;
  border: 1px solid var(--bs-border-color); border-radius: .5rem;
  /* Only compositor-friendly properties animate; nothing here reflows. */
  transition: border-color .15s ease-out, background-color .15s ease-out,
              transform .1s ease-out;
}
.tax-option:hover { border-color: rgba(81, 86, 190, .55); }
/* Feedback on press, not on release — waiting for change: feels dead. */
.tax-option:active { transform: scale(.985); }
.tax-option:has(input:focus-visible) { outline: 2px solid #5156be; outline-offset: 2px; }
.tax-option.is-selected { border-color: #5156be; background-color: rgba(81, 86, 190, .08); }
[data-layout-mode="dark"] .tax-option.is-selected { background-color: rgba(81, 86, 190, .20); }
.tax-option.is-retired { opacity: .55; cursor: not-allowed; }
.tax-option.is-retired:active { transform: none; }

/* Keep the colour change (it carries meaning, and colour is not vestibular),
   drop the movement. */
@media (prefers-reduced-motion: reduce) {
  .tax-option { transition: border-color .15s ease-out, background-color .15s ease-out; }
  .tax-option:active { transform: none; }
}
/* Solid tints instead of alpha over the card. */
@media (prefers-reduced-transparency: reduce) {
  .tax-option.is-selected { background-color: #ecebf8; }
  [data-layout-mode="dark"] .tax-option.is-selected { background-color: #2b2c45; }
}
/* Carry the state on a defined border, not a wash. */
@media (prefers-contrast: more) {
  .tax-option { border-width: 2px; }
  .tax-option.is-selected { border-color: #3b3f9e; background-color: transparent; }
}
