/*
 * Tabler shell exceptions.
 *
 * plan/ui-standardization.md §5 "Asset policy" makes this the application's
 * only stylesheet beside the vendored Tabler bundle, and requires every
 * rule to carry a semantic class name plus a comment naming the unmet
 * requirement, the component documentation checked, and the removal
 * condition.
 *
 * Prefer Tabler and Bootstrap utilities over anything added here. Every
 * rule below was audited on 2026-09-05: each still has live callers, and
 * none is a leftover of the retired Patternslib stylesheets.
 */

/* .no-js .navbar-expand-md .navbar-collapse
 * Unmet requirement: below the navbar's expand breakpoint the primary
 *   navigation lives in a Bootstrap collapse, which stays at
 *   `display: none` until Bootstrap's JavaScript adds `.show`. With
 *   scripting off the navigation would be unreachable, and plan §2 requires
 *   a migrated page to work as an ordinary HTTP page.
 * Documentation checked: https://docs.tabler.io/ui/layout/navbars and
 *   Bootstrap 5.3 Collapse — neither ships a scriptless expanded state.
 * Removal condition: drop when Tabler or Bootstrap ship a no-JavaScript
 *   navbar fallback, or when the primary navigation no longer collapses.
 */
@media (max-width: 767.98px) {
  .no-js .navbar-expand-md .navbar-collapse {
    display: block;
  }
}

/* .no-js .navbar-nav .dropdown-menu
 * Unmet requirement: Bootstrap keeps `.dropdown-menu` at `display: none`
 *   and absolutely positioned until its JavaScript opens the dropdown, so
 *   without scripting the navigation submenus and the user menu — logout
 *   included — cannot be reached at all.
 * Documentation checked: https://docs.tabler.io/ui/layout/navbars and
 *   Bootstrap 5.3 Dropdowns — both require the Dropdown plugin to open.
 * Removal condition: drop when the submenus move to a natively disclosable
 *   element. Note this is not legacy-shell debt — it exists because
 *   Bootstrap's dropdown needs JavaScript to open, so removing it would
 *   strand every scriptless visitor at the navigation.
 */
.no-js .navbar-nav .dropdown-menu {
  display: block;
  position: static;
}

/* .no-js .navbar-nav .submenu-toggle
 * Unmet requirement: with the submenu already expanded by the rule above,
 *   the toggle button controls nothing, and an `aria-expanded="false"` that
 *   can never change is worse than no control at all.
 * Documentation checked: https://docs.tabler.io/ui/layout/navbars — the
 *   documented toggle has no inert state.
 * Removal condition: drop together with the `.no-js` dropdown fallback
 *   above.
 */
.no-js .navbar-nav .submenu-toggle {
  display: none;
}

/* .shell-brand-link, .shell-brand-name and .shell-brand-byline
 * Unmet requirement: the shell brand must pair its fixed 26px product mark
 *   with an equally tall white wordmark, a full-width byline, and a muted
 *   hover state. Tabler's navbar-brand typography is smaller and inherits
 *   link colouring, while its utilities cannot justify a single-line byline
 *   to the exact width of the brand lockup.
 * Documentation checked: https://docs.tabler.io/ui/layout/navbars and
 *   Bootstrap 5.3 text colour / typography utilities.
 * Removal condition: drop when the product lockup becomes one supplied
 *   image asset or Tabler provides an equivalent navbar-brand treatment.
 */
.shell-brand-link,
.shell-brand-link:visited {
  color: var(--tblr-white);
}

.shell-brand-link:hover,
.shell-brand-link:focus-visible {
  color: var(--tblr-gray-300);
}

.shell-brand-name {
  font-size: 1.5rem;
  line-height: 26px;
}

.shell-brand-byline {
  inline-size: 100%;
  font-size: 12px;
  line-height: 1.1;
  text-align: justify;
  text-align-last: justify;
}

/* .shell-primary-navigation
 * Unmet requirement: the primary navigation categories are the shell's
 *   main wayfinding controls and need a stronger type scale and touch target
 *   than Tabler's compact default navbar links. No Tabler size variant makes
 *   navbar items prominent without changing unrelated dropdown contents.
 * Documentation checked: https://docs.tabler.io/ui/layout/navbars and
 *   Bootstrap 5.3 nav utilities.
 * Removal condition: drop when Tabler exposes a large navbar-item variant or
 *   the primary navigation moves to a component with an equivalent scale.
 */
.shell-primary-navigation > .navbar-nav > .nav-item > .nav-link {
  min-block-size: 2.75rem;
  padding: 0.6875rem 0.875rem;
  font-size: 16px;
  font-weight: 600;
}

.shell-primary-navigation > .navbar-nav > .nav-item > .nav-link.active {
  color: var(--tblr-white);
  background-color: var(--tblr-bg-surface-secondary);
  box-shadow: inset 0 -2px var(--tblr-primary);
  font-weight: 700;
}

/* .shell-primary-navigation .dropdown-menu
 * Unmet requirement: primary submenus sit on a shell surface with nearly
 *   the same tone as Tabler's default dropdown, so their boundary and active
 *   hierarchy disappear. The stronger Tabler elevation, border, raised
 *   surface and type scale keep the navigation layer legible.
 * Documentation checked: https://docs.tabler.io/ui/components/dropdowns.
 * Removal condition: drop when the shell and stock dropdown have sufficient
 *   contrast and the default menu type reaches the primary-nav scale.
 */
.shell-primary-navigation .dropdown-menu {
  min-inline-size: 14rem;
  padding: 0.5rem;
  background-color: var(--tblr-bg-surface-tertiary);
  border: 1px solid var(--tblr-border-color);
  box-shadow: var(--tblr-box-shadow-lg);
}

.shell-primary-navigation .dropdown-item {
  min-block-size: 2.5rem;
  padding: 0.625rem 0.75rem;
  border-radius: var(--tblr-border-radius-sm);
  font-size: 1rem;
}

.shell-primary-navigation .dropdown-item.active {
  color: var(--tblr-body-color);
  background-color: var(--tblr-bg-surface-secondary);
  font-weight: 700;
}

/* html.no-js .modal and its dialog / trigger / dismiss controls
 * Unmet requirement: plan §1 requires every migrated route to stay usable
 *   as an ordinary HTTP page, and §3.1 puts the commercial-case dialog
 *   forms (add activity, add offer, close case) into a Tabler Modal.
 *   Bootstrap keeps `.modal` at `display: none`, zeroes it through
 *   `.fade:not(.show)`, offsets and disables pointer events on
 *   `.modal-dialog` for the open transition, and Tabler's `.modal-blur`
 *   filters the backdrop — all of it undone by the Modal plugin, which is
 *   not there. Rendering a second, always-visible copy of the form instead
 *   would duplicate every field id on the page, so the one copy is unwrapped
 *   into normal flow and the controls that now do nothing are hidden.
 * Documentation checked: https://docs.tabler.io/ui/components/modals and
 *   Bootstrap 5.3 Modal — both require the Modal plugin to show a dialog and
 *   ship no scriptless open state.
 * Removal condition: drop when Bootstrap adopts the native `<dialog>`
 *   element (which renders without scripting), or when the case-page forms
 *   move off modals to their own routes.
 */
html.no-js .modal {
  display: block;
  position: static;
  overflow: visible;
  opacity: 1;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* Kept one level deeper than Bootstrap's own `.modal.fade .modal-dialog`,
 * which would otherwise win the transform back. */
html.no-js .modal .modal-dialog {
  max-width: none;
  margin: 0 0 1.5rem;
  transform: none;
  pointer-events: auto;
}

html.no-js [data-bs-toggle="modal"],
html.no-js [data-bs-dismiss="modal"] {
  display: none;
}

/* .htmx-indicator
 * Unmet requirement: the shell sets `includeIndicatorStyles: false` in its
 *   htmx configuration, because htmx otherwise injects these rules through
 *   an inline <style> element that a `style-src 'self'` policy blocks. The
 *   rules themselves are still needed, so they are served from here.
 * Documentation checked: https://htmx.org/docs/#indicators and
 *   https://htmx.org/reference/#config — the class contract is htmx's, only
 *   its delivery changes.
 * Removal condition: drop if htmx stops injecting indicator styles inline,
 *   or if the application stops using htmx request indicators.
 */
.htmx-indicator {
  opacity: 0;
  transition: opacity 200ms ease-in;
}

/* .htmx-request .htmx-indicator, .htmx-request.htmx-indicator
 * Unmet requirement: the visible half of the same contract — htmx marks the
 *   requesting element with `.htmx-request`, and the indicator has to become
 *   visible whether it is that element or a descendant of it.
 * Documentation checked: https://htmx.org/docs/#indicators — both selectors
 *   are part of htmx's own default stylesheet.
 * Removal condition: drop together with the `.htmx-indicator` rule above.
 */
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}

/* .shell-global-search-panel, .shell-freshness-dot, .search-result-*
 * Unmet requirement: Tabler supplies the dropdown, status-dot, and list-group
 * primitives but no cross-entity search panel or semantic type palette.
 * Removal condition: drop when Tabler provides a global-search component with
 * responsive results and distinguishable entity types.
 */
.shell-global-search {
  position: relative;
}

.shell-global-search > summary {
  list-style: none;
  cursor: pointer;
}

.shell-global-search > summary::-webkit-details-marker {
  display: none;
}

.shell-global-search-panel {
  position: absolute;
  inset-block-start: calc(100% + 0.5rem);
  inset-inline-end: 0;
  z-index: 1035;
  display: block;
  inline-size: min(calc(100vw - 1rem), 34rem);
}

.shell-global-search:not([open]) > .shell-global-search-panel {
  display: none;
}

.shell-freshness-dot {
  inline-size: 0.75rem;
  block-size: 0.75rem;
}

.search-result,
.search-suggestion {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-inline-start: 0.25rem solid transparent;
}

.search-result-issue { background: color-mix(in srgb, var(--tblr-blue) 16%, var(--tblr-bg-surface)); border-inline-start-color: var(--tblr-blue); }
.search-result-customer { background: color-mix(in srgb, var(--tblr-yellow) 18%, var(--tblr-bg-surface)); border-inline-start-color: var(--tblr-yellow); }
.search-result-case { background: color-mix(in srgb, var(--tblr-green) 16%, var(--tblr-bg-surface)); border-inline-start-color: var(--tblr-green); }
.search-result-contract { background: color-mix(in srgb, var(--tblr-orange) 17%, var(--tblr-bg-surface)); border-inline-start-color: var(--tblr-orange); }
.search-result-document { background: color-mix(in srgb, var(--tblr-secondary-color) 20%, var(--tblr-bg-surface)); border-inline-start-color: var(--tblr-secondary-color); }

.profitability-chart {
  min-block-size: clamp(24rem, 55vw, 42rem);
  inline-size: 100%;
}

[data-profitability-chart-panel][hidden] {
  display: none;
}

.shell-account-menus {
  align-items: center;
  margin-inline-start: auto;
}

@media (max-width: 767.98px) {
  .shell-global-search-panel {
    position: fixed;
    inset-block-start: 3.5rem;
    inset-inline: 0.5rem;
    inline-size: auto;
  }

  [data-profitability-charts] .nav-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
  }

  [data-profitability-charts] .nav-link {
    white-space: nowrap;
  }

  .profitability-chart {
    min-block-size: 32rem;
  }
}

/* #shell-time-booking-modal
 * Unmet requirement: the global booking dialog is loaded only when its
 *   shell control is activated. With scripting disabled there is no dialog
 *   content to unwrap, while the trigger remains an ordinary /time link.
 * Documentation checked: https://docs.tabler.io/ui/components/modals and
 *   htmx lazy loading patterns.
 * Removal condition: drop if the modal body becomes server-rendered or the
 *   booking control stops providing the ordinary /time fallback.
 */
html.no-js #shell-time-booking-modal {
  display: none;
}

/* Content links
 * Unmet requirement: Tabler's default accent-coloured links lose clarity
 *   against the near-black and raised gray work surfaces. Content links need
 *   one high-contrast neutral colour in both unvisited and visited states,
 *   with an underline reserved for hover so dense operational pages stay calm.
 * Documentation checked: https://docs.tabler.io/ui/typography and WCAG 2.2
 *   link-purpose / non-colour identification guidance.
 * Removal condition: drop when the Tabler theme variables provide the same
 *   neutral link and visited-state treatment application-wide.
 */
body a:not(.btn):not(.nav-link):not(.dropdown-item):not(.shell-brand-link),
body a:not(.btn):not(.nav-link):not(.dropdown-item):not(.shell-brand-link):visited {
  color: var(--tblr-gray-200);
  text-decoration: none;
}

body a:not(.btn):not(.nav-link):not(.dropdown-item):not(.shell-brand-link):hover {
  color: var(--tblr-white);
  text-decoration: underline;
  text-decoration-thickness: 0.06em;
  text-underline-offset: 0.16em;
}

/* .alert-info
 * Unmet requirement: informational guidance must read like a yellow post-it,
 *   while retaining Tabler's alert structure and polite live-region semantics.
 * Documentation checked: https://docs.tabler.io/ui/components/alerts.
 * Removal condition: drop when Tabler exposes a post-it information variant.
 */
.alert-info {
  --tblr-alert-color: #4d3800;
  --tblr-alert-bg: #fff3bf;
  --tblr-alert-border-color: #e6b800;
  --tblr-alert-link-color: #3d2b00;
}

/* #commercial-document-upload.dropzone, #profile-image-upload.dropzone,
 * .contract-documents-tab .dropzone-form.dropzone
 * Unmet requirement: Dropzone 5 hardcodes a white upload canvas that ignores
 *   Bootstrap colour mode, making upload fields illegible in the app's dark
 *   operational shell.
 * Documentation checked: https://docs.tabler.io/ui/components/dropzone and
 *   the vendored dropzone.min.css default `.dropzone` rule.
 * Removal condition: drop when the vendored Dropzone theme honours
 *   `data-bs-theme="dark"` or the upload surface leaves Dropzone.
 */
#commercial-document-upload.dropzone,
#profile-image-upload.dropzone,
.contract-documents-tab .dropzone-form.dropzone {
  color: var(--tblr-body-color);
  background-color: var(--tblr-bg-surface);
  border-color: var(--tblr-border-color);
}

/* .homepage-team-switcher
 * Unmet requirement: the homepage identity switcher needs room for an avatar
 *   and a full team-member name while remaining a compact page action.
 * Documentation checked: https://docs.tabler.io/ui/components/dropdowns.
 * Removal condition: drop if the page-header action gets a responsive width
 *   utility that fits identity-rich dropdown toggles.
 */
.homepage-team-switcher {
  inline-size: min(16rem, calc(100vw - 2rem));
}

.homepage-team-switcher .dropdown-menu {
  inline-size: 100%;
}

.homepage-view-as-alert {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.375rem;
  padding-inline-start: 0.75rem;
  margin: 0;
}

.homepage-view-as-alert .homepage-team-switcher {
  inline-size: min(14rem, calc(100vw - 8rem));
}

@media (max-width: 575.98px) {
  .homepage-view-as-alert {
    align-items: stretch;
    flex-direction: column;
  }

  .homepage-view-as-alert .homepage-team-switcher {
    inline-size: min(16rem, calc(100vw - 3rem));
  }
}

/* .contract-documents-tab .dropzone-form.dropzone
 * Unmet requirement: Dropzone 5's fixed 150px minimum and two-em message
 *   margin are oversized inside the contract document cards.
 * Documentation checked: Tabler Dropzone and the vendored Dropzone defaults.
 * Removal condition: drop when the upload macro exposes a documented compact
 *   density or the vendored theme follows Tabler's compact card spacing.
 */
.contract-documents-tab .dropzone-form.dropzone {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem;
  min-height: 0;
  padding: 0.75rem;
}

.contract-documents-tab .dropzone-form.dropzone .dz-message {
  grid-column: 1 / -1;
  margin-block: 0;
}

.contract-documents-tab .dropzone-form.dropzone > .mb-2 {
  min-width: 0;
  margin-bottom: 0 !important;
}

.contract-documents-tab .dropzone-form.dropzone > .btn {
  align-self: end;
}

.contract-documents-tab .dropzone-form.dropzone .dropzone-previews {
  grid-column: 1 / -1;
}

/* .readable-table-surface and its direct table descendants
 * Unmet requirement: Tabler's responsive table structure provides overflow,
 *   but the dark default leaves dense rows and headers too close in tone and
 *   gives links little non-colour distinction. The shared table surface needs
 *   a visible keyboard focus, a raised header, and higher-contrast links while
 *   preserving Tabler's striped and hover row states.
 * Documentation checked: https://preview.tabler.io/tables.html in dark mode
 *   and https://docs.tabler.io/ui/components/tables. The markup retains
 *   Tabler's `table-responsive` and `table table-vcenter card-table` pattern.
 * Removal condition: drop when Tabler's dark responsive-table defaults supply
 *   equivalent header hierarchy, link distinction, and overflow focus.
 */
.readable-table-surface {
  background-color: var(--tblr-bg-surface);
  border-radius: var(--tblr-border-radius);
  box-shadow: var(--tblr-box-shadow-sm);
}

.readable-table-surface:focus-visible {
  outline: 2px solid var(--tblr-teal);
  outline-offset: 2px;
}

.readable-table-surface > .table {
  margin-bottom: 0;
}

.readable-table-surface > .table > thead > tr > th {
  background-color: var(--tblr-bg-surface-secondary);
  color: var(--tblr-body-color);
  padding-block: 0.75rem;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.035em;
  text-transform: uppercase;
}

.readable-table-surface > .table > tbody > tr > td {
  padding-block: 0.875rem;
  border-bottom-color: var(--tblr-border-color-translucent);
}

.readable-table-surface > .table .badge,
.readable-table-surface > .table .status {
  white-space: nowrap;
}

html[data-bs-theme="dark"]
  .readable-table-surface
  > .table
  a:not(.btn):not(.dropdown-item) {
  color: var(--tblr-gray-200);
  font-weight: 500;
  text-decoration: none;
}

html[data-bs-theme="dark"]
  .readable-table-surface
  > .table
  a:not(.btn):not(.dropdown-item):hover {
  color: var(--tblr-white);
  text-decoration: underline;
  text-decoration-thickness: 0.06em;
  text-underline-offset: 0.16em;
}

/* .record-help-popover
 * Unmet requirement: native details is the direct, no-script fallback for
 * field help; its content must remain readable without taking over a record.
 * Documentation checked: Tabler Popovers and Bootstrap details fallback.
 * Removal condition: replace when a shared accessible help-popover workflow
 * is introduced for every record page.
 */
.record-help-popover {
  max-width: 28rem;
  z-index: 2;
}

/* .case-grid > [class*="col"], .case-grid .d-grid
 * Unmet requirement: the commercial case page's two-column grid must let
 *   the offers table scroll inside its own card on narrow viewports
 *   (.table-responsive). Bootstrap's .row is display:flex and a flex item
 *   refuses to shrink below its content's min-content width, so the
 *   seven-column table pushed the whole page to ~742px wide at 390px. The
 *   nested .d-grid also sizes its implicit column to max-content.
 *   min-width: 0 and minmax(0, 1fr) restore the shrink floor; Bootstrap 5.3
 *   ships neither utility, and no Tabler component expresses this.
 * Documentation checked: Bootstrap 5.3 flex utilities (no min-width
 *   utility exists) and CSS Flexbox's min-width: auto initial value —
 *   flex items do not shrink below min-content without an explicit floor.
 * Removal condition: drop if Bootstrap or Tabler adds a min-width-0
 *   utility, or if the offers table leaves the flex row.
 */
.case-grid > [class*="col"] {
  min-width: 0;
}

.case-grid .d-grid {
  grid-template-columns: minmax(0, 1fr);
}

/* [data-booking-popover] > [data-booking-popover-panel],
 * .issue-actions-menu > .issue-actions-menu-panel
 * Unmet requirement: the booking popover and the issue actions menu are
 *   <details> elements because Bootstrap's dropdown/modal components all
 *   require JavaScript and plan §1 requires the form to work without it;
 *   the <details> content flows inline by default, which would stretch
 *   the page header the popover sits in. The panel therefore overlays
 *   under its summary.
 * Documentation checked: https://docs.tabler.io/ui/components/dropdowns and
 *   Bootstrap 5.3 Dropdowns — both require the Dropdown plugin; no
 *   documented <details>-based popover exists to reuse.
 * Removal condition: drop if Tabler or Bootstrap ships a documented
 *   no-JavaScript popover these surfaces can adopt.
 */
[data-booking-popover],
.issue-actions-menu {
  position: relative;
}

[data-booking-popover] > [data-booking-popover-panel],
.issue-actions-menu > .issue-actions-menu-panel {
  position: absolute;
  inset-inline-end: 0;
  z-index: 10;
  width: min(92vw, 34rem);
}

/* .ts-today
 * Unmet requirement: the week grid marks today's column header and cells so
 *   the reader lands on the right day; Tabler's table variants carry no
 *   per-column current-date state.
 * Documentation checked: https://docs.tabler.io/ui/components/tables — the
 *   striped/hover/active variants style rows, not a semantic date column.
 * Removal condition: drop when Tabulator itself can style a current-date
 *   column. Phase 6's Tabulator week grid did not take this over —
 *   static/timesheet-grid.js still sets the hook — so the exception
 *   stands.
 */
.timesheet-grid .ts-today {
  background-color: var(--tblr-bg-surface-secondary);
}

/* .ts-flash-ok / .ts-flash-bad
 * Unmet requirement: the Tabulator week grid flashes a cell after an
 *   autosave — green on success, red on a refused value — the only
 *   per-cell feedback besides the panel-level error alert. No Tabler
 *   validation state applies to a transient flash.
 * Documentation checked: Bootstrap 5.3 form validation states (they are
 *   persistent, not transient) and Tabler form elements.
 * Removal condition: drop if Tabulator's editor states gain a themed
 *   flash, or the grid leaves the page.
 */
.tabulator .ts-flash-ok {
  background-color: var(--tblr-success-lt);
}

.tabulator .ts-flash-bad {
  background-color: var(--tblr-danger-lt);
}

/* .tabulator visual alignment
 * Unmet requirement: seven opt-in grids retain sorting, filtering and
 *   grouping that Tabler's presentation-only table cannot provide. Their
 *   density and header hierarchy should still match the semantic Tabler
 *   table surface beside them.
 * Documentation checked: https://preview.tabler.io/tables.html and the
 *   Tabulator Bootstrap 5 theme shipped locally.
 * Removal condition: drop if Tabulator's Bootstrap theme inherits Tabler's
 *   card-table spacing and typography directly.
 */
.tabulator {
  overflow: hidden;
  border-radius: var(--tblr-border-radius);
  box-shadow: var(--tblr-box-shadow-sm);
  font-size: var(--tblr-body-font-size);
}

.tabulator .tabulator-header .tabulator-col .tabulator-col-content,
.tabulator .tabulator-cell {
  padding: 0.75rem 1rem;
}

.tabulator .tabulator-header .tabulator-col {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.035em;
  text-transform: uppercase;
}

.tabulator .tabulator-row {
  min-height: 2.875rem;
}

.tabulator .tabulator-group {
  padding: 0.75rem 1rem;
  font-weight: 700;
}

/* .tabulator dark theme
 * Unmet requirement: the shell runs `data-bs-theme="dark"` (plan §5 keeps
 *   the dark operational character), but the vendored Tabulator Bootstrap 5
 *   theme hardcodes #fff/#e6e6e6 backgrounds and dark text, so every grid
 *   rendered light-on-dark with washed-out rows. These rules re-point the
 *   grid's surfaces at the shell's dark variables, scoped under the theme
 *   attribute so they outrank the vendored rules that load later.
 * Documentation checked: the Tabulator 6.x Bootstrap 5 theme ships no
 *   colour-mode support (its one data-bs-theme token is unrelated), and
 *   Tabler's theming is CSS-variable based (tabler.min.css).
 * Removal condition: drop when the vendored Tabulator theme honours
 *   Bootstrap colour modes, or when the shell stops defaulting to dark.
 */
html[data-bs-theme="dark"] .tabulator {
  background-color: var(--tblr-bg-surface);
  color: var(--tblr-body-color);
  border-color: var(--tblr-border-color);
}

html[data-bs-theme="dark"] .tabulator .tabulator-header,
html[data-bs-theme="dark"] .tabulator .tabulator-header .tabulator-col,
html[data-bs-theme="dark"] .tabulator .tabulator-header .tabulator-calcs-holder,
html[data-bs-theme="dark"] .tabulator .tabulator-header .tabulator-calcs-holder .tabulator-row {
  background-color: var(--tblr-bg-surface-secondary);
  color: var(--tblr-body-color);
  border-color: var(--tblr-border-color);
}

html[data-bs-theme="dark"] .tabulator .tabulator-tableholder .tabulator-table {
  background-color: var(--tblr-bg-surface);
  color: var(--tblr-body-color);
}

html[data-bs-theme="dark"] .tabulator .tabulator-row {
  background-color: var(--tblr-bg-surface);
  color: var(--tblr-body-color);
  border-color: var(--tblr-border-color-translucent);
}

html[data-bs-theme="dark"] .tabulator .tabulator-row.tabulator-row-even,
html[data-bs-theme="dark"] .tabulator .tabulator-row:nth-child(even) {
  background-color: var(--tblr-bg-surface-secondary);
}

html[data-bs-theme="dark"] .tabulator .tabulator-row:hover {
  background-color: var(--tblr-bg-surface-dark);
}

html[data-bs-theme="dark"] .tabulator .tabulator-footer,
html[data-bs-theme="dark"] .tabulator .tabulator-footer .tabulator-calcs-holder,
html[data-bs-theme="dark"] .tabulator .tabulator-footer .tabulator-calcs-holder .tabulator-row {
  background-color: var(--tblr-bg-surface-secondary);
  color: var(--tblr-body-color);
  border-color: var(--tblr-border-color);
}

html[data-bs-theme="dark"] .tabulator input[type="text"],
html[data-bs-theme="dark"] .tabulator input:not([type]) {
  background-color: var(--tblr-bg-forms);
  color: var(--tblr-body-color);
  border-color: var(--tblr-border-color);
}

/* .digest-card-grid, compact .digest-card state modifiers, .digest-well
 * Unmet requirement: the cockpit's ticket cards and collapsed category
 *   wells are a dense grid composition with five load-bearing visual
 *   states — ghost (worked on today, not in the well's status), warning
 *   (>= 80% budget), exceeded (>= 100%), running timer, booked today —
 *   whose class names are the test contract
 *   (tests/compass/test_digest_cards.py pins them verbatim). No Tabler
 *   component expresses a semantic state grid of this kind, and the
 *   classes must keep their names regardless.
 * Documentation checked: Tabler Cards and Badges. Focus Now now uses the
 *   documented card status edge; these rules remain for compact Other Work
 *   cards and the hatched ghost treatment only.
 * Removal condition: drop the compact-card rules when Other Work adopts the
 *   Tabler card composition; drop the ghost rule when that state disappears.
 */
.digest-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
  gap: 0.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.digest-card:not(.card) {
  display: block;
  padding: 0.75rem;
  background: var(--tblr-bg-surface);
  border: var(--tblr-border-width) solid var(--tblr-border-color);
  border-left-width: 3px;
  border-radius: var(--tblr-border-radius);
}

.digest-card.card {
  min-width: 0;
}

/* .ribbon-label-*, .digest-card-has-*-ribbons
 * Unmet requirement: issue-label colors are part of the board vocabulary and
 *   must remain exact; Tabler supplies the ribbon geometry but not these five
 *   semantic colors or collision-free positions for simultaneous ribbons.
 * Documentation checked: Tabler Cards / Card ribbons.
 * Removal condition: replace if the upstream label palette or Tabler ribbon
 *   API provides these semantic tokens and multi-ribbon placement.
 */
.digest-card-has-top-ribbons > .card-header {
  padding-top: 2.5rem !important;
}

.digest-card-has-side-ribbons > .card-body {
  padding-inline-end: 3.5rem !important;
}

.ribbon-label-urgent {
  inset-inline-end: 0.75rem;
}

.ribbon-label-focus {
  inset-inline-end: 3.25rem;
  color: #123c27;
  background-color: #8aeeb2;
  border-color: #8aeeb2;
}

.ribbon-label-interruption {
  inset-inline-end: 5.75rem;
  color: #3b2a0d;
  background-color: #e2b569;
  border-color: #e2b569;
}

.ribbon-label-high-value {
  inset-inline-end: 8.25rem;
  color: #332900;
  background-color: #fbca04;
  border-color: #fbca04;
}

.ribbon-label-epic {
  top: 4.75rem;
  color: #fff;
  background-color: #7e53e1;
  border-color: #7e53e1;
}

.ribbon-label-needs-architect {
  top: 7.25rem;
  color: #173b0f;
  background-color: #98fa79;
  border-color: #98fa79;
}

.digest-card-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.5rem;
  font-weight: var(--tblr-font-weight-bold);
}

.digest-card-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: 0.25rem 0.75rem;
}

.digest-card-facts dt {
  font-weight: var(--tblr-font-weight-normal);
}

.digest-card-facts dd {
  margin: 0;
}

.digest-card-ghost {
  border-style: dashed;
  background: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 8px,
    var(--tblr-bg-surface-secondary) 8px,
    var(--tblr-bg-surface-secondary) 16px
  );
}

.digest-card:not(.card).digest-card-warning {
  border-left-color: var(--tblr-warning);
}

.digest-card:not(.card).digest-card-exceeded {
  border-left-color: var(--tblr-danger);
}

.digest-card:not(.card).digest-card-running {
  border-left-color: var(--tblr-success);
}

.digest-card:not(.card).digest-card-today {
  border-left-color: var(--tblr-info);
}

/* .digest-card-progress
 * Unmet requirement: Tabler's card-progress example sizes its inner bar with
 *   an inline width, which the application's CSP forbids. A native progress
 *   element keeps the value semantic and uses the documented card edge.
 * Documentation checked: Tabler Cards / Card progress and HTML progress.
 * Removal condition: replace when Tabler offers a CSP-safe variable or
 *   attribute-driven card-progress implementation.
 */
.digest-card-progress {
  appearance: none;
  display: block;
  width: 100%;
  border: 0;
  background-color: var(--tblr-bg-surface-secondary);
}

.digest-card-progress::-webkit-progress-bar {
  background-color: var(--tblr-bg-surface-secondary);
}

.digest-card-progress-healthy::-webkit-progress-value {
  background-color: var(--tblr-success);
}

.digest-card-progress-attention::-webkit-progress-value {
  background-color: var(--tblr-warning);
}

.digest-card-progress-critical::-webkit-progress-value {
  background-color: var(--tblr-danger);
}

.digest-card-progress-healthy::-moz-progress-bar {
  background-color: var(--tblr-success);
}

.digest-card-progress-attention::-moz-progress-bar {
  background-color: var(--tblr-warning);
}

.digest-card-progress-critical::-moz-progress-bar {
  background-color: var(--tblr-danger);
}

.digest-well {
  margin-bottom: 0.5rem;
  border: var(--tblr-border-width) solid var(--tblr-border-color);
  border-radius: var(--tblr-border-radius);
  background: var(--tblr-bg-surface);
}

.digest-well > .digest-well-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  cursor: pointer;
  list-style: none;
}

.digest-well > .digest-well-summary::-webkit-details-marker {
  display: none;
}

.digest-well > .digest-card-grid,
.digest-well > section,
.digest-well > .update-day {
  padding: 0 1rem 0.75rem;
}

.compass-flag::before {
  content: "⚑";
  color: var(--tblr-warning);
  margin-right: 0.25rem;
}

/* .hovercard-popover
 * Unmet requirement: issue previews now include the Markdown description,
 *   which cannot be read at Bootstrap's compact default popover width.
 * Documentation checked: https://docs.tabler.io/ui/components/popovers.
 * Removal condition: drop if issue descriptions move to an interactive
 *   offcanvas or Tabler provides a wide informational-popover variant.
 */
.hovercard-popover {
  --tblr-popover-max-width: min(38rem, calc(100vw - 2rem));
}

.hovercard-description .markdown > :last-child {
  margin-bottom: 0;
}
