/* ---- Typeface -----------------------------------------------------------
   Inter, self-hosted. Not Google Fonts: a webfont request tells a third party
   who is reading this page, and our privacy policy names every processor that
   sees our customers. Four weights, latin only, woff2 only: about 90 KB for
   the set, and the system stack covers the moment before they land. */
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  --tblr-font-sans-serif: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, 'Helvetica Neue', Arial, sans-serif;
  --sp-font: var(--tblr-font-sans-serif);
}

body { font-family: var(--sp-font); -webkit-font-smoothing: antialiased; }

/*
 * Socio Pulse - brand layer over Tabler 1.5.1.
 *
 * Kept deliberately small: Tabler is overridden through its own CSS custom
 * properties rather than by fighting its selectors, so upgrading Tabler stays
 * a file swap. Nothing here uses !important except where Tabler sets an
 * inline-level default we must beat.
 */

:root {
  /*
   * Sampled from the logo (assets/img/logo.svg), not chosen alongside it.
   * The artwork is the source of truth for the palette - picking "close
   * enough" values is how a product ends up two shades off its own logo on
   * every screen.
   *
   *   blue   #0953EC  carries the product
   *   purple #6522FC  the secondary accent, used in gradients with the blue
   *   teal   #00B4A7  reserved for "live / healthy", never decorative
   *   navy   #071124  the lettering, and the darkest surface
   */
  --sp-brand:        #0953EC;
  --sp-brand-dark:   #0742BD;
  --sp-brand-light:  #E8F0FE;
  --sp-accent:       #6522FC;
  --sp-pulse:        #00B4A7;
  --sp-ink:          #071124;

  /* Map Tabler's primary onto the brand so every component follows. */
  --tblr-primary:        var(--sp-brand);
  --tblr-primary-rgb:    9, 83, 236;
  --tblr-link-color:     var(--sp-brand);
  --tblr-link-hover-color: var(--sp-brand-dark);
}

/* ---- App shell -------------------------------------------------------- */

.sp-app {
  /* Canvas, radii and the depth scale are set together in "Surface system"
     at the foot of this file. */
  min-height: 100vh;
}

.sp-skip-app {
  position: absolute;
  left: -9999px;
  top: .5rem;
  z-index: 2000;
  background: var(--sp-brand);
  color: #fff;
  padding: .6rem 1rem;
  border-radius: .4rem;
}

.sp-skip-app:focus { left: .5rem; color: #fff; }

/* ---- Sidebar ---------------------------------------------------------- */

.sp-sidebar {
  --tblr-navbar-bg: var(--sp-ink);
  --tblr-navbar-color: #aab6cc;
  --tblr-navbar-active-color: #fff;
  background: linear-gradient(180deg, #071124 0%, #0a1733 60%, #0c1c3d 100%);
  border-right: 0;
}

.sp-sidebar .navbar-toggler {
  color: #fff;
  border: 0;
  padding: .35rem;
}

.sp-sidebar .navbar-toggler .icon { width: 1.5rem; height: 1.5rem; }

.sp-brand {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  text-decoration: none;
  color: #fff;
  font-weight: 650;
  letter-spacing: -0.01em;
  padding: .35rem 0;
}

.sp-brand:hover { color: #fff; text-decoration: none; }

/*
 * The real symbol, not a coloured dot. An <img> rather than a background image
 * so it still appears when printed, and carries its own size if CSS fails.
 */
.sp-brand-mark {
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  object-fit: contain;
}

.sp-logo { height: 2.1rem; width: auto; display: block; }
.sp-logo-lg { height: 2.6rem; }
.sp-brand-name { font-size: 1.08rem; }

.sp-sidebar-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: .25rem 0 1rem;
}

@media (min-width: 992px) {
  .sp-sidebar .navbar-brand { padding: 1.1rem 0 .6rem; }

  /* The foot sits at the bottom of the rail on a tall screen. */
  .sp-sidebar-inner { min-height: calc(100vh - 4.6rem); }
}

/* Which workspace this is - the first thing someone in two agencies needs. */
.sp-workspace {
  display: flex;
  align-items: center;
  gap: .65rem;
  margin: .5rem 0 .75rem;
  padding: .6rem .7rem;
  border-radius: .65rem;
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .07);
}

.sp-workspace-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: .5rem;
  background: linear-gradient(135deg, var(--sp-brand) 0%, var(--sp-accent) 100%);
  color: #fff;
}

.sp-workspace-icon .icon { width: 1.15rem; height: 1.15rem; }

.sp-workspace-text { display: flex; flex-direction: column; min-width: 0; }

.sp-workspace-name {
  color: #fff;
  font-weight: 600;
  font-size: .9rem;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sp-workspace-meta { color: #8392ab; font-size: .75rem; }

.sp-create {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  margin-bottom: .5rem;
  font-weight: 600;
  box-shadow: 0 6px 18px -8px rgba(9, 83, 236, .8);
}

.sp-create .icon { width: 1.1rem; height: 1.1rem; }

.sp-nav { gap: .1rem; }

.sp-nav-heading {
  list-style: none;
  padding: 1rem .75rem .35rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: #5d6b85;
}

.sp-sidebar .sp-nav .nav-link {
  display: flex;
  align-items: center;
  gap: .1rem;
  padding: .5rem .75rem;
  border-radius: .5rem;
  color: #aab6cc;
  font-weight: 500;
  transition: background-color .12s ease, color .12s ease;
}

.sp-sidebar .sp-nav .nav-link:hover {
  background: rgba(255, 255, 255, .06);
  color: #fff;
}

.sp-sidebar .sp-nav .nav-link.active {
  background: rgba(9, 83, 236, .22);
  color: #fff;
  box-shadow: inset 3px 0 0 var(--sp-brand);
}

.sp-sidebar .sp-nav .nav-link-icon {
  display: inline-flex;
  width: 1.5rem;
  margin-right: .45rem;
  color: inherit;
  opacity: .9;
}

.sp-sidebar .sp-nav .nav-link-icon .icon { width: 1.2rem; height: 1.2rem; }

.sp-nav-badge {
  margin-left: auto;
  min-width: 1.35rem;
  padding: .1rem .4rem;
  border-radius: 999px;
  background: var(--sp-brand);
  color: #fff;
  font-size: .7rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
}

.sp-nav-badge.is-warning { background: #f59f00; color: #1f1300; }

.sp-sidebar-foot {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid rgba(255, 255, 255, .07);
  display: grid;
  gap: .15rem;
}

.sp-foot-link {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .4rem .75rem;
  border-radius: .5rem;
  color: #8392ab;
  font-size: .85rem;
  text-decoration: none;
}

.sp-foot-link .icon { width: 1.05rem; height: 1.05rem; }
.sp-foot-link:hover { color: #fff; background: rgba(255, 255, 255, .05); text-decoration: none; }

/* ---- Top bar ---------------------------------------------------------- */

.sp-topbar {
  position: sticky;
  top: 0;
  z-index: 1020;
  min-height: 3.6rem;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: saturate(160%) blur(6px);
  border-bottom: 1px solid #e6e9f0;
}

.sp-topbar-title { display: flex; align-items: center; font-size: .9rem; }

.sp-topbar .navbar-nav .sp-bell {
  position: relative;
  display: inline-flex;
  padding: .45rem;
  border-radius: .5rem;
  color: #475569;
}

.sp-bell:hover { background: #f1f4f9; color: var(--sp-ink); }
.sp-bell .icon { width: 1.3rem; height: 1.3rem; }

.sp-bell-dot {
  position: absolute;
  top: .4rem;
  right: .45rem;
  width: .55rem;
  height: .55rem;
  border-radius: 999px;
  background: #d63939;
  box-shadow: 0 0 0 2px #fff;
}

.sp-avatar {
  background: linear-gradient(135deg, var(--sp-brand) 0%, var(--sp-accent) 100%);
  color: #fff;
  font-weight: 700;
  font-size: .75rem;
  letter-spacing: .02em;
}

.sp-user { color: inherit; text-decoration: none; }
.sp-user:hover { text-decoration: none; }
.sp-user-name { font-weight: 600; color: var(--sp-ink); font-size: .875rem; }

.dropdown-item-icon { width: 1.05rem; height: 1.05rem; margin-right: .5rem; color: #64748b; }

/* ---- Mobile ----------------------------------------------------------- */

@media (max-width: 991.98px) {
  .sp-sidebar .container-fluid { flex-wrap: wrap; }
  .sp-sidebar-inner { padding-bottom: .75rem; }
  .sp-topbar { position: static; }
}

/* ---- Hero ------------------------------------------------------------- */

/* The hero's own surface is in "Surface system" at the foot of this file.
   The pulse dot: a small, slow signal that the system is alive. */
.sp-pulse {
  position: relative;
  flex: none;
  width: .75rem;
  height: .75rem;
  border-radius: 999px;
  background: var(--sp-pulse);
}

.sp-pulse::after {
  content: "";
  position: absolute;
  inset: -.35rem;
  border-radius: 999px;
  border: 2px solid var(--sp-pulse);
  opacity: 0;
  animation: sp-ping 2.4s cubic-bezier(0, 0, .2, 1) infinite;
}

@keyframes sp-ping {
  0%   { transform: scale(.6); opacity: .7; }
  80%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* Respect the viewer's motion preference - an animation nobody asked for
   should never be the reason someone cannot use the page. */
@media (prefers-reduced-motion: reduce) {
  .sp-pulse::after { animation: none; }
  .status-dot-animated::before { animation: none !important; }
}

/* ---- Dark mode -------------------------------------------------------- */

[data-bs-theme="dark"] .sp-topbar {
  background: var(--tblr-bg-surface);
}

/* ---- Accessibility ---------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--sp-brand);
  outline-offset: 2px;
}

/* ---- Media library / uploader ------------------------------------------ */

.sp-dropzone {
  border: 2px dashed var(--tblr-border-color);
  border-radius: var(--tblr-border-radius);
  padding: 2rem 1rem;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background-color .15s;
  background: var(--tblr-bg-surface-secondary);
}

.sp-dropzone:hover,
.sp-dropzone.is-dragging {
  border-color: var(--sp-brand);
  background: var(--sp-brand-light);
}

[data-bs-theme="dark"] .sp-dropzone.is-dragging,
[data-bs-theme="dark"] .sp-dropzone:hover {
  background: rgba(79, 70, 229, .12);
}

.sp-upload-row { padding: .5rem 0; border-bottom: 1px solid var(--tblr-border-color); }
.sp-upload-row:last-child { border-bottom: 0; }
.sp-upload-name { max-width: 70%; }

.sp-media-thumb {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--tblr-bg-surface-secondary);
}

.sp-media-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--tblr-secondary);
  letter-spacing: .08em;
}

.sp-media-card { height: 100%; }

/* ---- Composer ----------------------------------------------------------- */

.sp-media-pick { cursor: pointer; display: block; position: relative; }
.sp-media-pick .sp-media-thumb { aspect-ratio: 1; opacity: .75; transition: opacity .12s, box-shadow .12s; }
.sp-media-pick:hover .sp-media-thumb { opacity: 1; }
.sp-media-pick.is-selected .sp-media-thumb {
  opacity: 1;
  box-shadow: 0 0 0 3px var(--sp-brand);
}
.sp-media-pick.is-disabled { cursor: not-allowed; }
.sp-media-pick.is-disabled .sp-media-thumb { opacity: .2; }

/* ---- Calendar ----------------------------------------------------------- */

/*
 * Status colours are defined once here and mirrored by PostStatus::badgeClass()
 * so a badge and a calendar block never disagree about what "scheduled" looks
 * like (spec §12).
 */
.sp-ev { border: 0 !important; padding: 1px 4px; font-size: .78rem; }
.sp-ev-draft             { background: #adb5bd !important; }
.sp-ev-awaiting_approval { background: #f59f00 !important; }
.sp-ev-changes_requested { background: #fd7e14 !important; }
.sp-ev-rejected          { background: #d63939 !important; }
.sp-ev-approved          { background: #0ca678 !important; }
.sp-ev-scheduled         { background: #4f46e5 !important; }
.sp-ev-publishing        { background: #4299e1 !important; }
.sp-ev-published         { background: #2fb344 !important; }
.sp-ev-partially_published { background: #fd7e14 !important; }
.sp-ev-failed            { background: #d63939 !important; }
.sp-ev-cancelled,
.sp-ev-archived          { background: #868e96 !important; }

.sp-legend {
  width: .85rem; height: .85rem; border-radius: 3px; display: inline-block;
}

.fc .fc-toolbar-title { font-size: 1.05rem; font-weight: 600; }
.fc .fc-button-primary {
  background: var(--tblr-bg-surface-secondary);
  border-color: var(--tblr-border-color);
  color: var(--tblr-body-color);
}
.fc .fc-button-primary:not(:disabled).fc-button-active,
.fc .fc-button-primary:not(:disabled):active {
  background: var(--sp-brand); border-color: var(--sp-brand); color: #fff;
}

/* ---- Setup checklist ---------------------------------------------------- */

/* The one step to do next is the only thing on the list with contrast. A
   checklist where every row shouts equally is just a wall of text again. */
.sp-setup-next {
  background: var(--sp-brand-light);
  box-shadow: inset 3px 0 0 var(--sp-brand);
}

.sp-setup-done .fw-medium { color: var(--tblr-secondary); }

.sp-setup-num,
.sp-setup-tick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  font-size: .8rem;
  font-weight: 600;
}

.sp-setup-num {
  border: 1px solid var(--tblr-border-color);
  color: var(--tblr-secondary);
}

.sp-setup-num-next {
  background: var(--sp-brand);
  border-color: var(--sp-brand);
  color: #fff;
}

.sp-setup-tick {
  background: var(--sp-pulse);
  color: #fff;
}

[data-bs-theme="dark"] .sp-setup-next {
  background: rgba(9, 83, 236, .14);
}

/* ---- CSP-safe sizing ---------------------------------------------------- */

/*
 * The CSP is style-src 'self', which drops inline style="" attributes without
 * an error. Anything that needs a computed width uses one of these instead,
 * rounded to the nearest 5% - finer than a progress bar can visibly show.
 */
.sp-pct-0 { width: 0%; }
.sp-pct-5 { width: 5%; }
.sp-pct-10 { width: 10%; }
.sp-pct-15 { width: 15%; }
.sp-pct-20 { width: 20%; }
.sp-pct-25 { width: 25%; }
.sp-pct-30 { width: 30%; }
.sp-pct-35 { width: 35%; }
.sp-pct-40 { width: 40%; }
.sp-pct-45 { width: 45%; }
.sp-pct-50 { width: 50%; }
.sp-pct-55 { width: 55%; }
.sp-pct-60 { width: 60%; }
.sp-pct-65 { width: 65%; }
.sp-pct-70 { width: 70%; }
.sp-pct-75 { width: 75%; }
.sp-pct-80 { width: 80%; }
.sp-pct-85 { width: 85%; }
.sp-pct-90 { width: 90%; }
.sp-pct-95 { width: 95%; }
.sp-pct-100 { width: 100%; }

.sp-min-w-16  { min-width: 16rem; }
.sp-narrow-24 { max-width: 24rem; margin-left: auto; margin-right: auto; }
.sp-narrow-56 { max-width: 56rem; }
.sp-lead-sm   { font-size: 1.05rem; }
.sp-table-plain { width: 100%; border-collapse: collapse; }

/* Spam honeypot: off-screen, not display:none, so naive bots still fill it. */
.sp-honeypot {
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Messages keep the line breaks their sender typed. */
.sp-prewrap { white-space: pre-wrap; overflow-wrap: anywhere; }

/* The enrolment QR code sits on white whatever the theme: scanners need contrast. */
.sp-qr { background: #fff; padding: .5rem; border-radius: .5rem; line-height: 0; }

.sp-qty { width: 4.5rem; }

/* Tabler spreads the brand row (toggler | brand) and zeroes the rail's
   padding, indenting only the nav list. Keep the mark beside its name, and
   give the blocks above and below the list the same .5rem inset. */
.navbar-vertical.navbar-expand-lg .navbar-brand.sp-brand {
  justify-content: flex-start;
  gap: .6rem;
}

.sp-sidebar .sp-workspace,
.sp-sidebar .sp-sidebar-foot {
  margin-inline: .5rem;
}

.sp-sidebar .sp-create {
  width: calc(100% - 1rem);
  margin-inline: .5rem;
}

.sp-page-header { margin-top: 0; }

/* ---- Sign-in and registration ---------------------------------------- */

.sp-auth { background: #f4f6fb; min-height: 100vh; }

.sp-auth-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100vh;
}

@media (min-width: 992px) {
  .sp-auth-grid { grid-template-columns: minmax(22rem, 38%) minmax(0, 1fr); }
}

.sp-auth-panel {
  display: none;
  position: relative;
  overflow: hidden;
  padding: 2.5rem 3rem;
  color: #c9d3e6;
  background:
    radial-gradient(520px 320px at 110% 0%, rgba(101, 34, 252, .45), transparent 70%),
    radial-gradient(460px 300px at -10% 100%, rgba(0, 180, 167, .28), transparent 70%),
    linear-gradient(160deg, #071124 0%, #0b1a3a 55%, #0d2150 100%);
}

@media (min-width: 992px) {
  .sp-auth-panel { display: flex; flex-direction: column; }
  .sp-auth-logo { display: none; }
}

.sp-auth-brand { color: #fff; }
.sp-auth-brand .sp-brand-mark { width: 2rem; height: 2rem; }
.sp-auth-brand .sp-brand-name { font-size: 1.2rem; }

.sp-auth-pitch { margin: auto 0; max-width: 26rem; }

.sp-auth-pitch h2 {
  color: #fff;
  font-size: 2rem;
  line-height: 1.15;
  letter-spacing: -0.03em;
  font-weight: 800;
  margin-bottom: 1.5rem;
}

.sp-auth-pitch ul { list-style: none; padding: 0; margin: 0; display: grid; gap: .9rem; }
.sp-auth-pitch li { display: flex; gap: .7rem; align-items: flex-start; line-height: 1.5; }

.sp-auth-pitch .icon {
  flex: none;
  width: 1.3rem;
  height: 1.3rem;
  margin-top: .1rem;
  color: #6ee7d8;
}

.sp-auth-legal { margin: 0; font-size: .8rem; color: #7d8aa5; }

.sp-auth-main {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1.15rem;
}

.sp-auth-inner { width: 100%; max-width: 27rem; }

.sp-auth .sp-logo { height: 3rem; }

.sp-auth .card {
  border: 1px solid #e6e9f0;
  border-radius: .9rem;
  box-shadow: 0 24px 48px -30px rgba(15, 23, 42, .35);
}

.sp-auth .card .h2 { font-weight: 700; letter-spacing: -0.02em; }

.sp-auth-links {
  display: flex;
  justify-content: center;
  gap: 1.2rem;
  margin-top: 1.75rem;
  font-size: .82rem;
}

.sp-auth-links a { color: #64748b; text-decoration: none; }
.sp-auth-links a:hover { color: var(--sp-brand); }

/* Option cards (account type at sign-up) read better left-aligned. */
.sp-auth .form-selectgroup-label { text-align: left; }

/* The two halves of the connect handover: what the app will do, and what it
   will never do. Bordered rather than coloured, because one is not a warning. */
.sp-connect-panel {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 8px;
  padding: 1rem;
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

/* ---- Composer: destinations, preview ------------------------------------
   The preview is the reason this layout exists, so it stays in view while the
   form scrolls past it on a desktop. Below lg it drops under the form, where
   a sticky panel would eat the screen. */
.sp-destinations {
  display: grid;
  gap: .5rem;
  /* All four on one line: where a post goes is one glance across, not a list
     to read down. Two by two on a phone, where four would be slivers. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 576px) {
  .sp-destinations { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.sp-destination {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .625rem;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 8px;
  cursor: pointer;
  margin: 0;
  min-width: 0;
}
.sp-destination:hover { border-color: var(--tblr-primary, #206bc4); }
.sp-destination.is-on { border-color: var(--tblr-primary, #206bc4); background: rgba(32, 107, 196, .04); }
.sp-destination-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  /* Four to a row leaves little width, so a long page name shortens rather
     than pushing the badge out of the tile. */
  min-width: 0;
}
.sp-destination-name { font-weight: 500; }

/* Nothing to post to. The platform still shows, so you can see it is there
   and what is missing, but choosing it would promise something we cannot
   keep. The badge goes too: "manual publishing" is moot with no account. */
.sp-destination.is-unavailable { cursor: default; opacity: .45; }
.sp-destination.is-unavailable:hover { border-color: var(--tblr-border-color, #e6e7e9); }
.sp-destination.is-unavailable .badge { display: none; }

.sp-dropzone-compact { padding: 1.25rem 1rem; }
.sp-media-thumb-sm { width: 56px; height: 56px; object-fit: cover; }
.sp-library summary { cursor: pointer; }
.sp-variant-block {
  border-top: 1px solid var(--tblr-border-color, #e6e7e9);
  padding-top: 1rem;
  margin-bottom: 1rem;
}

@media (min-width: 992px) {
  .sp-preview-card { position: sticky; top: 1rem; }
}

.sp-preview-tabs .nav-link { padding: .25rem .75rem; }
.sp-preview-post {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 10px;
  overflow: hidden;
  background: var(--tblr-bg-surface, #fff);
}
.sp-preview-head { display: flex; align-items: center; gap: .5rem; padding: .75rem; }
.sp-preview-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--tblr-primary, #206bc4); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 600;
}
.sp-preview-account { font-weight: 600; line-height: 1.2; }
.sp-preview-meta { font-size: .75rem; }

.sp-preview-media {
  position: relative;
  background: #f1f3f5;
  aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
}
.sp-preview-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sp-preview-media-empty { color: #6c757d; font-size: .8125rem; text-align: center; padding: 1rem; }
.sp-preview-video { font-weight: 600; color: #6c757d; }
.sp-preview-count {
  position: absolute; top: .5rem; right: .5rem;
  background: rgba(0, 0, 0, .6); color: #fff;
  border-radius: 999px; padding: .125rem .5rem; font-size: .75rem;
}

/* A reel or a TikTok is a tall frame, and a preview that ignores that is
   telling the writer their square crop is fine when it is not. */
.sp-preview-type-reel .sp-preview-media,
.sp-preview-type-reels .sp-preview-media,
.sp-preview-type-story .sp-preview-media,
.sp-preview-tiktok .sp-preview-media { aspect-ratio: 9 / 16; }
.sp-preview-facebook .sp-preview-media,
.sp-preview-linkedin .sp-preview-media { aspect-ratio: 1.91 / 1; }
.sp-preview-type-feed.sp-preview-instagram .sp-preview-media { aspect-ratio: 1 / 1; }

.sp-preview-caption { padding: .75rem; white-space: pre-wrap; font-size: .875rem; }

[data-bs-theme="dark"] .sp-preview-media { background: #1a2234; }
[data-bs-theme="dark"] .sp-destination.is-on { background: rgba(32, 107, 196, .12); }

/* ---- Folded sidebar ------------------------------------------------------
   Tabler folds the rail and opens it on hover; these rules are about what the
   rail shows while it is closed. Labels go, icons stay centred, and the badge
   on Approvals shrinks to a dot, because a count nobody can read is noise. */
@media (min-width: 992px) {
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-brand-name,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-workspace-text,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-nav-heading,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .nav-link-title,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-create span,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-sidebar-foot span {
    display: none;
  }

  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .nav-link,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-workspace,
  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-create {
    justify-content: center;
    padding-inline: 0;
  }

  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .sp-nav-badge {
    position: absolute;
    top: .35rem;
    inset-inline-end: .7rem;
    min-width: .5rem;
    height: .5rem;
    padding: 0;
    font-size: 0;
    border-radius: 50%;
  }

  .sp-sidebar.navbar-folded-hover:not(:hover):not(:has(:focus-visible)) .nav-link { position: relative; }
  .sp-sidebar.navbar-folded-hover { transition: width .15s ease; }
  .sp-sidebar .nav-link-icon { flex: none; }
}

/* ---- Preview chrome ------------------------------------------------------
   Close enough to each platform that someone recognises where they are, and
   deliberately not a pixel copy: a preview that pretends to be the real thing
   is a promise about rendering we cannot keep. */
.sp-preview-time { font-size: .75rem; }
.sp-preview-actions {
  display: flex;
  gap: .25rem;
  border-top: 1px solid var(--tblr-border-color, #e6e7e9);
  padding: .5rem .25rem;
}
.sp-preview-action {
  flex: 1;
  text-align: center;
  font-size: .8125rem;
  color: #6c757d;
  padding: .25rem 0;
}
.sp-preview-ig-actions { display: flex; gap: .75rem; padding: .5rem .75rem 0; color: #212529; }
.sp-preview-ig-caption { padding: .25rem .75rem .75rem; font-size: .875rem; white-space: pre-wrap; }
.sp-preview-ig-caption strong { margin-right: .35rem; }
.sp-preview-tiktok .sp-preview-caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  color: #fff;
  background: linear-gradient(transparent, rgba(0, 0, 0, .75));
  padding: 2rem .75rem .75rem;
}
.sp-preview-tiktok .sp-preview-body { position: relative; }

/* ---- Platform logos ------------------------------------------------------
   Each network in its own colour, because four grey rows of text is the thing
   a person has to read rather than recognise. */
.sp-destination-logo {
  width: 2rem; height: 2rem; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px; color: #fff;
}
.sp-destination-logo .icon { width: 1.15rem; height: 1.15rem; }
.sp-logo-facebook { background: #1877f2; }
.sp-logo-instagram { background: linear-gradient(45deg, #f09433, #dc2743 50%, #bc1888); }
.sp-logo-linkedin { background: #0a66c2; }
.sp-logo-tiktok { background: #010101; }

.sp-preview-avatar.sp-logo-facebook,
.sp-preview-avatar.sp-logo-instagram,
.sp-preview-avatar.sp-logo-linkedin,
.sp-preview-avatar.sp-logo-tiktok { color: #fff; }
.sp-preview-avatar .icon { width: 1.2rem; height: 1.2rem; }

/* ---- Preview at phone width ---------------------------------------------
   Most of this is read on a phone, so the preview can be read that way too. */
.sp-preview-phone-width .sp-preview-post {
  max-width: 22rem;
  margin: 0 auto;
  border-radius: 1.25rem;
  box-shadow: 0 0 0 .5rem #1b2434, 0 1rem 2rem rgba(0, 0, 0, .18);
}
.sp-preview-phone-width .sp-preview-caption,
.sp-preview-phone-width .sp-preview-ig-caption { font-size: .8125rem; }

/* The whole Media card accepts a drop, so the small button does not have to
   be the target. */
.sp-compose-media.is-dragging { outline: 2px dashed var(--tblr-primary, #206bc4); outline-offset: -4px; }
.sp-advanced summary { cursor: pointer; }

/* A tile attached to the post, with the way to take it off again. */
.sp-attached { position: relative; display: inline-flex; }
.sp-attached-remove {
  position: absolute;
  top: -.35rem;
  inset-inline-end: -.35rem;
  width: 1.25rem;
  height: 1.25rem;
  border: 0;
  border-radius: 50%;
  background: #1b2434;
  color: #fff;
  font-size: .8rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.sp-attached-remove:hover { background: #c0392b; }
.sp-destination-account {
  font-size: .8125rem;
  color: var(--tblr-secondary, #6c757d);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sp-destination .badge { font-size: .625rem; padding: .1rem .35rem; }
.flex-none { flex: none; }

/* ---- Surface system ------------------------------------------------------
   What makes an interface read as considered rather than assembled is not
   decoration, it is consistency of depth, rhythm and weight. Tabler's
   defaults are deliberately neutral: a 1px grey box, a flat cap, 6px corners.
   Correct, and anonymous.

   This section sets that one level up, and it does it through Tabler's own
   custom properties wherever they exist, so an upgrade is still a file swap.
   Tabler scopes most of its tokens on the component itself (.card redeclares
   --tblr-card-*), so these are set on `.sp-app .card` rather than on the
   shell, which would be inherited and then overwritten.

   Everything here is scoped to .sp-app. The public site has its own voice in
   public.css and does not inherit any of it. */

.sp-app {
  /* Radii, inherited and read by every Tabler component that derives from
     them: cards from -lg, inputs and buttons from the base. Set here rather
     than through --tblr-border-radius-scale because that is resolved on
     :root, where it would reach the marketing site too. */
  --tblr-border-radius-sm: 7px;
  --tblr-border-radius:    9px;
  --tblr-border-radius-md: 9px;
  --tblr-border-radius-lg: 14px;
  --tblr-border-radius-xl: 18px;

  /* The depth scale. Three steps and no more: resting, raised, floating.
     Two-layer shadows, a tight contact shadow over a wide soft one, because
     a single blurred drop reads as a sticker. */
  --sp-shadow-sm: 0 1px 2px rgba(16, 24, 40, .04);
  --sp-shadow:    0 1px 2px rgba(16, 24, 40, .04), 0 6px 16px -6px rgba(16, 24, 40, .10);
  --sp-shadow-lg: 0 2px 4px rgba(16, 24, 40, .04), 0 16px 32px -12px rgba(16, 24, 40, .16);

  --sp-hairline: rgba(16, 24, 40, .07);
  --sp-rule:     rgba(16, 24, 40, .06);

  /* Two pools of brand light, very dilute, fixed so they do not slide around
     as the page scrolls. The canvas should be felt rather than noticed. */
  background:
    radial-gradient(1100px 560px at 100% -8%, rgba(101, 34, 252, .055), transparent 62%),
    radial-gradient(880px 480px at -8% 2%, rgba(9, 83, 236, .05), transparent 58%),
    #f6f8fc;
  background-attachment: fixed;
}

/* Tabler keeps a scrollbar gutter reserved on html at all times. The body
   background does not reliably reach into it, which leaves a strip of the
   wrong colour down the edge of every page, and it is unmissable in dark
   mode. Scoped with :has so the sign-in pages keep their own canvas. */
html:has(> .sp-app) { background-color: #f6f8fc; }
[data-bs-theme="dark"]:has(> .sp-app) { background-color: #0b0f1a; }

/* ---- Cards ---------------------------------------------------------------
   The portal is made of cards, so almost all of the "premium" question is
   answered here. Softer corners, a hairline instead of a grey border, and a
   real but quiet shadow so a card sits ON the canvas rather than being drawn
   onto it. */

.sp-app .card {
  --tblr-card-border-color: var(--sp-hairline);
  --tblr-card-border-radius: var(--tblr-border-radius-lg);
  --tblr-card-inner-border-radius: calc(var(--tblr-border-radius-lg) - 1px);
  --tblr-card-box-shadow: var(--sp-shadow);
  --tblr-card-cap-padding-y: 1.125rem;
  --tblr-card-cap-padding-x: 1.375rem;
  --tblr-card-spacer-y: 1.375rem;
  --tblr-card-spacer-x: 1.375rem;
  --tblr-card-cap-bg: transparent;
}

/* The cap is a heading, not a toolbar: a filled strip with a hard rule under
   it chops every card in two. A transparent cap and a hairline let the card
   read as one surface. */
.sp-app .card-header {
  border-bottom-color: var(--sp-rule);
  min-height: auto;
}

.sp-app .card-title {
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -.005em;
  color: var(--sp-ink);
}

.sp-app .card-subtitle,
.sp-app .card-header .text-secondary { letter-spacing: 0; }

.sp-app .card-footer {
  border-top-color: var(--sp-rule);
  background: transparent;
}

/* A card you can click should say so before it is clicked. Static cards do
   not move: a dashboard that lifts under the pointer is a toy. */
.sp-app a.card,
.sp-app .card-link-hover {
  text-decoration: none;
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}

.sp-app a.card:hover,
.sp-app .card-link-hover:hover {
  box-shadow: var(--sp-shadow-lg);
  border-color: rgba(9, 83, 236, .22);
  transform: translateY(-2px);
}

/* Nested cards (a card inside a card body) would otherwise double the
   shadow into a smudge. */
.sp-app .card .card { box-shadow: none; border-color: var(--sp-rule); }

/* ---- Page header ---------------------------------------------------------
   A page needs a moment of quiet above the content. The title grows, the
   pretitle becomes a small-caps eyebrow in brand colour, and the two sit on
   their own band of space rather than crowding the first card. */

.sp-page-header { margin: .5rem 0 1.5rem; }

.sp-page-header .page-title {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -.028em;
  line-height: 1.2;
  color: var(--sp-ink);
}

.sp-app .page-pretitle {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .085em;
  text-transform: uppercase;
  color: var(--sp-brand);
  margin-bottom: .3rem;
}

/* ---- Typography ----------------------------------------------------------
   Headings tighten as they grow. Left at Inter's defaults, large text looks
   loose and small text looks cramped, which is most of the difference
   between a page that feels designed and one that feels typed. */

.sp-app h1, .sp-app .h1 { letter-spacing: -.028em; }
.sp-app h2, .sp-app .h2 { letter-spacing: -.022em; }
.sp-app h3, .sp-app .h3 { letter-spacing: -.016em; }
.sp-app h4, .sp-app .h4 { letter-spacing: -.011em; }

/* A label above a number, a column head, a section eyebrow: all the same
   thing, so all one class. */
.sp-label {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--tblr-secondary, #667085);
}

/* ---- Tables --------------------------------------------------------------
   Data is the product here, so the table is a first-class surface: quiet
   column heads, generous rows, and no vertical rules, which add ink without
   adding meaning. */

.sp-app .table {
  --tblr-table-border-color: var(--sp-rule);
  margin-bottom: 0;
}

.sp-app .table > thead > tr > th {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--tblr-secondary, #667085);
  background: transparent;
  border-bottom: 1px solid var(--sp-rule);
  padding-top: .875rem;
  padding-bottom: .875rem;
  white-space: nowrap;
}

.sp-app .table > tbody > tr > td {
  padding-top: .875rem;
  padding-bottom: .875rem;
  vertical-align: middle;
}

/* The last row's rule doubles with the card's own edge. */
.sp-app .card > .table-responsive:last-child > .table > tbody > tr:last-child > td,
.sp-app .card > .table:last-child > tbody > tr:last-child > td { border-bottom: 0; }

.sp-app .table-hover > tbody > tr:hover > * {
  --tblr-table-bg-state: rgba(9, 83, 236, .035);
}

/* ---- Lists ---------------------------------------------------------------
   The dashboard is mostly list-group, so it gets the same care as the table. */

.sp-app .list-group { --tblr-list-group-border-color: var(--sp-rule); }

.sp-app .list-group-item { padding: .9375rem 1.375rem; }

.sp-app .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; }

.sp-app a.list-group-item-action:hover { background: rgba(9, 83, 236, .035); }

/* ---- Form controls -------------------------------------------------------
   Inputs are where an interface is actually touched, so they are worth the
   extra few pixels: taller, softer, and with a focus ring that is visibly
   the brand rather than the browser's default blue. */

.sp-app .form-control,
.sp-app .form-select {
  min-height: 2.5rem;
  border-color: #dde2ec;
  box-shadow: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.sp-app .form-control:hover:not(:disabled):not([readonly]),
.sp-app .form-select:hover:not(:disabled) { border-color: #c7cfe0; }

.sp-app .form-control:focus,
.sp-app .form-select:focus,
.sp-app .form-check-input:focus {
  border-color: var(--sp-brand);
  box-shadow: 0 0 0 3px rgba(9, 83, 236, .13);
}

.sp-app .form-label {
  font-size: .8125rem;
  font-weight: 500;
  color: #344054;
  margin-bottom: .375rem;
}

.sp-app .form-hint { font-size: .8125rem; }

.sp-app .input-group-text { border-color: #dde2ec; background: #f8fafc; }

.sp-app .form-check-input:checked { background-color: var(--sp-brand); border-color: var(--sp-brand); }

/* ---- Buttons -------------------------------------------------------------
   Weight before colour: a 500 label on a slightly raised surface reads as a
   control. The primary carries a breath of the accent so the brand's two
   colours appear together wherever an action does. */

.sp-app .btn {
  font-weight: 500;
  letter-spacing: -.005em;
  transition: background-color .15s ease, box-shadow .15s ease,
              transform .15s ease, border-color .15s ease;
}

.sp-app .btn:active { transform: translateY(1px); }

.sp-app .btn-primary {
  background-image: linear-gradient(135deg, var(--sp-brand) 0%, #2d4ef0 100%);
  border-color: transparent;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .08), 0 1px 3px rgba(9, 83, 236, .24);
}

.sp-app .btn-primary:hover {
  background-image: linear-gradient(135deg, var(--sp-brand-dark) 0%, var(--sp-brand) 100%);
  box-shadow: 0 2px 4px rgba(16, 24, 40, .1), 0 4px 10px -2px rgba(9, 83, 236, .35);
}

/* The sidebar CTA keeps its glow: it is the one button sitting on the dark
   rail, and the surface shadow above is tuned for the light canvas. Restated
   here because .sp-app .btn-primary now outranks .sp-create. */
.sp-app .sp-create {
  font-weight: 600;
  box-shadow: 0 6px 18px -8px rgba(9, 83, 236, .8);
}

.sp-app .sp-create:hover { box-shadow: 0 8px 22px -8px rgba(9, 83, 236, .95); }

.sp-app .btn-ghost-secondary,
.sp-app .btn-outline-secondary { border-color: #dde2ec; }

.sp-app .btn-outline-secondary:hover {
  background: #f4f6fb;
  border-color: #c7cfe0;
  color: var(--sp-ink);
}

/* ---- Badges and status ---------------------------------------------------
   Pills, because a status is a word about a thing and not a button. */

.sp-app .badge {
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: .01em;
  padding: .25em .625em;
}

/* ---- Empty states --------------------------------------------------------
   The first thing a new customer sees on half these pages. */

.sp-app .empty { padding: 3rem 1.5rem; }

.sp-app .empty-title { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.012em; }

.sp-app .empty-subtitle { color: var(--tblr-secondary, #667085); }

.sp-app .empty-icon {
  width: 3.5rem;
  height: 3.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(9, 83, 236, .1), rgba(101, 34, 252, .1));
  color: var(--sp-brand);
  margin-bottom: 1rem;
}

.sp-app .empty-icon .icon { width: 1.75rem; height: 1.75rem; }

/* ---- Stat tiles ----------------------------------------------------------
   A number on a card is the easiest thing in an interface to get wrong. The
   label goes above in small caps, the number is large and tight, and nothing
   else competes with it. */

.sp-stat { display: flex; flex-direction: column; gap: .3rem; }

.sp-stat-label {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--tblr-secondary, #667085);
}

.sp-stat-value {
  font-size: 1.875rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.03em;
  color: var(--sp-ink);
  font-variant-numeric: tabular-nums;
}

.sp-stat-meta { font-size: .8125rem; color: var(--tblr-secondary, #667085); }

/* A count tile: a marker, what is being counted, and the count. The marker
   is tinted only when the number means something is wrong or something is
   live, so colour on this row always carries information. */

/* Equal height across the row: one wrapped label would otherwise leave a
   ragged bottom edge along the whole set. */
.sp-tile { height: 100%; }

.sp-tile .card-body {
  display: flex;
  align-items: center;
  gap: .625rem;
  padding: .875rem 1rem;
}

.sp-tile-icon {
  width: 2rem;
  height: 2rem;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: rgba(9, 83, 236, .08);
  color: var(--sp-brand);
}

.sp-tile-icon .icon { width: 1.0625rem; height: 1.0625rem; }
.sp-tile-icon.is-warn  { background: rgba(245, 159, 0, .13);  color: #c06d00; }
.sp-tile-icon.is-alert { background: rgba(214, 57, 57, .11);  color: #c22929; }
.sp-tile-icon.is-live  { background: rgba(0, 180, 167, .13);  color: #008076; }

.sp-tile .sp-stat { min-width: 0; gap: .1rem; }
.sp-tile .sp-stat-label { font-size: .625rem; letter-spacing: .06em; line-height: 1.3; }
.sp-tile .sp-stat-value { font-size: 1.5rem; }

[data-bs-theme="dark"] .sp-tile-icon { background: rgba(9, 83, 236, .2); color: #8fb4ff; }
[data-bs-theme="dark"] .sp-tile-icon.is-warn  { background: rgba(245, 159, 0, .18);  color: #f0b357; }
[data-bs-theme="dark"] .sp-tile-icon.is-alert { background: rgba(214, 57, 57, .18);  color: #f08a8a; }
[data-bs-theme="dark"] .sp-tile-icon.is-live  { background: rgba(0, 180, 167, .18);  color: #4fd6cb; }

/* Numbers that change should line up as they change. */
.sp-app .sp-num, .sp-app .table td .sp-num { font-variant-numeric: tabular-nums; }

/* ---- Hero ----------------------------------------------------------------
   The one card on the dashboard allowed to be a surface in its own right. */

.sp-app .sp-hero {
  border: 0;
  border-radius: var(--tblr-border-radius-xl);
  color: #fff;
  background:
    radial-gradient(760px 320px at 88% -40%, rgba(0, 180, 167, .45), transparent 62%),
    radial-gradient(620px 300px at 10% 120%, rgba(101, 34, 252, .55), transparent 60%),
    linear-gradient(118deg, #071124 0%, #0b1f4d 52%, #0a3bb0 100%);
  box-shadow: 0 1px 2px rgba(7, 17, 36, .2), 0 18px 40px -16px rgba(7, 17, 36, .45);
}

.sp-app .sp-hero .h2,
.sp-app .sp-hero h2 { color: #fff; letter-spacing: -.024em; }

.sp-app .sp-hero .text-secondary,
.sp-app .sp-hero .text-muted { color: rgba(255, 255, 255, .72) !important; }

.sp-app .sp-hero .btn-primary {
  background-image: none;
  background-color: #fff;
  color: var(--sp-ink);
  box-shadow: 0 1px 2px rgba(7, 17, 36, .3);
}

.sp-app .sp-hero .btn-primary:hover { background-color: #eef2ff; color: var(--sp-ink); }

/* ---- Dark mode -----------------------------------------------------------
   Not an inversion: the same depth scale with the light coming from the
   surface rather than from above, which is how dark interfaces keep their
   layers readable. */

[data-bs-theme="dark"] .sp-app,
.sp-app[data-bs-theme="dark"] {
  --sp-hairline: rgba(255, 255, 255, .09);
  --sp-rule: rgba(255, 255, 255, .07);
  --sp-shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --sp-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 16px -6px rgba(0, 0, 0, .45);
  --sp-shadow-lg: 0 2px 4px rgba(0, 0, 0, .35), 0 16px 32px -12px rgba(0, 0, 0, .6);
  background:
    radial-gradient(1100px 560px at 100% -8%, rgba(101, 34, 252, .12), transparent 62%),
    radial-gradient(880px 480px at -8% 2%, rgba(9, 83, 236, .1), transparent 58%),
    #0b0f1a;
}

[data-bs-theme="dark"] .sp-app .card-title,
[data-bs-theme="dark"] .sp-app .sp-stat-value,
[data-bs-theme="dark"] .sp-page-header .page-title { color: #e8ecf5; }

[data-bs-theme="dark"] .sp-app .form-control,
[data-bs-theme="dark"] .sp-app .form-select,
[data-bs-theme="dark"] .sp-app .input-group-text { border-color: rgba(255, 255, 255, .13); }

[data-bs-theme="dark"] .sp-app .input-group-text { background: rgba(255, 255, 255, .04); }

[data-bs-theme="dark"] .sp-app .form-label { color: #c3cbdb; }

[data-bs-theme="dark"] .sp-app .table-hover > tbody > tr:hover > * {
  --tblr-table-bg-state: rgba(255, 255, 255, .035);
}

[data-bs-theme="dark"] .sp-app a.list-group-item-action:hover { background: rgba(255, 255, 255, .035); }

[data-bs-theme="dark"] .sp-app .btn-outline-secondary:hover { background: rgba(255, 255, 255, .06); color: #e8ecf5; }

/* ---- Motion --------------------------------------------------------------
   Every transition above is an affordance, not an effect, so every one of
   them can be dropped without losing meaning. */

@media (prefers-reduced-motion: reduce) {
  .sp-app a.card,
  .sp-app .card-link-hover,
  .sp-app .btn,
  .sp-app .form-control,
  .sp-app .form-select { transition: none; }

  .sp-app a.card:hover,
  .sp-app .card-link-hover:hover,
  .sp-app .btn:active { transform: none; }
}
