/* ============================================
   Turbo Web Styles - Universal Components
   ============================================

   Universal UI patterns reused across multiple web projects.
   Uses BEM naming convention and CSS custom properties.

   Low-volatility: changes here affect all consuming projects.
   Only add components used across at least two separate projects.
   Dashboard-specific or project-specific styles go in the
   consuming project's own dashboard.css file.
   ============================================ */

/* ============================================
   FORM SELECT (COMPACT)
   ============================================ */

.form-select-compact {
  font-size: var(--font-size-sm);
  padding: var(--spacing-xs) var(--spacing-sm);
  height: var(--input-height-sm);
  border-radius: var(--border-radius-sm);
  background-color: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  color: var(--color-text-primary);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-select-compact:focus {
  border-color: var(--color-border-focus);
  box-shadow: 0 0 0 2px rgba(var(--color-primary-rgb), 0.1);
  outline: none;
}

.form-select-compact:disabled {
  background-color: var(--color-surface-disabled);
  color: var(--color-text-disabled);
  cursor: not-allowed;
}

/* ============================================
   BUTTON DISABLED STATE
   ============================================

   Bootstrap sets `.btn:disabled { pointer-events: none }`, which
   suppresses hover events on the button itself — meaning native
   `title` tooltips never appear, and the user gets no explanation
   for why the button is unusable. Re-enabling pointer events lets
   the tooltip fire while the `disabled` attribute still blocks
   activation. Stronger opacity + `not-allowed` cursor make the
   disabled state visually unambiguous.
   ============================================ */

.btn:disabled,
.btn.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: auto;
}

/* ============================================
   SKELETON LOADER
   ============================================ */

.skeleton {
  background: linear-gradient(
    90deg,
    var(--color-surface-hover) 25%,
    var(--color-surface-active) 50%,
    var(--color-surface-hover) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s ease-in-out infinite;
  border-radius: var(--border-radius-sm);
}

@keyframes skeleton-loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.skeleton--text {
  height: 14px;
  margin-bottom: var(--spacing-sm);
}

.skeleton--title {
  height: 24px;
  width: 60%;
  margin-bottom: var(--spacing-lg);
}

.skeleton--metric {
  height: 48px;
  width: 100%;
  margin-bottom: var(--spacing-md);
}

.skeleton--table-row {
  height: 40px;
  width: 100%;
  margin-bottom: var(--spacing-xs);
}

/* ============================================
   EMPTY STATE
   ============================================ */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-3xl) var(--spacing-xl);
  text-align: center;
  color: var(--color-text-secondary);
}

.empty-state__icon {
  font-size: 48px;
  margin-bottom: var(--spacing-lg);
  opacity: 0.5;
}

.empty-state__message {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-sm);
}

.empty-state__detail {
  color: var(--color-text-secondary);
  margin: 0;
}

.empty-state__action {
  margin-top: var(--spacing-md);
}

/* ============================================
   ERROR STATE
   ============================================ */

.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-2xl) var(--spacing-xl);
  text-align: center;
  color: var(--color-error);
  background-color: rgba(var(--color-error-rgb), 0.05);
  border: var(--border-width) solid var(--color-error);
  border-radius: var(--border-radius-md);
}

.error-state__icon {
  font-size: 32px;
  margin-bottom: var(--spacing-md);
}

.error-state__message {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  margin-bottom: var(--spacing-xs);
}

.error-state__detail {
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
}

/* ============================================
   LOADING INDICATOR
   ============================================ */

.loading-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-2xl);
  color: var(--color-text-secondary);
}

.loading-indicator__text {
  font-size: var(--font-size-sm);
}

/* ============================================
   PAGE HEADER
   ============================================ */

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--spacing-2xl);
  padding: 0 0 var(--spacing-lg);
  background: none;
  border-bottom: var(--border-width) solid var(--color-border);
}

.page-header__title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-primary);
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-sm);
}

.page-header__logo {
  width: 28px;
  height: 28px;
  object-fit: contain;
  flex: 0 0 auto;
}

.page-header__actions {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
}

/* List-filter input. Two homes:
     .page-header__search   — single-grid pages (search lives in page-header actions)
     .card-header__search   — multi-card pages (search lives in card-header per table)
   Fixed width and no shrink so it never crowds out the sibling toggles/buttons;
   the sibling controls also need to keep their single-line labels regardless
   of viewport width. */
.page-header__search,
.card-header__search {
  width: 240px;
  flex: 0 0 auto;
}

.page-header__actions > .form-check-inline,
.page-header__actions > .btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* Bootstrap's .form-check-inline ships with margin-right: 1rem; inside a flex
   container with gap that double-spaces the right side. Let flex gap own all
   spacing between siblings. */
.page-header__actions > .form-check-inline {
  margin-right: 0;
}

@media (max-width: 768px) {
  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spacing-md);
  }

  .page-header__actions {
    width: 100%;
    flex-direction: column;
    gap: var(--spacing-sm);
  }

  .page-header__actions .form-select-compact {
    width: 100%;
  }

  .page-header__search,
  .card-header__search {
    width: 100%;
  }
}

/* ============================================
   SCROLLBAR
   ============================================ */

.scrollbar-thin {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}

.scrollbar-thin::-webkit-scrollbar {
  width: 6px;
}

.scrollbar-thin::-webkit-scrollbar-track {
  background: transparent;
}

.scrollbar-thin::-webkit-scrollbar-thumb {
  background-color: var(--color-border);
  border-radius: 3px;
}

/* ============================================
   APP SHELL (top bar + body row with optional sidebar)

   Structure (used by Portal, Settings, Admin):

     .app-shell                    column flex, viewport-height
       .app-shell__topbar          horizontal bar, sticky top
       .app-shell__body            row flex, fills remaining height
         .app-nav                  optional left rail
         .app-shell__content       column flex, scrolls inside
           .app-shell__main        scrollable content area
           .app-footer             flex footer
   ============================================ */

.app-shell {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

.app-shell__body {
  display: flex;
  flex: 1;
  min-height: 0;
}

.app-shell__content {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.app-shell__main {
  flex: 1;
  overflow-y: auto;
  padding: var(--spacing-2xl);
}

/* ============================================
   APP SHELL TOPBAR
   ============================================ */

.app-shell__topbar {
  height: 56px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--spacing-lg);
  padding: 0 var(--spacing-xl);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.app-shell__topbar-start {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  min-width: 0;
  flex: 1 1 auto;
}

.app-shell__topbar-end {
  display: flex;
  align-items: center;
  gap: var(--spacing-lg);
  flex: 0 0 auto;
}

.app-shell__brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  text-decoration: none;
  color: inherit;
}

.app-shell__brand:hover {
  text-decoration: none;
  color: inherit;
}

.app-shell__brand-logo {
  width: 24px;
  height: 24px;
}

.app-shell__section {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
  text-decoration: none;
  white-space: nowrap;
  margin-left: var(--spacing-sm);
}

a.app-shell__section:hover {
  color: var(--color-text-primary);
  text-decoration: none;
}

/* Continuation crumbs that follow .app-shell__section. Same size as the section
   anchor, but normal weight + secondary color so the section reads as the
   dominant element and the trailing crumbs read as context. */
.app-shell__crumb,
.app-shell__crumb-sep {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-normal);
  color: var(--color-text-secondary);
  white-space: nowrap;
}

.app-shell__crumb-sep {
  color: var(--color-text-tertiary);
  margin: 0 var(--spacing-xs);
}

a.app-shell__crumb {
  text-decoration: none;
}

a.app-shell__crumb:hover {
  color: var(--color-text-primary);
  text-decoration: none;
}

.app-shell__topbar-link {
  text-decoration: none;
  color: var(--color-text-primary);
  font-weight: 600;
  font-size: var(--font-size-base);
}

.app-shell__topbar-link:hover {
  color: var(--color-link);
}

.app-shell__theme-toggle {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-secondary);
  font-size: var(--font-size-base);
  padding: var(--spacing-xs);
  border-radius: var(--border-radius-sm);
  flex-shrink: 0;
  line-height: 1;
}

.app-shell__theme-toggle:hover {
  color: var(--color-text-primary);
  background: var(--color-surface-hover);
}

/* Theme-icon asset swap — driven by --asset-display-*-inline tokens (see theme.css). */
.app-shell__theme-icon--light { display: var(--asset-display-light-inline); }
.app-shell__theme-icon--dark  { display: var(--asset-display-dark-inline); }

@media (max-width: 960px) {
  .app-shell__topbar {
    padding: 0 var(--spacing-md);
  }
}

/* ============================================
   ACCOUNT MENU (top-bar identity dropdown)
   ============================================ */

.account-menu {
  position: relative;
}

.account-menu__trigger {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  padding: var(--spacing-xs) 0;
  border: none;
  background: transparent;
  cursor: pointer;
  font: inherit;
  color: var(--color-text-primary);
  font-size: var(--font-size-base);
  font-weight: 600;
}

.account-menu__trigger:hover {
  color: var(--color-link);
}

.account-menu__name {
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  min-width: 220px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius-md);
  box-shadow: var(--shadow-md);
  z-index: 201;
  display: none;
  padding: var(--spacing-xs) 0;
}

.account-menu--open .account-menu__panel {
  display: block;
}

/* Transparent fullscreen overlay — captures clicks anywhere off the panel and
   closes the dropdown. Sits above page content but below the panel itself.
   Same pattern as .portal-ctx-menu__backdrop. */
.account-menu__backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  cursor: default;
}

.account-menu__item {
  display: block;
  padding: var(--spacing-sm) var(--spacing-md);
  color: var(--color-text-primary);
  text-decoration: none;
  font-size: var(--font-size-base);
  white-space: nowrap;
}

.account-menu__item:hover {
  background: var(--color-surface-hover);
  color: var(--color-text-primary);
}

.account-menu__divider {
  height: 1px;
  background: var(--color-border);
  margin: var(--spacing-xs) 0;
}

/* ============================================
   APP NAV (left-edge sidebar)
   ============================================ */

.app-nav {
  display: flex;
  flex-direction: column;
  width: 220px;
  flex-shrink: 0;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  overflow-y: auto;
}

/* Brand and theme controls used to live in a sidebar header (.app-nav__header /
   .app-nav__title / .app-nav__theme-toggle). They moved to the unified topbar
   (.app-shell__brand, .app-shell__section, .app-shell__theme-toggle). */

/* Sidebar footer — brand mark on the left, version right-aligned, single row
   pinned at the bottom of .app-nav via position:sticky so it stays visible
   even when the nav scrolls. */
.app-nav__footer {
  position: sticky;
  bottom: 0;
  margin-top: auto;
  padding: var(--spacing-md);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm);
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
}

.app-nav__footer-logo {
  display: inline-flex;
  flex: 0 1 auto;
  min-width: 0;
  opacity: 0.35;
  transition: opacity var(--transition-fast);
}

.app-nav__footer-logo:hover {
  opacity: 0.6;
}

.app-nav__footer-watermark {
  display: block;
  width: 100%;
  max-width: 120px;
  height: auto;
}

/* Watermark asset swap — driven by --asset-display-* tokens (see theme.css). */
.app-nav__footer-watermark--light { display: var(--asset-display-light); }
.app-nav__footer-watermark--dark  { display: var(--asset-display-dark); }

.app-nav__footer-version {
  flex-shrink: 0;
  font-size: var(--font-size-xs);
  color: var(--color-text-tertiary);
  white-space: nowrap;
}

/* ============================================
   APP SIDENAV (container for nav sections)
   ============================================ */

.app-sidenav {
  display: flex;
  flex-direction: column;
  padding: var(--spacing-md) 0;
  flex: 1;
}

/* ============================================
   NAV SECTION (collapsible nav group)
   ============================================ */

.nav-section__header {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  width: 100%;
  padding: var(--spacing-xs) var(--spacing-lg);
  margin-top: var(--spacing-md);
  color: var(--color-text-secondary);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.nav-section__header:hover {
  color: var(--color-text-primary);
}

.nav-section__title-link {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  flex: 1;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.nav-section__title-link:hover,
.nav-section__title-link:focus {
  color: inherit;
  text-decoration: none;
}

.nav-section__title-link.active {
  color: var(--color-primary);
}

.nav-section__title-link--static {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  flex: 1;
  min-width: 0;
}

.nav-section__icon {
  font-size: var(--font-size-sm);
  width: 14px;
  text-align: center;
  flex-shrink: 0;
}

.nav-section__toggle {
  margin-left: auto;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: inherit;
  display: flex;
  align-items: center;
}

.nav-section__chevron {
  font-size: 10px;
}

.nav-section__items {
  display: flex;
  flex-direction: column;
}

.nav-section__items a {
  display: block;
  padding: 6px var(--spacing-lg) 6px calc(var(--spacing-lg) + 14px + var(--spacing-xs));
  color: var(--color-text-primary);
  font-size: 13px;
  text-decoration: none;
  border-left: 2px solid transparent;
  transition: background 150ms, border-color 150ms;
}

.nav-section__items a:hover {
  background: rgba(var(--color-primary-rgb), 0.06);
}

.nav-section__items a.active {
  color: var(--color-primary);
  border-left-color: var(--color-primary);
  background: rgba(var(--color-primary-rgb), 0.08);
  font-weight: 600;
}

/* ============================================
   NAV UNDERLINE — color override

   Bootstrap's default has active = emphasis (white-ish) and inactive = link
   color (blue), which inverts how the sidebar nav signals "selected" (active
   = brand, inactive = default text). Re-map so both navs follow the same
   convention: active item gets the brand color, inactive items use the
   default text color.
   ============================================ */

.nav-underline {
  --bs-nav-link-color: var(--color-text-primary);
  --bs-nav-link-hover-color: var(--color-primary);
  --bs-nav-underline-link-active-color: var(--color-primary);
}

/* ============================================
   APP FOOTER
   ============================================ */

.app-footer {
  display: flex;
  align-items: center;
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-surface-hover);
  border-top: 1px solid var(--color-border);
  flex-shrink: 0;
}

.app-footer__spacer {
  flex: 1;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

.app-footer__logo {
  display: inline-block;
  text-decoration: none;
  opacity: 0.25;
  transition: opacity var(--transition-fast);
}

.app-footer__logo:hover {
  opacity: 0.4;
}

.app-footer__watermark {
  display: block;
  width: 125px;
  height: auto;
}

/* Watermark asset swap — driven by --asset-display-* tokens (see theme.css). */
.app-footer__watermark--light { display: var(--asset-display-light); }
.app-footer__watermark--dark  { display: var(--asset-display-dark); }

.app-footer__version {
  font-size: var(--font-size-sm);
  color: var(--color-text-tertiary);
}

/* ============================================
   LOGIN PAGE + BOX
   ============================================ */

.login-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: var(--color-background);
}

.login-page__center {
  width: 100%;
  max-width: 380px;
  padding: var(--spacing-lg);
}

.login-box {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius-md);
  padding: var(--spacing-2xl);
  box-shadow: var(--shadow-sm);
}

.login-box__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-2xl);
  text-align: center;
}

.login-box__logo {
  width: 40px;
  height: 40px;
}

.login-box__title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
  margin: 0;
}

