/* ==========================================================================
   Accounting_PRO — application theme
   Layered on top of Bootstrap 5.3 (wwwroot/lib/bootstrap). The layout is a
   top navigation bar "app shell"; every colour, radius and shadow is a token
   so the palette can be changed in one place.
   1. tokens    2. base    3. shell/top bar    4. top bar menu
   5. cards/tiles    6. tables    7. forms    8. buttons/badges/alerts
   9. SweetAlert2    10. utilities/print
   ========================================================================== */

/* ---------------------------------------------------------------- 1. tokens */
:root {
  --app-sans: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --app-ink: #0f172a;
  --app-ink-soft: #475569;
  --app-muted: #6b7a90;
  --app-bg: #f4f6fb;
  --app-surface: #ffffff;
  --app-surface-soft: #f8fafc;
  --app-line: #e6eaf2;
  --app-line-soft: #eef1f7;
  --app-primary: #4f46e5;
  --app-primary-ink: #4338ca;
  --app-primary-soft: #eef2ff;
  --app-primary-ring: rgba(79, 70, 229, .18);
  --app-success-soft: #e7f7ef;
  --app-success-ink: #0b6a4a;
  --app-warning-soft: #fdf3e3;
  --app-warning-ink: #8a5108;
  --app-danger-soft: #fdecea;
  --app-danger-ink: #a82419;
  --app-info-soft: #e7f4f8;
  --app-info-ink: #0b5b72;

  /* Solid status pills (badge.bg-*). Saturated fills + white text so a
     document's state reads at a glance inside a dense table row.
     Every colour is >= 4.5:1 against white text. */
  --app-status-primary: #4f46e5;
  --app-status-neutral: #475569;
  --app-status-success: #047857;
  --app-status-info: #0369a1;
  --app-status-warning: #b45309;
  --app-status-danger: #d92d20;
  --app-status-dark: #1e293b;
  --app-status-ring: rgba(15, 23, 42, .24);
  --app-status-line: rgba(255, 255, 255, .28);
  --app-radius: 16px;
  --app-radius-sm: 10px;
  --app-radius-lg: 22px;
  --app-shadow-xs: 0 1px 2px rgba(15, 23, 42, .05);
  --app-shadow-sm: 0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
  --app-shadow: 0 20px 45px -28px rgba(15, 23, 42, .45);
  --app-drawer-w: 300px;
  --app-topbar-h: 60px;
  --app-navbar-from: #141d38;
  --app-navbar-to: #0b1224;

  /* Income vs expenses chart (Views/Dashboard/Index.cshtml): the three
     series of the stacked bars. They are tokens like every other colour —
     wwwroot/js/dashboard-chart.js reads them back at run time, so the
     palette of the chart is changed here and nowhere else. */
  --app-chart-income: #3b82f6;
  --app-chart-expense: #22c55e;
  --app-chart-net: #f97316;

  /* Bootstrap theme mapping */
  --bs-font-sans-serif: var(--app-sans);
  --bs-body-font-family: var(--app-sans);
  --bs-body-bg: var(--app-bg);
  --bs-body-color: var(--app-ink);
  --bs-border-color: var(--app-line);
  --bs-border-radius: var(--app-radius-sm);
  --bs-border-radius-sm: 8px;
  --bs-border-radius-lg: var(--app-radius);
  --bs-primary: var(--app-primary);
  --bs-primary-rgb: 79, 70, 229;
  --bs-link-color: var(--app-primary);
  --bs-link-color-rgb: 79, 70, 229;
  --bs-link-hover-color: var(--app-primary-ink);
  --bs-secondary-color: var(--app-muted);
  --bs-emphasis-color: var(--app-ink);
  --bs-focus-ring-color: var(--app-primary-ring);
  --bs-heading-color: var(--app-ink);
}

/* ------------------------------------------------------------------ 2. base */
html {
  font-size: 15px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

body {
  margin: 0;
  background-color: var(--app-bg);
  color: var(--app-ink);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
  font-weight: 650;
  letter-spacing: -.018em;
  color: var(--app-ink);
}

a {
  text-decoration: none;
}

a:hover, a:focus {
  text-decoration: none;
}

.text-muted {
  color: var(--app-muted) !important;
}

.small, small {
  font-size: .82rem;
}

code {
  color: var(--app-primary-ink);
  background-color: var(--app-primary-soft);
  padding: .12rem .4rem;
  border-radius: 6px;
  font-size: .85em;
}

hr {
  border-top-color: var(--app-line);
  opacity: 1;
}

* {
  scrollbar-width: thin;
  scrollbar-color: #ccd4e2 transparent;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-thumb {
  background-color: #ccd4e2;
  border: 3px solid transparent;
  border-radius: 999px;
  background-clip: content-box;
}

/* ----------------------------------------------------- 3. shell and top bar */
/* One column: a sticky navigation bar, then the page, then the footer. The
   old left rail is gone, so wide content — registers, ledgers, aged reports
   — gets the whole window width instead of the space beside the sidebar. */
.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* The bar carries the brand, the organisation switcher, the menu groups and
   the account menu. It reuses the palette the sidebar had (the same dark navy
   gradient), so the theme is unchanged. In the drawer range (below 992px) the
   bar's items wrap onto a second line; from 992px up it is a single row and it
   is the menu — not the account menu — that gives up room instead (section 4). */
.app-topbar {
  position: sticky;
  top: 0;
  z-index: 1030;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  min-height: var(--app-topbar-h);
  padding: .45rem clamp(.85rem, 2vw, 1.6rem);
  color: #cbd5e6;
  background-image: linear-gradient(90deg, var(--app-navbar-from) 0%, var(--app-navbar-to) 100%);
  border-bottom: 1px solid rgba(148, 163, 184, .16);
}

@media (min-width: 992px) {
  /* One row, always. The account badge is the last item on the bar and must
     never be pushed onto a line of its own; the menu is the flexible part, so
     a long menu wraps inside its own box instead (section 4 packs it). */
  .app-topbar {
    flex-wrap: nowrap;
  }
}

.app-topbar-org {
  flex: none;
}

/* Drawer head — brand + close button. Bootstrap hides .offcanvas-header from
   992px up, which is exactly where the bar shows the menu inline instead. */
.app-topnav-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  flex: none;
  padding: 1rem 1.1rem;
  border-bottom: 1px solid rgba(148, 163, 184, .16);
}

.app-brand {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex: none;
  color: #fff;
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: -.02em;
}

.app-brand:hover, .app-brand:focus {
  color: #fff;
}

.app-brand-mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 11px;
  color: #fff;
  background-image: linear-gradient(135deg, #6366f1, #22d3ee);
  box-shadow: 0 10px 20px -10px rgba(99, 102, 241, .9);
}

.app-brand-mark .app-icon {
  width: 19px;
  height: 19px;
}

/* The brand artwork (wwwroot/img/logo-cloud.svg) is the tile: it brings its own
   gradient background, so the drawn one is switched off and only a soft glow
   is kept underneath. `border-radius: 22%` matches the artwork's own corner
   radius (112 of 512) at any size. */
.app-brand-mark.is-logo {
  background-image: none;
  box-shadow: 0 10px 22px -12px rgba(63, 162, 255, .9);
}

.app-brand-mark > img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 22%;
}

.app-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.app-brand-sub {
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .04em;
  color: #8b98b5;
}

/* The menu column is the only part of the drawer that scrolls: it may shrink
   (min-height: 0 — a flex item's automatic minimum would otherwise be its
   content height) so a long menu stays inside the drawer. From 992px up the
   same element is the bar's inline menu — see section 4. */
.app-topnav-body {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  flex: 1 1 auto;
  min-height: 0;
  padding: .9rem .9rem 1.2rem;
  overflow-y: auto;
  overflow-x: hidden;
  /* The global scrollbar colours are tuned for light panels. */
  scrollbar-color: rgba(148, 163, 184, .45) transparent;
}

.app-topnav-body::-webkit-scrollbar-thumb {
  background-color: rgba(148, 163, 184, .45);
}

/* The menu panel. Bootstrap's offcanvas-lg makes this element a static,
   visible part of the bar from 992px up; below that it slides in from the
   left wearing the palette's navy gradient, exactly like the old sidebar. */
.app-topnav {
  --bs-offcanvas-width: min(var(--app-drawer-w), 86vw);
  --bs-offcanvas-bg: var(--app-navbar-to);
  --bs-offcanvas-color: #cbd5e6;
  --bs-offcanvas-border-color: rgba(148, 163, 184, .16);
  color: #cbd5e6;
  background-image: linear-gradient(180deg, var(--app-navbar-from) 0%, var(--app-navbar-to) 100%);
}

@media (min-width: 992px) {
  .app-topnav {
    /* Bootstrap's navbar does this for .offcanvas-lg at its breakpoint; the
       bar is not a .navbar, so the same rules are declared here. */
    position: static;
    z-index: auto;
    flex: 1 1 auto;
    min-width: 0;
    width: auto !important;
    height: auto !important;
    visibility: visible !important;
    background-color: transparent !important;
    background-image: none !important;
    border: 0 !important;
    transform: none !important;
    transition: none;
  }

  .app-topnav .app-topnav-head {
    display: none;
  }

  .app-topnav .app-topnav-body {
    display: flex;
    flex-grow: 1;
    min-width: 0;
    padding: 0;
    overflow: visible;
    background-color: transparent;
  }
}

/* --------------------------------------------------------- 4. top bar menu */
/* One menu, two shapes: a wrapping row of dropdown groups on desktop and an
   accordion inside the drawer below 992px. Only these rules change — the
   markup is one list either way. */
.app-nav {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.app-nav-item {
  min-width: 0;
}

/* Group toggles are <button>s, links are <a>s — reset both to the same look. */
.app-nav-link {
  display: flex;
  align-items: center;
  gap: .45rem;
  width: 100%;
  padding: .5rem .7rem;
  border: 0;
  border-radius: 10px;
  background-color: transparent;
  color: #c2cbe0;
  font-size: .875rem;
  font-weight: 600;
  line-height: 1.25;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}

.app-nav-link:hover,
.app-nav-link:focus {
  background-color: rgba(148, 163, 184, .18);
  color: #fff;
}

.app-nav-link:focus-visible {
  outline: 2px solid rgba(199, 210, 254, .85);
  outline-offset: 2px;
}

/* The current module keeps the highlight the old sidebar used. */
.app-nav-link.is-active {
  color: #fff;
  background-image: linear-gradient(135deg, rgba(99, 102, 241, .95), rgba(79, 70, 229, .88));
  box-shadow: 0 14px 24px -18px rgba(99, 102, 241, 1);
}

.app-nav-caret {
  width: 15px;
  height: 15px;
  flex: none;
  opacity: .7;
  transition: transform .15s ease;
}

.app-nav-link.show .app-nav-caret {
  transform: rotate(180deg);
}

/* A group's menu: a light card hanging off the bar, coloured with the theme's
   own tokens so the palette is untouched. `data-bs-display="static"` on the
   toggle keeps Bootstrap from positioning it with Popper, so `top`/`left`
   come from the stylesheet — which is what lets the very same markup also
   open inline inside the drawer. */
.app-menu {
  --bs-dropdown-min-width: 15rem;
  --bs-dropdown-spacer: .4rem;
  --bs-dropdown-border-radius: 14px;
  --bs-dropdown-link-hover-bg: var(--app-primary-soft);
  --bs-dropdown-link-hover-color: var(--app-primary-ink);
  --bs-dropdown-link-active-bg: var(--app-primary);
  padding: .4rem;
  border: 1px solid var(--app-line);
  border-radius: 14px;
  box-shadow: var(--app-shadow);
}

.app-menu .dropdown-header {
  padding: .45rem .6rem .25rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.app-menu .dropdown-item {
  display: flex;
  align-items: center;
  gap: .6rem;
  border-radius: 9px;
  font-size: .875rem;
  font-weight: 500;
}

.app-menu .dropdown-item .app-icon {
  width: 17px;
  height: 17px;
  flex: none;
  color: var(--app-muted);
  opacity: .75;
}

.app-menu .dropdown-item.is-active {
  color: var(--app-primary-ink);
  background-color: var(--app-primary-soft);
  font-weight: 600;
}

.app-menu .dropdown-item.is-active .app-icon {
  color: var(--app-primary);
  opacity: 1;
}

.app-menu .dropdown-divider {
  margin: .35rem .2rem;
}

@media (min-width: 992px) {
  /* The bar's inline row of groups. Wrapping keeps every group reachable on a
     narrower window instead of hiding the last one. */
  .app-nav {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: .15rem;
  }

  .app-nav-link {
    width: auto;
  }
}

/* Laptop screens (992–1599px): the menu, the organisation pill and the account
   badge only just fit on the bar's single row, so everything that is not the
   navigation label itself gives up a little room. Wide desktops get the roomy
   version back. */
@media (min-width: 992px) and (max-width: 1599.98px) {
  .app-nav {
    gap: .1rem;
  }

  .app-nav-link {
    padding-inline: .5rem;
  }

  /* "Current organisation" is a caption, not information: it is the first
     thing to go when the row is tight, leaving a single-line pill. The signed
     in user's name is dropped the same way (see .app-pill-text in section 5).
     Scoped to the bar so it outranks the pill's own display rule below. */
  .app-topbar .app-pill-sub {
    display: none;
  }
}

@media (max-width: 991.98px) {
  /* Inside the drawer a group opens in place — an accordion rather than a
     floating card that the panel would clip. */
  .app-topnav .app-menu {
    position: static !important;
    float: none;
    width: 100%;
    min-width: 0;
    margin: 0 0 .4rem;
    padding: .2rem 0 .3rem .85rem;
    border: 0;
    border-left: 2px solid rgba(148, 163, 184, .3);
    border-radius: 0;
    background-color: transparent;
    background-image: none;
    box-shadow: none;
  }

  .app-topnav .app-menu .dropdown-header {
    color: #7885a3;
  }

  .app-topnav .app-menu .dropdown-item {
    color: #c2cbe0;
  }

  .app-topnav .app-menu .dropdown-item .app-icon {
    color: currentColor;
  }

  .app-topnav .app-menu .dropdown-item:hover,
  .app-topnav .app-menu .dropdown-item:focus {
    background-color: rgba(148, 163, 184, .18);
    color: #fff;
  }

  .app-topnav .app-menu .dropdown-item.is-active {
    color: #fff;
    background-color: transparent;
    background-image: linear-gradient(135deg, rgba(99, 102, 241, .95), rgba(79, 70, 229, .88));
  }
}

/* ------------------------------------------ 5. bar controls and page body */
.app-topbar-actions {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-left: auto;
  /* The badge keeps its size — the menu shrinks before the account menu does. */
  flex: none;
}

/* The drawer toggle and the account / organisation pills live on the dark
   bar, so they are tinted for it: a translucent white surface with the
   palette's own colours on hover. The menus they open stay light. */
.app-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: none;
  padding: 0;
  border: 1px solid rgba(148, 163, 184, .3);
  border-radius: 11px;
  background-color: rgba(255, 255, 255, .08);
  color: #e2e8f0;
  transition: border-color .15s ease, color .15s ease, background-color .15s ease;
}

.app-icon-btn:hover, .app-icon-btn:focus {
  border-color: rgba(199, 210, 254, .6);
  color: #fff;
  background-color: rgba(255, 255, 255, .16);
}

.app-pill {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  /* Matches the account pill, whose avatar sets the height: a single-line
     organisation pill in the tight laptop bar stays level with it. */
  min-height: 44px;
  padding: .34rem .7rem;
  border: 1px solid rgba(148, 163, 184, .3);
  border-radius: 999px;
  background-color: rgba(255, 255, 255, .08);
  color: #e2e8f0;
  font-size: .84rem;
  font-weight: 600;
  line-height: 1.2;
  transition: border-color .15s ease, background-color .15s ease;
}

.app-pill:hover, .app-pill:focus {
  color: #fff;
  border-color: rgba(199, 210, 254, .6);
  background-color: rgba(255, 255, 255, .16);
}

.app-pill .app-icon {
  width: 17px;
  height: 17px;
  opacity: .8;
}

.app-pill-sub {
  display: block;
  font-size: .7rem;
  font-weight: 500;
  color: #93a1bb;
}

/* The signed-in user's name beside the avatar. It is the first thing the bar
   drops as the window narrows: on laptop screens (up to 1600px — 1280/1366/
   1440/1536 logical widths) the avatar badge alone identifies the account, so
   the menu groups stay on one line instead of wrapping. Wide desktops get the
   name back. The email is clamped so a long address can never squeeze the
   menu even there. */
.app-pill-text {
  display: none;
  flex-direction: column;
  min-width: 0;
}

.app-pill-name,
.app-pill-sub {
  display: block;
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 1600px) {
  .app-pill-text {
    display: flex;
  }
}

/* Anonymous visitors get text buttons ("Log in") on the same dark bar. */
.app-topbar-actions .btn-link,
.app-topbar-actions .btn-link:visited {
  color: #e2e8f0;
}

.app-topbar-actions .btn-link:hover,
.app-topbar-actions .btn-link:focus {
  color: #fff;
}

.app-avatar {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 50%;
  color: #fff;
  font-size: .76rem;
  font-weight: 700;
  text-transform: uppercase;
  background-image: linear-gradient(135deg, #4f46e5, #0ea5e9);
}

.app-content {
  flex: 1 1 auto;
  width: 100%;
  padding: clamp(1.1rem, 2.4vw, 2rem) clamp(1rem, 2.4vw, 2rem) 3rem;
}

.app-footer {
  padding: 1rem clamp(1rem, 2.4vw, 2rem);
  border-top: 1px solid var(--app-line);
  background-color: #fff;
  font-size: .79rem;
  color: var(--app-muted);
}

/* ------------------------------------------------------- 6. page furniture */
/* `.page` fills the whole main panel, so wide content — invoice/bill registers,
   the ledger, aged reports, statements, details pages — gets every pixel
   between the sidebar and the window edge instead of a centred column.
   Single-column screens that read better as a narrow card opt back in with
   `.page-narrow` (a class, not a hidden cap, so a page can opt out per view). */
.page {
  width: 100%;
  max-width: none;
  margin-inline: auto;
}

/* Opt-in readable column for form-shaped pages (one card, centred). */
.page-narrow {
  max-width: 1180px;
}

/* Kept as the explicit "no cap" alias — full width is now the default. */
.page-wide {
  max-width: none;
}

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

/* Product mark beside a page title — the dashboard opens with the brand
   artwork (wwwroot/img/logo-cloud.svg) next to the organisation name. */
.page-header-brand {
  display: flex;
  align-items: center;
  gap: .85rem;
}

.page-header-logo {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 22%;
  box-shadow: 0 14px 26px -16px rgba(63, 162, 255, .9);
}

.page-title {
  margin: 0;
  font-size: clamp(1.2rem, 1.6vw, 1.5rem);
  font-weight: 700;
  letter-spacing: -.022em;
}

.page-subtitle {
  margin: .3rem 0 0;
  font-size: .86rem;
  color: var(--app-muted);
}

.page-subtitle .badge {
  vertical-align: middle;
}

.page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

.page-note {
  margin: 1.25rem 0 0;
  font-size: .8rem;
  color: var(--app-muted);
}

.page-section-title {
  margin: 0 0 .85rem;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--app-muted);
}

/* -------------------------------------------------------- 7. cards and tiles */
.card,
.app-card {
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface);
  box-shadow: var(--app-shadow-sm);
}

.card-header {
  padding: .9rem 1.15rem;
  border-bottom: 1px solid var(--app-line-soft);
  background-color: #fff;
  font-weight: 600;
}

.card-header:first-child {
  border-top-left-radius: var(--app-radius);
  border-top-right-radius: var(--app-radius);
}

.card-footer {
  padding: .85rem 1.15rem;
  border-top: 1px solid var(--app-line-soft);
  background-color: #fff;
  font-size: .82rem;
}

.card-footer:last-child {
  border-bottom-left-radius: var(--app-radius);
  border-bottom-right-radius: var(--app-radius);
}

.card-body {
  padding: 1.15rem;
}

.app-panel {
  padding: 1rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-sm);
  background-color: var(--app-surface-soft);
}

.filter-card {
  padding: 1rem;
  margin-bottom: 1.15rem;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: .85rem;
  margin-bottom: 1.35rem;
}

.stat {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface);
  box-shadow: var(--app-shadow-sm);
}

.stat-label {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.stat-value {
  font-size: 1.28rem;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
}

.stat-meta {
  font-size: .78rem;
  color: var(--app-muted);
}

/* Financial summary of the dashboard (Views/Dashboard/Index.cshtml): the
   KPI cards above the module tiles. Mobile first — two cards per row on a
   phone, which is the shape the row is designed around, and four on a wide
   screen so the four period figures sit on one line.

   Two grids, not one: the receivables / payables pair is its own grid so
   each card can span two columns and line up under the period figures.
   That means the gap between the two rows has to be stated here as well —
   a gap is only ever applied INSIDE the grid that declares it, so two
   stacked grids sit flush against each other however large their own gap
   is. Keep the .kpi-grid + .kpi-grid value in step with the gap beside it.

   Each card carries an accent of its own: a hairline gradient across the
   top, an icon chip and a soft wash in the top corner. That is what makes
   six figures readable at a glance — the numbers still do the work, the
   colour only tells them apart. */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .85rem;
}

/* The row gap between the period figures and the open-document figures. */
.kpi-grid + .kpi-grid {
  margin-top: .85rem;
}

@media (min-width: 992px) {
  .kpi-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
  }

  .kpi-grid + .kpi-grid {
    margin-top: 1rem;
  }

  /* Receivables / payables: two cards of the same width as the four above,
     so the two rows line up on a wide screen. */
  .kpi-grid-two > .kpi-card {
    grid-column: span 2;
  }
}

.kpi-card {
  --kpi-accent: var(--app-primary);
  --kpi-soft: rgba(79, 70, 229, .14);

  position: relative;
  display: flex;
  flex-direction: column;
  gap: .35rem;
  min-width: 0;
  padding: 1rem 1.05rem 1.05rem;
  overflow: hidden;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface);
  background-image: radial-gradient(125% 105% at 100% 0%, var(--kpi-soft) 0%, transparent 62%);
  box-shadow: var(--app-shadow-sm);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}

/* The accent hairline. */
.kpi-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background-image: linear-gradient(90deg, var(--kpi-accent), transparent 90%);
}

.kpi-card:hover {
  transform: translateY(-2px);
  border-color: #d8ddef;
  box-shadow: var(--app-shadow);
}

/* One accent per figure: income green, costs slate, the result in the brand
   indigo, cash blue, money owed to the organisation amber and money it owes
   red. The wash is the same colour at a fraction of the strength, so the
   card reads as tinted rather than as a block of colour. */
.kpi-card.is-income {
  --kpi-accent: var(--app-status-success);
  --kpi-soft: rgba(4, 120, 87, .14);
}

.kpi-card.is-expense {
  --kpi-accent: var(--app-status-neutral);
  --kpi-soft: rgba(71, 85, 105, .12);
}

.kpi-card.is-profit {
  --kpi-accent: var(--app-primary);
  --kpi-soft: rgba(79, 70, 229, .15);
}

.kpi-card.is-cash {
  --kpi-accent: var(--app-status-info);
  --kpi-soft: rgba(3, 105, 161, .13);
}

.kpi-card.is-receivable {
  --kpi-accent: var(--app-status-warning);
  --kpi-soft: rgba(180, 83, 9, .14);
}

.kpi-card.is-payable {
  --kpi-accent: var(--app-status-danger);
  --kpi-soft: rgba(217, 45, 32, .12);
}

.kpi-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-bottom: .2rem;
  border-radius: 11px;
  color: var(--kpi-accent);
  background-color: var(--kpi-soft);
}

.kpi-icon .app-icon {
  width: 18px;
  height: 18px;
}

.kpi-label {
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.kpi-value {
  font-size: clamp(1.25rem, 4.8vw, 1.7rem);
  font-weight: 750;
  letter-spacing: -.025em;
  line-height: 1.1;
  color: var(--app-ink);
  /* Money reads better in a fixed-width figure: two cards of one row line
     their digits up instead of drifting with the glyph widths. */
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.kpi-value.is-positive {
  color: var(--app-success-ink);
}

.kpi-value.is-negative {
  color: var(--app-danger-ink);
}

.kpi-meta {
  margin-top: auto;
  font-size: .76rem;
  color: var(--app-muted);
}

/* A change against the period before reads as a pill, so a row of cards
   shows direction before it shows text. The costs of the period keep the
   arrow but not the colour: a rise there is neither good nor bad on its
   own, and painting it green would say it was. */
.kpi-meta.is-up,
.kpi-meta.is-down {
  align-self: flex-start;
  padding: .1rem .5rem;
  border-radius: 999px;
  font-weight: 600;
}

.kpi-meta.is-up {
  color: var(--app-success-ink);
  background-color: var(--app-success-soft);
}

.kpi-meta.is-down {
  color: var(--app-danger-ink);
  background-color: var(--app-danger-soft);
}

/* Income vs expenses chart (Views/Dashboard/Index.cshtml): the stacked
   monthly bars directly under the KPI cards.

   The plot area is given its height here rather than by the script, so the
   card reserves the space before Chart.js draws into it and the page never
   shifts under the reader's cursor (no layout shift, no spinner). */
.chart-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.15rem;
  margin-bottom: 1.5rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface);
  box-shadow: var(--app-shadow-sm);
}

.chart-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: .75rem;
}

.chart-title {
  margin: 0;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--app-ink);
}

.chart-subtitle {
  margin: .25rem 0 0;
  font-size: .8rem;
  color: var(--app-muted);
}

/* The totals of the three series as text: the card still says what it
   shows when the canvas is read out by a screen reader or never drawn. */
.chart-totals {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.1rem;
  font-size: .8rem;
  color: var(--app-ink-soft);
}

.chart-totals .chart-dot {
  display: inline-block;
  width: .55rem;
  height: .55rem;
  margin-right: .35rem;
  border-radius: 999px;
  vertical-align: baseline;
  background-color: var(--app-muted);
}

.chart-totals .chart-dot.is-income {
  background-color: var(--app-chart-income);
}

.chart-totals .chart-dot.is-expense {
  background-color: var(--app-chart-expense);
}

.chart-totals .chart-dot.is-net {
  background-color: var(--app-chart-net);
}

.chart-totals strong {
  font-weight: 650;
  color: var(--app-ink);
  font-variant-numeric: tabular-nums;
}

/* The filter row: the recommended windows on one line, Apply on the end.
   The two dates only appear for a custom range (see the small script in the
   view) and wrap onto a line of their own on a phone. */
.chart-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: .65rem;
  padding: .8rem .9rem;
  border: 1px solid var(--app-line-soft);
  border-radius: var(--app-radius-sm);
  background-color: var(--app-surface-soft);
}

.chart-filter-field {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  min-width: 0;
}

.chart-filter-field > .form-label {
  margin: 0;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.chart-filter-field .form-select,
.chart-filter-field .form-control {
  min-width: 10.5rem;
}

/* The plot area: tall enough to read six bars, short enough to keep the
   tiles below within a scroll of the cards. */
.chart-frame {
  position: relative;
  height: clamp(230px, 38vw, 320px);
}

.chart-frame canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* The same months as a table. It is revealed by the view's noscript rule when
   there is no JavaScript to draw with, and by the script itself when the
   payload cannot be read — so a chart that cannot be drawn is data on the
   screen rather than a chart-shaped hole. */
.chart-fallback {
  display: none;
  overflow-x: auto;
}

.chart-fallback.is-visible {
  display: block;
}

.tile {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 1.15rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface);
  box-shadow: var(--app-shadow-sm);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}

.tile:hover {
  transform: translateY(-2px);
  border-color: #d8ddef;
  box-shadow: var(--app-shadow);
}

.tile-icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin-bottom: .85rem;
  border-radius: 13px;
  background-color: var(--app-primary-soft);
  color: var(--app-primary);
}

.tile-icon .app-icon {
  width: 21px;
  height: 21px;
}

/* Landing tiles lead with a differently coloured glyph each, so the four
   capabilities read apart at a glance (Views/Home/Index.cshtml). The base
   .tile-icon (primary) is unchanged for every other screen. */
.tile-icon.is-info {
  background-color: var(--app-info-soft);
  color: var(--app-info-ink);
}

.tile-icon.is-success {
  background-color: var(--app-success-soft);
  color: var(--app-success-ink);
}

.tile-icon.is-warning {
  background-color: var(--app-warning-soft);
  color: var(--app-warning-ink);
}

.tile-title {
  margin: 0 0 .3rem;
  font-size: 1rem;
  font-weight: 650;
}

.tile-text {
  margin: 0 0 1rem;
  font-size: .85rem;
  color: var(--app-muted);
}

.tile-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: auto;
}

.empty-state {
  padding: 2.5rem 1.25rem;
  text-align: center;
  color: var(--app-muted);
}

.empty-state .app-icon {
  width: 34px;
  height: 34px;
  margin-bottom: .6rem;
  color: #c3cbd9;
}

.empty-state-title {
  margin: 0 0 .25rem;
  font-size: .95rem;
  font-weight: 650;
  color: var(--app-ink);
}

.empty-state-text {
  margin: 0;
  font-size: .84rem;
}

.plan-card {
  position: relative;
  overflow: hidden;
}

.plan-card.is-featured {
  border-color: #c9c6f8;
  box-shadow: 0 26px 50px -36px rgba(79, 70, 229, .85);
}

.plan-price {
  font-size: 1.85rem;
  font-weight: 750;
  letter-spacing: -.03em;
  line-height: 1.1;
}

/* ----------------------------------------------------------------- 8. tables */
.app-table {
  margin: 0;
  color: var(--app-ink);
  font-size: .885rem;
  --bs-table-bg: transparent;
}

.app-table > :not(caption) > * > * {
  padding: .78rem 1.1rem;
  border-bottom-color: var(--app-line-soft);
  background-color: transparent;
  box-shadow: none;
}

.app-table > thead > tr > th {
  padding-top: .7rem;
  padding-bottom: .7rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--app-muted);
  background-color: var(--app-surface-soft);
  border-bottom: 1px solid var(--app-line);
  white-space: nowrap;
}

.app-table > tbody > tr {
  transition: background-color .12s ease;
}

.app-table > tbody > tr:hover > * {
  background-color: var(--app-primary-soft);
}

.app-table > tbody > tr:last-child > * {
  border-bottom: 0;
}

.app-table > tfoot > tr > * {
  background-color: var(--app-surface-soft);
  font-weight: 650;
}

.app-table td .btn-group,
.app-table th .btn-group {
  flex-wrap: nowrap;
}

.table-responsive {
  border-top-left-radius: var(--app-radius);
  border-top-right-radius: var(--app-radius);
}

.app-table-wrap {
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface);
  box-shadow: var(--app-shadow-sm);
  overflow: hidden;
}

.app-cell-actions {
  white-space: nowrap;
}

.app-cell-strong {
  font-weight: 650;
}

.app-cell-sub {
  display: block;
  font-size: .78rem;
  color: var(--app-muted);
}

/* Sortable header of a listing screen (Services/Sorting/ListSort.cs and
   TagHelpers/SortHeaderTagHelper.cs): the whole title is a link, the arrow
   only shows on hover and stays on the column currently sorted. */
.sort-header-link {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  color: inherit;
  text-decoration: none;
}

.sort-header-link:hover,
.sort-header-link:focus {
  color: var(--app-primary);
  text-decoration: none;
}

.sort-header-icon {
  width: 13px;
  height: 13px;
  flex: none;
  opacity: .45;
  transition: opacity .12s ease;
}

.sort-header-link:hover .sort-header-icon {
  opacity: 1;
}

.sort-header-link.is-ascending,
.sort-header-link.is-descending {
  color: var(--app-primary);
}

.sort-header-link.is-ascending .sort-header-icon,
.sort-header-link.is-descending .sort-header-icon {
  opacity: 1;
}

/* ------------------------------------------------------------------ 9. forms */
.form-label {
  margin-bottom: .35rem;
  font-size: .82rem;
  font-weight: 600;
  color: var(--app-ink-soft);
}

.form-control,
.form-select {
  padding: .55rem .8rem;
  border-color: var(--app-line);
  border-radius: var(--app-radius-sm);
  background-color: #fff;
  font-size: .9rem;
  color: var(--app-ink);
}

/* Bootstrap draws the select arrow as a background image pinned to the right
   edge. The shared padding above would leave the value sitting underneath it
   (a narrow select such as the pager's "Rows" showed "10" and the chevron on
   top of each other), so the arrow keeps its own reserved space. */
.form-select {
  padding-right: 2.25rem;
  background-position: right .8rem center;
}

.form-select-sm {
  padding-right: 1.9rem;
  background-position: right .55rem center;
}

.form-control::placeholder {
  color: #9aa6ba;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--app-primary);
  box-shadow: 0 0 0 .22rem var(--app-primary-ring);
}

.form-check-input {
  border-color: #cdd5e4;
}

.form-check-input:checked {
  background-color: var(--app-primary);
  border-color: var(--app-primary);
}

.form-check-input:focus {
  border-color: var(--app-primary);
  box-shadow: 0 0 0 .2rem var(--app-primary-ring);
}

.form-check-label {
  font-size: .88rem;
}

.form-text {
  font-size: .78rem;
  color: var(--app-muted);
}

.input-group-text {
  border-color: var(--app-line);
  border-radius: var(--app-radius-sm);
  background-color: var(--app-surface-soft);
  color: var(--app-muted);
  font-size: .85rem;
}

.form-switch .form-check-input {
  width: 2.4rem;
  height: 1.25rem;
}

.field-validation-error,
span.field-validation-error.text-danger {
  display: block;
  margin-top: .25rem;
  font-size: .78rem;
  font-weight: 500;
  color: var(--app-danger-ink) !important;
}

.input-validation-error {
  border-color: #f0a8a0 !important;
}

.input-validation-error:focus {
  box-shadow: 0 0 0 .22rem rgba(217, 45, 32, .16) !important;
}

.validation-summary-errors {
  padding: .7rem .9rem;
  border: 1px solid #f7cdc8;
  border-radius: var(--app-radius-sm);
  background-color: var(--app-danger-soft);
  font-size: .85rem;
  color: var(--app-danger-ink);
}

.validation-summary-errors ul {
  margin: 0;
  padding-left: 1.1rem;
}

.validation-summary-valid {
  display: none;
}

.form-section {
  padding-top: .25rem;
}

/* ------------------------------------------ 10. buttons, badges and alerts */
.btn {
  --bs-btn-border-radius: 11px;
  padding: .5rem .95rem;
  border-radius: 11px;
  font-size: .875rem;
  font-weight: 600;
  letter-spacing: -.005em;
  transition: background-color .12s ease, border-color .12s ease, color .12s ease, transform .1s ease;
}

.btn:active {
  transform: translateY(1px);
}

.btn-sm {
  --bs-btn-border-radius: 9px;
  padding: .32rem .68rem;
  font-size: .8rem;
}

.btn-lg {
  --bs-btn-border-radius: 13px;
  font-size: .95rem;
}

.btn-primary {
  --bs-btn-bg: var(--app-primary);
  --bs-btn-border-color: var(--app-primary);
  --bs-btn-hover-bg: var(--app-primary-ink);
  --bs-btn-hover-border-color: var(--app-primary-ink);
  --bs-btn-active-bg: var(--app-primary-ink);
  --bs-btn-active-border-color: var(--app-primary-ink);
  box-shadow: 0 14px 24px -18px rgba(79, 70, 229, .95);
}

.btn-outline-primary {
  --bs-btn-color: var(--app-primary);
  --bs-btn-border-color: #ccc9f9;
  --bs-btn-hover-bg: var(--app-primary-soft);
  --bs-btn-hover-color: var(--app-primary-ink);
  --bs-btn-hover-border-color: #b8b4f8;
  --bs-btn-active-bg: var(--app-primary-soft);
  --bs-btn-active-color: var(--app-primary-ink);
  --bs-btn-active-border-color: #b8b4f8;
  --bs-btn-disabled-color: #a9a7d8;
  --bs-btn-disabled-border-color: var(--app-line);
}

.btn-outline-secondary {
  --bs-btn-color: var(--app-ink-soft);
  --bs-btn-bg: #fff;
  --bs-btn-border-color: var(--app-line);
  --bs-btn-hover-bg: #f1f4fa;
  --bs-btn-hover-color: var(--app-ink);
  --bs-btn-hover-border-color: #d5dced;
  --bs-btn-active-bg: #eef1f8;
  --bs-btn-active-color: var(--app-ink);
  --bs-btn-active-border-color: #d5dced;
}

.btn-outline-dark {
  --bs-btn-color: var(--app-ink);
  --bs-btn-border-color: #d5dced;
  --bs-btn-hover-bg: #eef1f8;
  --bs-btn-hover-color: var(--app-ink);
  --bs-btn-hover-border-color: #c3cbdd;
  --bs-btn-active-bg: #e7ebf4;
  --bs-btn-active-color: var(--app-ink);
  --bs-btn-active-border-color: #c3cbdd;
}

.btn-outline-danger {
  --bs-btn-color: var(--app-danger-ink);
  --bs-btn-border-color: #f5c6c1;
  --bs-btn-hover-bg: var(--app-danger-soft);
  --bs-btn-hover-color: var(--app-danger-ink);
  --bs-btn-hover-border-color: #eba9a2;
  --bs-btn-active-bg: #fbdedb;
  --bs-btn-active-color: var(--app-danger-ink);
  --bs-btn-active-border-color: #eba9a2;
}

.btn-outline-success {
  --bs-btn-color: var(--app-success-ink);
  --bs-btn-border-color: #bfe7d7;
  --bs-btn-hover-bg: var(--app-success-soft);
  --bs-btn-hover-color: var(--app-success-ink);
  --bs-btn-hover-border-color: #a4dcc6;
  --bs-btn-active-bg: #d8f2e6;
  --bs-btn-active-color: var(--app-success-ink);
  --bs-btn-active-border-color: #a4dcc6;
}

.btn-danger {
  --bs-btn-bg: #d92d20;
  --bs-btn-border-color: #d92d20;
  --bs-btn-hover-bg: #b42318;
  --bs-btn-hover-border-color: #b42318;
  --bs-btn-active-bg: #b42318;
  --bs-btn-active-border-color: #b42318;
}

.btn-success {
  --bs-btn-bg: #0e8a63;
  --bs-btn-border-color: #0e8a63;
  --bs-btn-hover-bg: #0b6a4a;
  --bs-btn-hover-border-color: #0b6a4a;
  --bs-btn-active-bg: #0b6a4a;
  --bs-btn-active-border-color: #0b6a4a;
}

.btn-light {
  --bs-btn-bg: #fff;
  --bs-btn-border-color: var(--app-line);
  --bs-btn-hover-bg: #f1f4fa;
  --bs-btn-hover-border-color: #d5dced;
  --bs-btn-color: var(--app-ink-soft);
}

.btn-link {
  --bs-btn-color: var(--app-primary);
  --bs-btn-hover-color: var(--app-primary-ink);
  font-weight: 600;
}

.btn:focus-visible {
  box-shadow: 0 0 0 .22rem var(--app-primary-ring);
}

.btn-check:focus-visible + .btn {
  box-shadow: 0 0 0 .22rem var(--app-primary-ring);
}

/* ------------------------------------------------------------------------
   Action groups
   Actions that post a form (Remove, Post, Unmatch, Ignore, Resend, ...) have
   to sit inside their own <form> so the antiforgery token travels with the
   request. That wrapper makes the button an *indirect* child of .btn-group,
   and Bootstrap only flattens the corners of and overlaps its direct .btn
   children — so the wrapped button kept its own rounded corners, shared no
   1px seam with its neighbour and the join rendered as two rounded corners
   sitting on top of each other (the "Edit | Remove" and "… | Remove | Post"
   groups in the tables). Mirroring Bootstrap's group treatment onto the
   wrapper makes the group read as one control again.

   The outer corners are deliberately left alone: the button keeps whatever
   radius .btn/.btn-sm gave it, exactly like its siblings.
   ---------------------------------------------------------------------- */
.btn-group > form {
  position: relative;
  flex: 1 1 auto;
  margin: 0;
}

/* Same 1px seam Bootstrap gives neighbouring .btn children. */
.btn-group > form:not(:first-child) {
  margin-left: calc(var(--bs-border-width) * -1);
}

.btn-group > form > .btn {
  width: 100%;
  vertical-align: top;
}

.btn-group > form:not(:first-child) > .btn {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

.btn-group > form:not(:last-child) > .btn {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

/* Keep the hovered/focused border on top of the shared edge. */
.btn-group > form:hover,
.btn-group > form:focus-within {
  z-index: 1;
}

.badge {
  padding: .36em .7em;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 650;
  letter-spacing: .01em;
  vertical-align: middle;
  white-space: nowrap;
}

/* Status badges are deliberately solid and saturated (draft / sent / part
   paid / paid / overdue / cancelled and the equivalent states in the other
   tables) so they stand out against the white rows. Non-status labels keep
   the quiet .bg-light treatment below. */
.badge.bg-primary,
.badge.bg-secondary,
.badge.bg-success,
.badge.bg-info,
.badge.bg-warning,
.badge.bg-danger,
.badge.bg-dark {
  color: #fff !important;
  border: 1px solid var(--app-status-line);
  box-shadow: 0 1px 2px var(--app-status-ring);
}

.badge.bg-primary {
  background-color: var(--app-status-primary) !important;
}

.badge.bg-secondary {
  background-color: var(--app-status-neutral) !important;
}

.badge.bg-success {
  background-color: var(--app-status-success) !important;
}

.badge.bg-info {
  background-color: var(--app-status-info) !important;
}

.badge.bg-warning {
  background-color: var(--app-status-warning) !important;
}

.badge.bg-danger {
  background-color: var(--app-status-danger) !important;
}

.badge.bg-dark {
  background-color: var(--app-status-dark) !important;
}

/* Quiet variant: feature codes, role names, types, check marks. */
.badge.bg-light {
  background-color: #f1f4f9 !important;
  color: #4b5768 !important;
  border: 1px solid var(--app-line);
  box-shadow: none;
}

.badge.border {
  border-color: var(--app-line) !important;
}

.alert {
  padding: .8rem 1rem;
  border-radius: var(--app-radius-sm);
  border-width: 1px;
  font-size: .87rem;
}

.alert-success {
  background-color: var(--app-success-soft);
  border-color: #bfe7d7;
  color: var(--app-success-ink);
}

.alert-danger {
  background-color: var(--app-danger-soft);
  border-color: #f7cdc8;
  color: var(--app-danger-ink);
}

.alert-warning {
  background-color: var(--app-warning-soft);
  border-color: #f5dcb4;
  color: var(--app-warning-ink);
}

.alert-info {
  background-color: var(--app-info-soft);
  border-color: #bfe3ec;
  color: var(--app-info-ink);
}

.alert-dark {
  background-color: #eef1f6;
  border-color: #dde3ec;
  color: #334155;
}

.alert-link {
  font-weight: 650;
  text-decoration: underline;
}

/* ------------------------------------------- 11. dropdowns and small widgets */
.dropdown-menu {
  padding: .4rem;
  border: 1px solid var(--app-line);
  border-radius: 14px;
  box-shadow: var(--app-shadow);
  font-size: .875rem;
}

.dropdown-item {
  padding: .45rem .6rem;
  border-radius: 9px;
  color: var(--app-ink-soft);
  font-weight: 500;
}

.dropdown-item:hover, .dropdown-item:focus {
  background-color: var(--app-primary-soft);
  color: var(--app-primary-ink);
}

.dropdown-item.active, .dropdown-item:active {
  background-color: var(--app-primary);
  color: #fff;
}

.dropdown-header {
  padding: .35rem .6rem;
  font-size: .67rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.dropdown-divider {
  margin: .3rem 0;
  border-color: var(--app-line-soft);
}

.list-group {
  border-radius: var(--app-radius);
}

.list-group-item {
  padding: .85rem 1.15rem;
  border-color: var(--app-line-soft);
  font-size: .88rem;
}

.list-group-item-action:hover, .list-group-item-action:focus {
  background-color: var(--app-surface-soft);
}

.list-group-item.active {
  background-color: var(--app-primary);
  border-color: var(--app-primary);
}

.page-link {
  border-color: var(--app-line);
  color: var(--app-ink-soft);
  font-size: .85rem;
}

.page-item.active .page-link {
  background-color: var(--app-primary);
  border-color: var(--app-primary);
}

/* Pager of a listing page (Views/Shared/_Pagination.cshtml): the row summary
   on the left, the "Rows" selector and the page links on the right. Never
   printed - the printed sheet shows the table, not the controls. */
.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-top: 1rem;
}

.pager-summary {
  font-size: .82rem;
  color: var(--app-muted);
}

.pager-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem;
}

.pager-rows {
  display: flex;
  align-items: center;
  gap: .4rem;
}

.pager-size-label {
  margin-bottom: 0;
  font-size: .82rem;
  font-weight: 600;
  color: var(--app-muted);
  white-space: nowrap;
}

/* Narrow on purpose: it only ever holds a page size, so it hugs its value
   instead of stretching, and keeps the arrow clear of the digits. */
.pager-size {
  width: auto;
  min-width: 5rem;
  padding: .3rem 1.9rem .3rem .6rem;
  font-size: .82rem;
  background-position: right .55rem center;
}

.nav-pills {
  gap: .35rem;
}

.nav-pills .nav-link {
  padding: .45rem .9rem;
  border-radius: 999px;
  color: var(--app-ink-soft);
  font-size: .85rem;
  font-weight: 600;
}

.nav-pills .nav-link.active,
.nav-pills .show > .nav-link {
  background-color: var(--app-primary);
  color: #fff;
}

.progress {
  height: .55rem;
  border-radius: 999px;
  background-color: var(--app-line-soft);
}

.progress-bar {
  background-color: var(--app-primary);
}

/* --------------------------------------------------------- 12. SweetAlert2 */
.swal2-container {
  font-family: var(--app-sans);
}

.swal2-popup {
  padding: 1.6rem 1.5rem 1.4rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-lg);
  box-shadow: var(--app-shadow);
}

.swal2-title {
  padding: 0;
  font-size: 1.12rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--app-ink);
}

.swal2-html-container {
  margin: .6rem 0 0;
  font-size: .89rem;
  color: var(--app-muted);
}

.swal2-html-container strong,
.swal2-html-container code {
  color: var(--app-ink);
}

.swal2-actions {
  gap: .5rem;
  margin-top: 1.35rem;
}

.swal2-styled {
  margin: 0;
  padding: .55rem 1.15rem;
  border-radius: 11px;
  font-size: .875rem;
  font-weight: 600;
  box-shadow: none !important;
}

.swal2-styled:focus-visible {
  box-shadow: 0 0 0 .22rem var(--app-primary-ring) !important;
}

.swal2-styled.swal2-confirm {
  background-color: var(--app-primary);
}

.swal2-styled.swal2-cancel {
  background-color: #eef1f6;
  color: var(--app-ink-soft);
}

.swal2-styled.swal2-cancel:hover {
  background-color: #e4e8f1;
}

.app-swal-danger .swal2-styled.swal2-confirm {
  background-color: #d92d20;
}

.app-swal-danger .swal2-styled.swal2-confirm:focus-visible {
  box-shadow: 0 0 0 .22rem rgba(217, 45, 32, .22) !important;
}

.swal2-icon {
  margin: .2rem auto 1rem;
  border-width: 3px;
}

.swal2-icon.swal2-warning {
  border-color: #f5dcb4;
  color: #b45309;
}

.swal2-icon.swal2-error {
  border-color: #f5c6c1;
  color: #d92d20;
}

.swal2-icon.swal2-info {
  border-color: #bfe3ec;
  color: #0e7490;
}

.swal2-icon.swal2-success {
  border-color: #bfe7d7;
  color: #0e8a63;
}

.swal2-icon.swal2-success [class^='swal2-success-line'] {
  background-color: #0e8a63;
}

.swal2-icon.swal2-success .swal2-success-ring {
  border-color: #bfe7d7;
}

.swal2-input, .swal2-textarea, .swal2-select {
  margin: 1rem auto 0;
  padding: .55rem .8rem;
  border-color: var(--app-line);
  border-radius: var(--app-radius-sm);
  font-size: .9rem;
  box-shadow: none;
}

.swal2-input:focus, .swal2-textarea:focus, .swal2-select:focus {
  border-color: var(--app-primary);
  box-shadow: 0 0 0 .22rem var(--app-primary-ring);
}

.swal2-footer {
  margin-top: 1.1rem;
  padding-top: .9rem;
  border-color: var(--app-line-soft);
  font-size: .79rem;
  color: var(--app-muted);
}

.swal2-popup.swal2-toast {
  padding: .8rem 1rem;
  border-radius: 14px;
  box-shadow: var(--app-shadow);
  align-items: center;
}

.swal2-toast .swal2-title {
  margin: 0;
  font-size: .88rem;
  font-weight: 600;
  color: var(--app-ink);
}

.swal2-toast .swal2-icon {
  width: 1.8rem;
  height: 1.8rem;
  margin: 0 .6rem 0 0;
  border-width: 2px;
}

.swal2-toast .swal2-html-container {
  margin: 0;
  font-size: .82rem;
}

.app-swal-modal .swal2-html-container {
  text-align: left;
}

.app-swal-modal .swal2-html-container .form-label {
  text-align: left;
}

/* --------------------------------------------------------- 13. loading view */
/* The "we are waiting for the server" indicator. Two stages: the slim bar at
   the top of the viewport appears at once, the blurred card follows when the
   wait passes ~400 ms, so a navigation that finishes instantly never flashes a
   spinner (the timing lives in wwwroot/js/loading.js, the markup in
   Views/Shared/_LoadingOverlay.cshtml). */
.app-loading {
  position: fixed;
  inset: 0;
  z-index: 1080;
  display: none;
}

.app-loading.is-active {
  display: block;
}

/* A file indicator is not a navigation: the page underneath stays usable, so
   the user can carry on reading while the download is prepared. */
.app-loading.is-download {
  pointer-events: none;
}

.app-loading-backdrop {
  position: absolute;
  inset: 0;
  background-color: rgba(244, 246, 251, .65);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  animation: app-loading-fade .16s ease-out both;
}

.app-loading-bar {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 3px;
  overflow: hidden;
}

.app-loading-bar > span {
  display: block;
  width: 38%;
  height: 100%;
  border-radius: 0 999px 999px 0;
  background-image: linear-gradient(90deg, var(--app-primary), #0ea5e9);
  box-shadow: 0 0 12px rgba(79, 70, 229, .5);
  animation: app-loading-slide 1.05s cubic-bezier(.65, .05, .36, 1) infinite;
}

.app-loading-card {
  position: absolute;
  top: 50%;
  left: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
  min-width: 15rem;
  max-width: min(22rem, calc(100vw - 2.5rem));
  padding: 1.5rem 1.85rem 1.4rem;
  text-align: center;
  background-color: rgba(255, 255, 255, .97);
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  box-shadow: 0 26px 60px -30px rgba(15, 23, 42, .55);
  opacity: 0;
  transform: translate(-50%, -50%) scale(.97);
  transition: opacity .2s ease-out, transform .2s ease-out;
}

.app-loading.is-card .app-loading-card {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.app-loading-ring {
  width: 36px;
  height: 36px;
  border: 3px solid var(--app-primary-soft);
  border-top-color: var(--app-primary);
  border-right-color: var(--app-primary);
  border-radius: 50%;
  animation: app-loading-spin .72s linear infinite;
}

.app-loading-text {
  font-size: .93rem;
  font-weight: 650;
  color: var(--app-ink);
}

.app-loading-hint {
  font-size: .78rem;
  color: var(--app-muted);
}

@keyframes app-loading-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes app-loading-slide {
  0% { transform: translateX(-105%); }
  60% { transform: translateX(120%); }
  100% { transform: translateX(275%); }
}

@keyframes app-loading-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .app-loading-backdrop,
  .app-loading-card {
    animation: none;
    transition: none;
  }

  .app-loading-bar > span {
    width: 100%;
    opacity: .8;
    animation: none;
  }

  .app-loading-ring {
    animation-duration: 1.6s;
  }
}

/* ------------------------------------------------------------ 14. utilities */
.measure {
  max-width: 36rem;
}

.measure-sm {
  max-width: 26rem;
}

.stack-sm > * + * {
  margin-top: .5rem;
}

.stack > * + * {
  margin-top: 1rem;
}

.app-icon {
  width: 20px;
  height: 20px;
}

.btn .app-icon,
.dropdown-item .app-icon {
  width: 16px;
  height: 16px;
  flex: none;
}

.avatar-lg {
  width: 46px;
  height: 46px;
  font-size: 1rem;
}

/* ----------------------------------- 15. public landing page (Home / Index) */
/* The signed-out marketing page. Mobile first: one column that opens up
   through the Bootstrap grid (col-md / col-xl) as the window grows, and the
   offer grid turns into two columns from 768px. Nothing here needs
   JavaScript and the icons are inline SVG, so the page paints in one pass. */
.landing-hero {
  position: relative;
  overflow: hidden;
  padding: clamp(2.25rem, 6vw, 4rem) clamp(1rem, 4vw, 2.5rem);
  text-align: center;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-lg);
  background-color: var(--app-surface);
  background-image:
    radial-gradient(48rem 26rem at 12% -18%, rgba(99, 102, 241, .20), transparent 62%),
    radial-gradient(40rem 24rem at 94% -8%, rgba(14, 165, 233, .18), transparent 58%),
    linear-gradient(180deg, #fbfcff, var(--app-surface) 68%);
  box-shadow: var(--app-shadow-sm);
}

.landing-hero-inner {
  position: relative;
  max-width: 54rem;
  margin-inline: auto;
}

.landing-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .34rem .85rem;
  border: 1px solid var(--app-primary-ring);
  border-radius: 999px;
  background-color: var(--app-primary-soft);
  color: var(--app-primary-ink);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.landing-eyebrow .app-icon {
  width: 15px;
  height: 15px;
}

.landing-hero-title {
  margin: 1.1rem 0 0;
  font-size: clamp(1.65rem, 6vw, 2.7rem);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.12;
}

.landing-hero-text {
  max-width: 42rem;
  margin: .8rem auto 0;
  font-size: clamp(.92rem, 2.6vw, 1.05rem);
  color: var(--app-muted);
}

.landing-hero-points {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem .6rem;
  margin: 1.6rem 0 0;
  padding: 0;
  list-style: none;
}

.landing-hero-points li {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .42rem .85rem;
  border: 1px solid var(--app-line);
  border-radius: 999px;
  background-color: var(--app-surface);
  box-shadow: var(--app-shadow-xs);
  font-size: .8rem;
  font-weight: 550;
  color: var(--app-ink-soft);
}

.landing-hero-points .app-icon {
  width: 15px;
  height: 15px;
  color: var(--app-status-success);
}

.landing-hero-note {
  margin: 1.1rem 0 0;
  font-size: .78rem;
  color: var(--app-muted);
}

.landing-section {
  margin-top: clamp(1.75rem, 5vw, 2.75rem);
}

.landing-section-head {
  margin-bottom: 1.1rem;
  text-align: center;
}

.landing-section-eyebrow {
  display: block;
  margin-bottom: .5rem;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--app-primary);
}

.landing-section-title {
  margin: 0;
  font-size: clamp(1.15rem, 4vw, 1.6rem);
  font-weight: 750;
  letter-spacing: -.025em;
}

.landing-section-text {
  max-width: 44rem;
  margin: .45rem auto 0;
  font-size: .87rem;
  color: var(--app-muted);
}

.landing-footnote {
  margin: 1rem 0 0;
  font-size: .78rem;
  text-align: center;
  color: var(--app-muted);
}

/* --- plan card ---------------------------------------------------------- */
.plan-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
}

.plan-name {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -.015em;
}

.plan-tagline {
  margin: .35rem 0 0;
  font-size: .84rem;
  color: var(--app-muted);
}

.plan-price-row {
  display: flex;
  align-items: baseline;
  gap: .35rem;
  margin: 1rem 0 0;
}

.plan-price-unit {
  font-size: .85rem;
  color: var(--app-muted);
}

.plan-price-note {
  margin: .35rem 0 0;
  font-size: .78rem;
  color: var(--app-muted);
}

.plan-saving {
  display: inline-block;
  padding: .1em .55em;
  border-radius: 999px;
  background-color: var(--app-success-soft);
  color: var(--app-success-ink);
  font-weight: 650;
}

.plan-users {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: .85rem 0 0;
  font-size: .8rem;
  color: var(--app-ink-soft);
}

.plan-users .app-icon {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--app-muted);
}

.plan-features {
  display: grid;
  gap: .4rem;
  margin: .9rem 0 0;
  padding: 0;
  list-style: none;
  font-size: .84rem;
  color: var(--app-ink-soft);
}

.plan-features li {
  display: flex;
  align-items: flex-start;
  gap: .45rem;
}

.plan-features .app-icon {
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: .12rem;
  color: var(--app-status-success);
}

.plan-features-empty {
  margin: .9rem 0 0;
  font-size: .82rem;
  color: var(--app-muted);
}

.plan-cta {
  margin-top: auto;
  padding-top: 1.1rem;
}

/* Landing only: the recommended card wears a slim gradient cap so the eye
   lands on it first. Scoped to .landing-section so the shared .plan-card
   (Subscription -> Choose plan / Expired) keeps its plain treatment. */
.landing-section .plan-card.is-featured::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background-image: linear-gradient(90deg, #4f46e5, #0ea5e9);
}


/* --- launch offer spotlight --------------------------------------------- */
/* A deliberate step out of the light page: a saturated indigo -> violet
   band with frosted offer cards, so the launch offers read as the headline
   of the page rather than another quiet panel. It sits above the price
   list (Views/Home/Index.cshtml) for exactly that reason. */
.offer-spotlight {
  position: relative;
  overflow: hidden;
  padding: clamp(1.5rem, 4vw, 2.6rem);
  border-radius: var(--app-radius-lg);
  color: #fff;
  background-image:
    radial-gradient(40rem 24rem at 8% -22%, rgba(129, 140, 248, .65), transparent 60%),
    radial-gradient(34rem 22rem at 100% -12%, rgba(56, 189, 248, .45), transparent 55%),
    linear-gradient(135deg, #4338ca 0%, #6d28d9 52%, #4f46e5 100%);
  box-shadow: 0 42px 80px -48px rgba(67, 56, 202, .95), var(--app-shadow-xs);
}

.offer-spotlight::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: inherit;
  pointer-events: none;
}

.offer-spotlight-head {
  position: relative;
  max-width: 46rem;
  margin-bottom: 1.4rem;
}

.offer-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .3rem .8rem;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 999px;
  background-color: rgba(255, 255, 255, .16);
  color: #fff;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.offer-eyebrow .app-icon {
  width: 15px;
  height: 15px;
}

.offer-spotlight-title {
  margin: .85rem 0 0;
  font-size: clamp(1.4rem, 4.4vw, 2.1rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.12;
  color: #fff;
}

.offer-spotlight-note {
  margin: .5rem 0 0;
  font-size: clamp(.9rem, 2.4vw, 1rem);
  color: rgba(255, 255, 255, .84);
}

.offer-spotlight-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: .9rem;
}

@media (min-width: 768px) {
  .offer-spotlight-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.offer-card {
  display: flex;
  gap: .95rem;
  padding: 1.15rem;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: var(--app-radius);
  background-color: rgba(255, 255, 255, .10);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  transition: transform .18s ease, background-color .18s ease, border-color .18s ease;
}

.offer-card:hover {
  transform: translateY(-3px);
  border-color: rgba(255, 255, 255, .42);
  background-color: rgba(255, 255, 255, .17);
}

.offer-card-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 14px;
  background-color: rgba(255, 255, 255, .2);
  color: #fff;
}

.offer-card-icon .app-icon {
  width: 22px;
  height: 22px;
}

.offer-card-body {
  min-width: 0;
}

.offer-card-title {
  margin: 0;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: #fff;
}

.offer-card-highlight {
  display: inline-block;
  margin-top: .4rem;
  padding: .22em .7em;
  border-radius: 999px;
  background-color: #fff;
  color: var(--app-primary-ink);
  font-size: .95rem;
  font-weight: 800;
  letter-spacing: -.01em;
}

.offer-card-text {
  margin: .5rem 0 0;
  font-size: .85rem;
  color: rgba(255, 255, 255, .84);
}

.offer-spotlight-foot {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem 1.25rem;
  margin-top: 1.4rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(255, 255, 255, .2);
  font-size: .8rem;
  color: rgba(255, 255, 255, .84);
}

.offer-claim-btn {
  --bs-btn-color: var(--app-primary-ink);
  --bs-btn-bg: #fff;
  --bs-btn-border-color: #fff;
  --bs-btn-hover-color: var(--app-primary-ink);
  --bs-btn-hover-bg: #eef2ff;
  --bs-btn-hover-border-color: #eef2ff;
  --bs-btn-active-color: var(--app-primary-ink);
  --bs-btn-active-bg: #e0e7ff;
  --bs-btn-active-border-color: #e0e7ff;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-weight: 650;
  box-shadow: 0 16px 30px -18px rgba(15, 23, 42, .8);
}

.offer-claim-btn .app-icon {
  width: 16px;
  height: 16px;
}

/* --- closing line ------------------------------------------------------- */
.landing-closing {
  margin-top: clamp(1.75rem, 5vw, 2.5rem);
  text-align: center;
}

.landing-closing-title {
  margin: 0;
  font-size: clamp(1.05rem, 3.6vw, 1.4rem);
  font-weight: 750;
  letter-spacing: -.02em;
}

.landing-closing-text {
  margin: .35rem 0 0;
  font-size: .83rem;
  color: var(--app-muted);
}

/* ------------------------------------------------------- 16. auth screens */
/* Sign-in, register, external-login and confirmation screens. When
   ViewData["AuthScreen"] is true, Views/Shared/_Layout.cshtml renders
   .auth-shell instead of the app shell: a centred card on a soft
   gradient, no sidebar or top bar. */
.auth-shell {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: clamp(1.35rem, 4vw, 3rem) 1.15rem;
  background-color: var(--app-bg);
  background-image:
    radial-gradient(52rem 30rem at 8% -10%, rgba(99, 102, 241, .22), transparent 62%),
    radial-gradient(44rem 28rem at 96% 2%, rgba(14, 165, 233, .20), transparent 60%),
    linear-gradient(180deg, #fbfcff, var(--app-bg) 70%);
}

.auth-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
  width: 100%;
  max-width: 27rem;
}

.auth-brand {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  color: var(--app-ink);
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -.02em;
}

.auth-brand:hover,
.auth-brand:focus {
  color: var(--app-primary-ink);
}

.auth-brand .app-brand-mark {
  width: 40px;
  height: 40px;
  border-radius: 13px;
}

/* Sign-in card leads with the brand artwork (wwwroot/img/logo-cloud.svg),
   centred above the heading - the sign-in page is the first thing a new
   customer sees, and the shell mark above the card is only 40px. */
.auth-logo {
  display: flex;
  justify-content: center;
  margin-bottom: 1rem;
}

.auth-logo img {
  width: 76px;
  height: 76px;
  border-radius: 22%;
  box-shadow: 0 20px 34px -20px rgba(63, 162, 255, .95), var(--app-shadow-xs);
}

.auth-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.auth-brand-sub {
  font-size: .71rem;
  font-weight: 500;
  letter-spacing: .045em;
  color: var(--app-muted);
}

.auth-main {
  width: 100%;
  padding: clamp(1.35rem, 3.2vw, 1.9rem);
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-lg);
  background-color: var(--app-surface);
  box-shadow: 0 32px 65px -38px rgba(15, 23, 42, .45), var(--app-shadow-xs);
}

.auth-head {
  margin-bottom: 1.3rem;
}

.auth-title {
  margin: 0 0 .3rem;
  font-size: clamp(1.3rem, 1.5vw, 1.5rem);
  font-weight: 700;
  letter-spacing: -.024em;
}

.auth-sub {
  margin: 0;
  font-size: .88rem;
  line-height: 1.5;
  color: var(--app-muted);
}

/* The framework pages that are not overridden (forgot password, two
   factor, lock-out, …) use <h1>/<h2> headings: keep them tidy inside
   the card as well. */
.auth-main > h1 {
  margin: 0 0 .55rem;
  font-size: 1.4rem;
  letter-spacing: -.024em;
}

.auth-main h2 {
  font-size: .95rem;
  font-weight: 650;
  color: var(--app-ink-soft);
}

.auth-main hr {
  margin: 1rem 0;
}

.auth-main > p:last-child {
  margin-bottom: 0;
}

.auth-badge {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: .85rem;
  border-radius: 14px;
  color: var(--app-primary);
  background-color: var(--app-primary-soft);
}

.auth-badge .app-icon {
  width: 22px;
  height: 22px;
}

.auth-form .form-floating > .form-control {
  background-color: var(--app-surface-soft);
}

.auth-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
}

.auth-link-sm {
  font-size: .82rem;
  font-weight: 600;
}

.auth-hint {
  margin: 0 0 1rem;
  font-size: .78rem;
  line-height: 1.45;
  color: var(--app-muted);
}

.auth-note {
  padding: .6rem .75rem;
  margin: 0 0 1rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-sm);
  background-color: var(--app-surface-soft);
  font-size: .78rem;
  line-height: 1.45;
  color: var(--app-muted);
}

.auth-divider {
  position: relative;
  margin: 1.25rem 0;
  text-align: center;
}

.auth-divider::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background-color: var(--app-line);
}

.auth-divider > span {
  position: relative;
  padding: 0 .7rem;
  background-color: var(--app-surface);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.auth-providers {
  display: flex;
  flex-direction: column;
  gap: .55rem;
}

.btn-provider {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  --bs-btn-color: var(--app-ink);
  --bs-btn-bg: #fff;
  --bs-btn-border-color: #d7dcea;
  --bs-btn-hover-bg: #f7f9fd;
  --bs-btn-hover-color: var(--app-ink);
  --bs-btn-hover-border-color: #c3cbdd;
  --bs-btn-active-bg: #eef2f9;
  --bs-btn-active-color: var(--app-ink);
  --bs-btn-active-border-color: #c3cbdd;
  box-shadow: var(--app-shadow-xs);
}

.btn-provider .provider-logo {
  width: 18px;
  height: 18px;
  flex: none;
}

.auth-identity {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: .85rem;
  padding: .75rem .85rem;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius);
  background-color: var(--app-surface-soft);
}

.auth-identity-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 12px;
  color: #fff;
  background-image: linear-gradient(135deg, #4f46e5, #0ea5e9);
}

.auth-identity-icon .app-icon {
  width: 19px;
  height: 19px;
}

.auth-identity-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.3;
}

.auth-identity-text strong {
  font-size: .92rem;
}

.auth-identity-text > span {
  font-size: .8rem;
  color: var(--app-muted);
  overflow-wrap: anywhere;
}

.auth-alt {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: .35rem;
  margin-top: 1.25rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--app-line-soft);
  font-size: .86rem;
  color: var(--app-muted);
}

.auth-alt a {
  font-weight: 600;
}

.auth-footnote {
  margin: .7rem 0 0;
  font-size: .78rem;
  line-height: 1.45;
  text-align: center;
  color: var(--app-muted);
}

.auth-footer {
  font-size: .76rem;
  color: var(--app-muted);
}

.auth-footer a {
  color: var(--app-ink-soft);
}

@media (max-width: 420px) {
  .auth-main {
    border-radius: var(--app-radius);
  }
}

/* -------------------------------------------------------- 17. print styles */
@media print {
  .app-loading,
  .app-topbar,
  .app-footer,
  .page-actions,
  .filter-card,
  .no-print {
    display: none !important;
  }

  body {
    background-color: #fff;
  }

  .app-content {
    padding: 0;
  }

  .card, .app-card, .app-table-wrap {
    box-shadow: none;
    border-color: #cbd5e1;
  }
}






