/* ============================================================================
   Design tokens — same flat palette used in the client wireframes, so the
   real app matches what was already signed off.
   ============================================================================ */
:root {
    --surface-0: #f5f5f0;
    --surface-1: #efefea;
    --surface-2: #ffffff;
    --text-primary: #1a1a18;
    --text-secondary: #5c5c58;
    --text-muted: #9a9a94;
    --border: rgba(0, 0, 0, 0.10);
    --border-strong: rgba(0, 0, 0, 0.18);
    --radius: 8px;
    --accent: #1a56db;
    --accent-bg: #e6f1fb;
    --success: #3B6D11;
    --success-bg: #eaf3de;
    --danger: #A32D2D;
    --danger-bg: #fcebeb;
    --warning: #633806;
    --warning-bg: #faeeda;
    /* Dark chrome (topnav/sidebar/login page background) — reskin, 2026-09-14.
     Deliberately separate from the --surface- and --text- tokens above:
     those still drive card and page-content surfaces (dashboard cards,
     the auth card) which stay light by design, so the reskin only ever
     targets these new tokens. */
    --chrome-bg: #081028;
    --chrome-border: rgba(255, 255, 255, 0.08);
    --chrome-text: #b7bad4;
    --chrome-text-muted: #7f83a6;
    --chrome-text-strong: #e7e8f2;
    --chrome-active: #e0208f;
    --page-bg-dark: #1E1E1E;
}

html, body {
  height: 100%;
}

body {
  background: var(--surface-0);
  color: var(--text-primary);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  margin: 0;
}

/* Letterboxing behind the boxed/centered app shell (.app-topnav/.app-body
   above) — scoped to this one class, added only to _Layout.cshtml's <body>,
   so _LayoutAuth's and the Error page's own body backgrounds are untouched.
   Deliberately a shade darker than --chrome-bg (#05070f vs #12162c) so the
   centered box reads as a distinct object against the page rather than
   blending into it. Reskin, 2026-09-14. */
body.app-shell-body {
  background: var(--page-bg-dark);
}

a {
  color: var(--accent);
}

/* ============================================================================
   App shell — topnav + collapsible sidebar
   Dark chrome + boxed/centered layout, reskin 2026-09-14 (Matt's Figma).
   Deliberately scoped to .app-topnav/.app-sidebar only — .app-main and the
   cards inside it keep the light --surface-* tokens untouched, per Matt's
   "dashboard cards stay white" call. The mobile .offcanvas-body menu (see
   _Layout.cshtml) is left on its original light styling below — it wasn't
   part of what was previewed/approved, so it isn't changed here.
   ============================================================================ */
.app-topnav {
  background: var(--chrome-bg);
  border-bottom: 1px solid var(--chrome-border);
  /* Taller bar per Matt's reference (2026-09-14): measured off the Figma
     dev-mode screenshot at ~124px tall, achieved here via padding rather
     than a fixed height so it still hugs the (now full-size) logo. */
  padding: 2.25rem 1.5rem;
  max-width: 1440px;
  margin: 0 auto;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.app-topnav .text-secondary,
.app-topnav i {
  color: var(--chrome-text-strong) !important;
}

.app-logo {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  object-fit: cover;
  display: inline-block;
  vertical-align: middle;
}

/* The topnav's own logo — a wide icon+wordmark lockup, not the square icon
   .app-logo above is sized for, so it gets its own id-scoped override rather
   than changing .app-logo (which the small 36x36 icon on the secondary
   Account pages below still relies on at its original size/shape). */
#navLogo {
  width: auto;
  /* Was pulse-lockup.png (247x51, PNG); swapped 2026-09-15 for
     pulse-logo-horizontal-white.svg (Matt's "Pulse Logo - White Text -
     Horizontal" file, renamed to this project's kebab-case convention).
     The topnav is dark chrome, so this needs the white-fill variant — unlike
     Login.cshtml/Register.cshtml's .auth-logo-chip, which sits on the plain
     white .auth-card and uses the dark-fill pulse-logo-horizontal.svg
     instead (no dark backing box there — see .auth-logo-chip's own comment).
     Both variants share the same 3617.2x731.1 viewBox (~4.85:1), the same
     aspect ratio as the old PNG, so this height still gives the same
     on-screen size. Vector now, so it stays crisp at any pixel density
     rather than being capped at the old PNG's native resolution. */
  height: 51px;
  border-radius: 0;
  object-fit: contain;
}

/* Wide "loopaNZ" wordmark used on the auth (Login/Register) card header — deliberately
   separate from .app-logo, which is sized/cropped (30x30, object-fit:cover) for the
   small square dark nav icon used everywhere else and is the wrong shape for this
   wide logo. */
.auth-logo {
  display: block;
  height: 60px;
  width: auto;
  max-width: 100%;
  align-self: center; /* the header is a flex-column container (default
    align-items:stretch), which would otherwise stretch this fixed-height image
    across the full row width, squashing/distorting it */
  margin: 0 auto;
}

/* Wraps the <img class="auth-logo"> on Login.cshtml/Register.cshtml — no
   background here, 2026-09-16: Matt wants the plain dark-fill logo
   (pulse-logo-horizontal.svg) directly on the white .auth-card, not the
   white-fill variant boxed in a dark chip (that was reskin 2026-09-14's
   approach, and the dark box itself was the complaint — it obscured the
   logo rather than showing it off). Kept as its own class rather than
   dropped from the markup in case a future auth-page tweak needs to target
   just this wrapper again. */
.auth-logo-chip {
  display: inline-flex;
}

/* The logo on Login/Register/Forgot password links back to the public website ("/"). */
.auth-logo-link {
  display: block;
}

.app-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--accent);
  font-weight: 600;
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.app-body {
  display: flex;
  min-height: calc(100vh - 57px);
  max-width: 1440px;
  margin: 0 auto;
  background: var(--surface-0);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.app-sidebar {
  width: 220px;
  flex-shrink: 0;
  background: var(--chrome-bg);
  border-right: 1px solid var(--chrome-border);
  padding: 0.75rem 0;
}

/* Same _SidebarNav.cshtml partial renders in both the desktop .app-sidebar and
   the mobile .offcanvas-body (see _Layout.cshtml) — these selectors have to
   match both containers, or the mobile menu falls back to unstyled links. */
.app-sidebar .nav-section,
.offcanvas-body .nav-section {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  padding: 0.75rem 1rem 0.25rem;
}

.app-sidebar .nav-link,
.offcanvas-body .nav-link {
  color: var(--text-secondary);
  padding: 0.5rem 1rem;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: 0;
  text-decoration: none;
}

.app-sidebar .nav-link i,
.offcanvas-body .nav-link i {
  font-size: 17px;
}

.app-sidebar .nav-link.active,
.app-sidebar .nav-link:hover,
.offcanvas-body .nav-link.active,
.offcanvas-body .nav-link:hover {
  background: var(--surface-1);
  color: var(--text-primary);
}

/* Dark-sidebar colour overrides — .app-sidebar only, layered on top of the
   shared rules above rather than replacing them, so .offcanvas-body (the
   mobile menu) keeps its original light styling untouched. Reskin, 2026-09-14. */
.app-sidebar .nav-section {
  color: var(--chrome-text-muted);
}

.app-sidebar .nav-link {
  color: var(--chrome-text);
}

    .app-sidebar .nav-link:hover {
        background: rgba(255, 255, 255, 0.06);
        color: #e01fb5;
    }

.app-sidebar .nav-link.active {
  background: transparent;
  color: var(--chrome-active);
}

.app-main {
  flex: 1;
  padding: 1.25rem;
  min-width: 0;
}

/* Collapse sidebar into an offcanvas below md */
@media (max-width: 767.98px) {
  .app-sidebar {
    display: none;
  }
}

/* ============================================================================
   Cards / metric stats
   ============================================================================ */
.stat-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
}

.stat-val {
  font-size: 1.4rem;
  font-weight: 600;
}

.stat-label {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.stat-delta {
  font-size: 0.8rem;
  color: var(--success);
}

/* Edit-page hero preview band (Posts/Edit.cshtml, Admin/Content/Edit.cshtml, via
   Shared/_MediaHeroPreview.cshtml) — same visual language as a Dashboard card's own
   image band (.article-card .card-img below): full width, rounded top corners,
   object-fit:cover. The negative margin exactly cancels .stat-card's own padding
   (0.75rem 1rem, above) so this sits flush against the card's top/left/right edges
   despite being a normal padded child of it — .stat-card itself is deliberately left
   untouched rather than given its own overflow:hidden/zero padding, since plenty of
   other .stat-card usages across the app (dashboard metric tiles, etc.) rely on that
   padding applying uniformly on every side. Matt's own ask, 2026-08-13, after the
   plain small img-thumbnail preview this replaced read as too small/easy to miss next
   to a scraped listing's real photo. */
.media-hero-preview {
  margin: -0.75rem -1rem 0.75rem -1rem;
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden;
  background: var(--surface-1);
}

/* 2026-08-24 (Matt's own ask): this preview was fixed at 16:9 with object-fit:cover,
   which crops anything that isn't already that shape — most visibly, a baked Social
   Tile (Infrastructure/Content/ImageSharpSocialTileRenderer.cs), which renders at
   whatever the Template's own background image's native aspect ratio is (often
   square/portrait, not 16:9). object-fit:cover centers its crop, so the star row
   drawn near the very top of the tile and the last line or two of the description
   band at the very bottom were BOTH silently cut off — not a rendering bug, just
   never visible in this preview. Switched to a Facebook/Instagram-style "show the
   whole image, letterboxed" box instead: a fixed max-height so the card doesn't grow
   unboundedly for a tall template, object-fit:contain so nothing is ever cropped, and
   a dark letterbox background for the empty space either side of a non-matching
   aspect ratio (same idea as how those platforms themselves preview an upload before
   you post it). */
.media-hero-preview .js-media-hero-image-wrap,
.media-hero-preview .js-media-hero-video-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  position: relative; /* anchors Posts/Edit.cshtml's own live-preview loading spinner overlay */
}

.media-hero-preview img,
.media-hero-preview video {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 480px;
  margin: 0 auto;
}

/* ============================================================================
   Article grid (Instagram-style dashboard cards)
   ============================================================================ */
.article-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  height: 100%;
  /* Bootstrap's row/col flexbox already stretches every card in the same visual
     row to equal height — the actual bug was that the content below the image
     (title/excerpt/optional Source line) is normal block flow, so a card with a
     1-line excerpt and no Source left its Post/Edit/Thumbs-down row sitting higher
     up than a card with a 2-line excerpt plus a Source line, with the leftover
     equal-height space landing as invisible padding below the buttons instead.
     Making this a flex column lets the action row opt into .mt-auto
     (_DashboardCards.cshtml's .p-3 wrapper is flex-column too) to always sit flush
     against the bottom of the card, regardless of how much sits above it. */
  display: flex;
  flex-direction: column;
}

.article-card .card-img {
  height: 210px;
  background: var(--surface-1);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 24px;
}

/* Dashboard card grid: 2-up by default (col-sm-6), 3-up at lg and above
   (col-lg-4, Bootstrap classes on .dashboard-card-col in _DashboardCards.cshtml).
   Matt's call, 2026-09-14: capped at 3-up even on ultra-wide monitors — the old
   4-up (col-xl-3) and 5-up (custom 1600px breakpoint) tiers read as too
   squashed once the app shell was boxed to a 1440px centered column, so both
   are removed here rather than re-tuned. */

/* Multi-photo post on a Dashboard card (added 2026-09-24): the post's photos in the same
   210px image band, in the grid Facebook uses — 2 side by side; 3 one large left and two
   stacked; 4 one large on top and three below; 5 two on top and three below, "+N" on the
   last when there are more. */
.card-multi-grid {
  position: absolute;
  inset: 0;
  display: grid;
  gap: 2px;
}

.card-multi-grid-cell {
  position: relative;
  overflow: hidden;
  min-height: 0;
}

.card-multi-grid-cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-multi-grid-2 { grid-template-columns: 1fr 1fr; }

.card-multi-grid-3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; }
.card-multi-grid-3 .card-multi-grid-cell:first-child { grid-row: span 2; }

.card-multi-grid-4 { grid-template-columns: repeat(3, 1fr); grid-template-rows: 3fr 2fr; }
.card-multi-grid-4 .card-multi-grid-cell:first-child { grid-column: span 3; }

.card-multi-grid-5 { grid-template-columns: repeat(6, 1fr); grid-template-rows: 3fr 2fr; }
.card-multi-grid-5 .card-multi-grid-cell:nth-child(-n+2) { grid-column: span 3; }
.card-multi-grid-5 .card-multi-grid-cell:nth-child(n+3) { grid-column: span 2; }

.card-multi-grid-more {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 1.25rem;
  font-weight: 600;
}

.multi-photo-badge {
  position: absolute;
  left: 8px;
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: var(--radius);
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  z-index: 1;
}

.src-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: var(--radius);
  text-transform: uppercase;
  letter-spacing: .04em;
  background: var(--warning-bg);
  color: var(--warning);
}

.new-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--radius);
  text-transform: uppercase;
  letter-spacing: .04em;
  background: var(--success-bg);
  color: var(--success);
}

/* Trending/Hot badge — bottom-left of the card image, deliberately away from the
   src-badge/new-badge/Headline pill cluster already occupying the top corners. */
.trending-badge {
  position: absolute;
  bottom: 8px;
  left: 8px;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--radius);
  text-transform: uppercase;
  letter-spacing: .04em;
  background: var(--danger-bg);
  color: var(--danger);
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

/* Anonymized shared-impression count — bottom-right of the card image, next to an
   eye icon, per Matt's spec ("down bottom right where the picture sits"). */
.impression-count {
  position: absolute;
  bottom: 8px;
  right: 8px;
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: var(--radius);
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.plat-badge {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: var(--radius);
  font-weight: 600;
}

.plat-fb { background: var(--accent-bg); color: #0C447C; }
.plat-ig { background: var(--danger-bg); color: #4b1528; }
.plat-li { background: var(--accent-bg); color: #042c53; }

.card-title-sm {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
}

.card-excerpt {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.action-btn {
  flex: 1;
  font-size: 12px;
  font-weight: 600;
  border-radius: var(--radius);
  border: 1px solid;
  padding: 0.3rem 0;
  /* Explicit rather than relying on browser/element defaults — a plain <button>
     (Thumbs down, and Post once a channel's connected) happens to center its own
     content in most browsers, but the <a>-tag variants of Post/Edit (not-connected
     Post, and Edit) have no such default and were left-aligned instead. Pin it here
     once for every variant of every action button instead of patching each markup
     spot with its own text-center class. */
  text-align: center;
}

/* Post/Edit/thumbs-down colours, reskin 2026-09-14: matched to Matt's reference
   image (tinted pill buttons over solid icon colour), so these are hardcoded
   hex values rather than the shared --success/--accent/--danger tokens above —
   those tokens are still used as-is by pill-live/toast/plat-badge elsewhere,
   and changing them would have recoloured all of those too.

   .btn-post-action itself moved off green to solid pink, reskin 2026-09-16, per
   Matt: "any Green button ... should now be pink with the white text" — this is
   the one shared class every green action button in the app uses (Settings'
   Save/Change email/Add/Business Registration Update, the Website Connection
   card's Connect/Update/Resume scraping/Scrape now, and the dashboard card's
   own Post button in _DashboardCards.cshtml), so this single rule covers all of
   them. Same three-shade pink/hover/active as the pulse-toolbar buttons above,
   for the same "pressed in" active feedback. .btn-edit-action (blue) and
   .btn-del-action (red) alongside it are untouched — Matt only asked about
   the green ones. */
.btn-post-action { background: #fa36cd; border-color: #fa36cd; color: #ffffff; }
.btn-post-action:hover { background: #e01fb5; border-color: #e01fb5; color: #ffffff; }
.btn-post-action:active { background: #c7189f; border-color: #c7189f; color: #ffffff; }
/* Dashboard's "My Website Connections" toggle, "on" state — reskin 2026-09-16.
   Was the shared --success/--success-bg pair (green); moved off that so a real
   "success" state (live pills, success toasts, positive deltas elsewhere in
   this file) keeps a consistent meaning. Uses --pink-active, the same shade
   the pink toolbar buttons above go to on :active, so the toggle reads as
   "pressed in" rather than just a random second pink. */
.btn-website-filter-on { background: #c7189f; border-color: #c7189f; color: #ffffff; }
.btn-edit-action { background: rgba(30, 135, 255, 0.14); border-color: #1e87ff; color: #1e87ff; }
/* Delete/Reject/Dismiss/Decline/Cancel — every one of these is a real, clickable,
   destructive-or-negative action (never a disabled placeholder). */
.btn-del-action { background: rgba(255, 90, 100, 0.14); border-color: #ff5a64; color: #ff5a64; }
/* Amber/orange "caution, this changes something" action — distinct from btn-del-action's
   red, which is for actions that remove/reject/decline something. Same --warning/
   --warning-bg pair pill-sched already uses for "Scheduled" status pills, just reused
   here for a button instead of a pill. */
.btn-warn-action { background: var(--warning-bg); border-color: var(--warning); color: var(--warning); }

/* ============================================================================
   Post modal — per-channel toggle rows
   ============================================================================ */
.channel-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 0.5rem;
  background: var(--surface-2);
}

.channel-toggle-row-disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.channel-toggle-row-disabled .form-check-input {
  cursor: not-allowed;
}

.channel-toggle-icon {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border-radius: 7px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
}

.channel-connection-picker {
  font-size: 11px;
  padding: 0.15rem 0.4rem;
}

.channel-toggle-row .form-check.form-switch {
  padding-left: 2.5em;
}

.channel-toggle-row .form-check-input:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}

/* ============================================================================
   Past-posts list + detail
   ============================================================================ */
.post-list-item {
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  display: block;
}

.post-list-item:hover,
.post-list-item.active {
  background: var(--surface-1);
}

/* Past Posts: a post that failed to publish (2026-09-23). */
.post-list-item-failed {
  background: var(--danger-bg);
  box-shadow: inset 3px 0 0 var(--danger);
}

.post-list-item-failed:hover,
.post-list-item-failed.active {
  background: var(--danger-bg);
  filter: brightness(0.97);
}

.post-failed-card {
  background: var(--danger-bg);
  border: 1px solid var(--danger);
}

.post-failed-banner,
.channel-result-failed {
  color: var(--danger);
  font-weight: 600;
}

.status-pill {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
}

.pill-live { background: var(--success-bg); color: var(--success); }
.pill-sched { background: var(--warning-bg); color: var(--warning); }
.pill-draft { background: var(--surface-1); color: var(--text-muted); }
.pill-cancelled { background: var(--danger-bg); color: var(--danger); }

.metric-card {
  background: var(--surface-1);
  border-radius: var(--radius);
  padding: 0.6rem;
  text-align: center;
}

.metric-val { font-size: 1.1rem; font-weight: 600; }
.metric-lbl { font-size: 0.7rem; color: var(--text-muted); }

.chart-box {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem;
}

/* ============================================================================
   Toast notifications — one shared, styled notification component used for
   both TempData["Toast"/"Error"/"Info"] (rendered once, sitewide, from
   Pages/Shared/_ToastMessages.cshtml in _Layout.cshtml — no more bare
   .alert-success/.alert-danger divs duplicated on every page) and any
   client-side JS that used to call the native, unstyled alert() (e.g.
   Schedule.cshtml's drag-to-reschedule/date-range errors) — see
   window.loopaToast in site.js.
   ============================================================================ */
#toastStack {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 360px;
}

.toast-alert {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--surface-2);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.14);
  font-size: 0.875rem;
  line-height: 1.4;
  opacity: 0;
  transform: translateX(16px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.toast-alert.show {
  opacity: 1;
  transform: translateX(0);
}

.toast-alert-icon {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
}

.toast-alert-message {
  flex: 1 1 auto;
  padding-top: 1px;
}

.toast-alert-close {
  flex: 0 0 auto;
  background: none;
  border: none;
  padding: 0;
  margin-left: 4px;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}

.toast-alert-close:hover {
  opacity: 1;
}

.toast-alert-success { border-color: var(--success); background: var(--success-bg); color: var(--success); }
.toast-alert-success .toast-alert-icon { background: var(--success); color: var(--success-bg); }

.toast-alert-danger { border-color: var(--danger); background: var(--danger-bg); color: var(--danger); }
.toast-alert-danger .toast-alert-icon { background: var(--danger); color: var(--danger-bg); }

.toast-alert-warning { border-color: var(--warning); background: var(--warning-bg); color: var(--warning); }
.toast-alert-warning .toast-alert-icon { background: var(--warning); color: var(--warning-bg); }

.toast-alert-info { border-color: var(--accent); background: var(--accent-bg); color: var(--accent); }
.toast-alert-info .toast-alert-icon { background: var(--accent); color: var(--accent-bg); }

.geo-chip {
  font-size: 11px;
  padding: 3px 8px;
  background: var(--surface-0);
  border-radius: var(--radius);
  color: var(--text-secondary);
  display: inline-block;
  margin: 2px;
}

/* ============================================================================
   Schedule / calendar (FullCalendar)
   ============================================================================ */
.schedule-toolbar {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
}

.schedule-toolbar .btn-group .btn,
.schedule-toolbar .btn-outline-primary {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  border-color: var(--border-strong);
}

.schedule-toolbar .btn-group .btn:hover,
.schedule-toolbar .btn-outline-primary:hover {
  background: var(--surface-1);
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.schedule-toolbar .btn-outline-primary {
  color: var(--accent);
  border-color: var(--accent);
}

.schedule-toolbar .btn-outline-primary:hover {
  background: var(--accent);
  color: #fff;
}

.schedule-toolbar input[type="date"] {
  font-size: 12px;
  border-color: var(--border-strong);
}

.schedule-legend {
  font-size: 11.5px;
  color: var(--text-secondary);
}

.schedule-legend .legend-dot {
  width: 8px;
  height: 8px;
  display: inline-block;
  border-radius: 50%;
  margin-right: 3px;
  vertical-align: middle;
}

.schedule-calendar-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}

#scheduleCalendar {
  --fc-border-color: var(--border);
  --fc-page-bg-color: var(--surface-2);
  --fc-neutral-bg-color: var(--surface-1);
  --fc-list-event-hover-bg-color: var(--surface-1);
  --fc-today-bg-color: var(--accent-bg);
  --fc-button-bg-color: var(--surface-2);
  --fc-button-border-color: var(--border-strong);
  --fc-button-text-color: var(--text-secondary);
  --fc-button-hover-bg-color: var(--surface-1);
  --fc-button-hover-border-color: var(--border-strong);
  --fc-button-hover-text-color: var(--text-primary);
  --fc-button-active-bg-color: var(--accent);
  --fc-button-active-border-color: var(--accent);
  --fc-button-active-text-color: #fff;
  font-family: inherit;
}

#scheduleCalendar .fc-toolbar-title {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-primary);
}

#scheduleCalendar .fc-button {
  text-transform: capitalize;
  font-size: 12.5px;
  font-weight: 600;
  padding: 0.35rem 0.7rem;
  box-shadow: none !important;
}

#scheduleCalendar .fc-button:focus {
  box-shadow: none !important;
}

#scheduleCalendar .fc-button-primary:not(:disabled).fc-button-active {
  color: #fff;
}

#scheduleCalendar .fc-col-header-cell-cushion,
#scheduleCalendar .fc-daygrid-day-number,
#scheduleCalendar .fc-timegrid-slot-label-cushion {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: 12px;
  font-weight: 600;
}

#scheduleCalendar .fc-daygrid-day-number {
  color: var(--text-primary);
  font-weight: 500;
  padding: 6px 8px;
}

#scheduleCalendar a {
  text-decoration: none;
}

#scheduleCalendar .fc-day-today {
  background: var(--accent-bg) !important;
}

#scheduleCalendar .fc-day-today .fc-daygrid-day-number {
  color: var(--accent);
  font-weight: 700;
}

#scheduleCalendar .fc-daygrid-day-frame {
  transition: background-color 0.1s ease;
}

#scheduleCalendar .fc-daygrid-day:hover .fc-daygrid-day-frame {
  background: var(--surface-1);
}

#scheduleCalendar .fc-event {
  border: none;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 600;
  padding: 1px 5px;
  cursor: grab;
}

#scheduleCalendar .fc-event:active {
  cursor: grabbing;
}

#scheduleCalendar .fc-daygrid-event-dot {
  border-width: 4.5px;
}

#scheduleCalendar .fc-daygrid-event {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#scheduleCalendar .fc-scrollgrid {
  border-radius: 6px;
  overflow: hidden;
}

/* ============================================================================
   Auth pages (login / register)
   ============================================================================ */
.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Was var(--page-bg-dark) (near-black, reskin 2026-09-14) — Matt asked to
     remove the black backdrop behind Login/Register/Forgot password (shared
     via _LayoutAuth.cshtml's .auth-wrap), 2026-09-16. Back to the app's own
     plain light page background, same as everywhere else. */
  background: var(--surface-0);
  padding: 1.5rem;
}

.auth-card {
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  padding: 2rem 2.25rem;
  width: 100%;
  max-width: 400px;
}

/* ============================================================================
   Error page (Pages/Error.cshtml) — reached via app.UseExceptionHandler("/Error")
   in Production/Staging. Never shows exception detail; just orients the person
   and gives them a reference ID for support.
   ============================================================================ */
.error-page-wrap {
  min-height: calc(100vh - 57px - 2.5rem);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.error-page-card {
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  padding: 2.5rem;
  width: 100%;
  max-width: 480px;
  text-align: center;
}

.error-icon-circle {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--danger-bg);
  color: var(--danger);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  margin: 0 auto 1.25rem;
}

.error-page-heading {
  font-size: 1.35rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.error-code-box {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.9rem 1.1rem;
  margin: 1.5rem 0;
  text-align: left;
}

.error-code-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.3rem 0;
}

.error-code-row + .error-code-row {
  border-top: 1px solid var(--border);
}

.error-code-label {
  font-size: 0.78rem;
  color: var(--text-muted);
}

.error-code-value {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-primary);
}

.error-page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  margin-top: 1.5rem;
}

/* ============================================================================
   Social Content Dashboard toolbar/stats — matched to Matt's LoopaPulse Figma
   export (index.html/site.css, "LoopaPulse - 50/50", 2026-09-15): the Create
   Post button, Clear filters, the My Content toggle's off state, the three
   stat tiles, and the date-range/topic filter selects.

   Scoped to .pulse-toolbar/.pulse-stats — two classes added directly onto
   Index.cshtml's existing header div, filter-bar <form>, and stat-row <div> —
   rather than restyling the bare Bootstrap classes (.btn-primary,
   .btn-outline-secondary, .form-select/.form-control, .stat-card) globally.
   Those same classes are reused as-is on Login/Register/Admin/other pages,
   which this reskin was never asked to touch.

   Hardcoded hex rather than the shared --accent/--border tokens above, same
   reasoning as the Post/Edit/Delete action buttons further up this file:
   --accent is still blue everywhere else in the app (Login/Register/Admin),
   and repointing that token would repaint all of those too. */

/* .btn-primary is this toolbar's one true call-to-action (Index.cshtml's "New
   Post" button, top-right) — stays solid pink unconditionally, same as any
   other single-action primary button in the app. */
.pulse-toolbar .btn-primary {
  background: #fa36cd;
  border-color: #fa36cd;
  color: #ffffff;
}

.pulse-toolbar .btn-primary:hover {
  background: #e01fb5;
  border-color: #e01fb5;
  color: #ffffff;
}

.pulse-toolbar .btn-primary:active {
  background: #c7189f;
  border-color: #c7189f;
  color: #ffffff;
}

/* .btn-outline-secondary, by contrast, is this toolbar's filter/toggle-style
   buttons (My Content, the category buttons next to it, Clear filters) — reset
   2026-09-17 per Matt: these had drifted into being solid pink even in their
   "off" state (the same rule this replaced painted every option pink
   unconditionally, so a whole row of untoggled filter buttons all read as
   "on"). Now: white by default, pink only on hover or while actually pressed
   — .btn-website-filter-on (below) is the separate class that marks a filter
   as genuinely toggled on, so it doesn't get this hover-only treatment. */
.pulse-toolbar .btn-outline-secondary {
  background: #ffffff;
  border-color: #fa36cd;
  color: #fa36cd;
}

.pulse-toolbar .btn-outline-secondary:hover {
  background: #fa36cd;
  border-color: #fa36cd;
  color: #ffffff;
}

.pulse-toolbar .btn-outline-secondary:active {
  background: #e01fb5;
  border-color: #e01fb5;
  color: #ffffff;
}

/* My Content's own "on" state (.btn-website-filter-on, above) swaps to a
   different class entirely rather than adding a modifier to this one — see
   Index.cshtml's WebsiteConnectionsOnly check — so it's untouched by the rules
   above and keeps its own distinct "pressed in" pink shade (--pink-active),
   one step darker than the hover-only pink above it, so an actually-selected
   filter still reads differently from one you're just hovering over. */

.pulse-toolbar .form-select,
.pulse-toolbar .form-control {
  border-color: rgba(3, 2, 41, 0.1);
  border-radius: 4px;
  color: #030229;
  font-weight: 500;
}

.pulse-stats .stat-card {
  padding: 1.25rem;
  border-radius: 8px;
}

.pulse-stats .stat-label {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #030229;
  font-weight: 500;
}

.pulse-stats .stat-val {
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Up/down vs-last-month pill, same component as the Figma export's .delta/
   .delta--up/.delta--down — colors darkened from the export's raw #14ca74/#ff5a65
   (tuned for text on its dark navy post cards) for contrast on these white stat
   cards. Index.cshtml only renders this when Model.*DeltaPercent is non-null —
   see IndexModel.CalculateDeltaPercent's own doc comment for why a zero previous-
   month value means no badge rather than a misleading +/-100%. */
.pulse-stats .stat-delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1.3;
}

.pulse-stats .stat-delta-up {
  background: rgba(5, 193, 104, 0.15);
  color: #0a8a4f;
}

.pulse-stats .stat-delta-down {
  background: rgba(255, 90, 101, 0.15);
  color: #d6323c;
}

/* ============================================================================
   Dashboard card → creative preview modal ("click the whole card" feature,
   2026-09-16). .article-card itself just gets a pointer + hover affordance —
   the click is handled by a delegated listener in site.js, which bails out on
   any actual link/button/form control inside the card (Post/Edit/thumbs-down,
   the Source link) so the existing per-button behaviour is untouched.
   ============================================================================ */
.article-card {
  cursor: pointer;
  transition: box-shadow 0.15s ease;
}

.article-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

/* Platform tab row inside #creativePreviewModal (_CreativePreviewModal.cshtml) — brand
   icons/colours per Matt's ask ("use the logo icons... not our pink standard"), so these
   are deliberately outside the shared pink .btn-post-action family above. */
.platform-tabs {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.platform-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 12.5px;
  font-weight: 600;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text-secondary);
  padding: 0.4rem 0.9rem;
}

.platform-tab:hover {
  background: var(--surface-1);
}

.platform-tab.active {
  color: #fff;
  border-color: transparent;
}

/* Active-tab colour = darker brand colour, per platform, so the active button
   reads clearly against the others (Matt: "the button is active (darker colour)"). */
.platform-tab-fb.active { background: #1877F2; }
.platform-tab-ig.active { background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888); }
.platform-tab-li.active { background: #0A66C2; }
.platform-tab-tt.active { background: #000000; }

.platform-preview-stage {
  background: var(--surface-1);
  border-radius: var(--radius);
  padding: 1rem;
  display: flex;
  justify-content: center;
}

/* Lightweight stylized mockups (Matt's call, not pixel-accurate clones) — reuse the
   card's own Title/Description/Image/Video, re-chromed per platform. Only one
   .platform-mock is visible at a time (site.js toggles the [hidden] attribute). */
.platform-mock {
  background: #fff;
  border-radius: 10px;
  overflow: hidden;
  width: 100%;
  max-width: 420px;
  border: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-primary);
}

.mock-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 15px;
}

.mock-media {
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 180px;
  max-height: 320px;
  overflow: hidden;
}

/* Hidden by default; site.js sets style.display on whichever of img/video actually
   has a src for this card (a card can have an image, a video, or neither). */
.mock-media img,
.mock-media video {
  width: 100%;
  max-height: 320px;
  object-fit: cover;
  display: none;
}

.mock-caption {
  font-size: 12.5px;
  line-height: 1.45;
  padding: 0 0.9rem;
}

/* Facebook */
.mock-fb-header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
}
.mock-fb-name { font-weight: 600; font-size: 13px; }
.mock-fb-meta { font-size: 11px; color: var(--text-muted); display: flex; align-items: center; gap: 3px; }
.mock-fb-header + .mock-caption { padding-bottom: 0.75rem; }
.mock-fb-actions {
  display: flex;
  justify-content: space-around;
  padding: 0.5rem 0.9rem;
  border-top: 1px solid var(--border);
  margin-top: 0.5rem;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
}
.mock-fb-actions span { display: inline-flex; align-items: center; gap: 4px; }

/* Instagram */
.mock-ig-header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
}
.mock-avatar-ig { background: linear-gradient(45deg, #f09433, #dc2743, #bc1888); color: #fff; }
.mock-ig-name { font-weight: 600; font-size: 13px; }
.mock-ig-actions {
  display: flex;
  gap: 0.8rem;
  padding: 0.6rem 0.9rem 0.3rem;
  font-size: 18px;
}
.mock-ig-actions + .mock-caption { padding-bottom: 0.9rem; }

/* LinkedIn */
.mock-li-header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
}
.mock-avatar-li { background: #E9F3FF; color: #0A66C2; }
.mock-li-name { font-weight: 600; font-size: 13px; }
.mock-li-meta { font-size: 11px; color: var(--text-muted); }
.mock-li-header + .mock-caption { padding-bottom: 0.75rem; }
.mock-li-actions {
  display: flex;
  justify-content: space-around;
  padding: 0.5rem 0.9rem;
  border-top: 1px solid var(--border);
  margin-top: 0.5rem;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-secondary);
}
.mock-li-actions span { display: inline-flex; align-items: center; gap: 4px; }

/* TikTok — vertical 9:16 frame instead of the feed-post layout the other three
   share, since that's the recognisable "in-situ" shape for this platform. */
.platform-mock-tt {
  background: #000;
  max-width: 260px;
}
.mock-tt-frame {
  position: relative;
  aspect-ratio: 9 / 16;
  background: #000;
}
.mock-tt-media {
  position: absolute;
  inset: 0;
  min-height: 0;
  max-height: none;
}
.mock-tt-media img,
.mock-tt-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.mock-tt-rail {
  position: absolute;
  right: 8px;
  bottom: 70px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  color: #fff;
  font-size: 20px;
}
.mock-tt-rail .mock-avatar-tt {
  width: 32px;
  height: 32px;
  background: #fff;
  color: #000;
  margin-bottom: 4px;
}
.mock-tt-overlay {
  position: absolute;
  left: 10px;
  right: 60px;
  bottom: 16px;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
.mock-tt-name { font-weight: 700; font-size: 13px; margin-bottom: 3px; }
.mock-tt-overlay .mock-caption { padding: 0; font-size: 12px; color: #fff; }

/* ============================================================================
   Website Scrape History table (Pages/WebsiteScrapeHistory.cshtml) — Matt's ask,
   2026-09-16: long unbroken content (the scraped Page URL, and ScrapingBee error
   text that often echoes back a documentation URL) used to force the whole table
   wider than the page, which squeezed the Started date/time onto three lines and
   pushed the per-row Copy button off screen. Trigger/Result/Listings found/Posts
   created are short, fixed-format content, so they're pinned to hug their content
   (the standard "white-space:nowrap + width:1%" trick — cooperates fine with the
   table's existing d-none/d-md-table-cell/d-lg-table-cell responsive hiding, since
   a hidden cell simply isn't part of the width calculation at that breakpoint) —
   whatever space is left goes to the Page/Details columns. Page still shows its
   full URL, just wrapped; Details truncates to one line (the existing title=""
   attribute already gives the full message on hover) so the Copy button — already
   flex-shrink-0 — always stays visible instead of being pushed off the row.
   ============================================================================ */
.scrape-history-col-narrow {
  white-space: nowrap;
  width: 1%;
}

.scrape-history-col-wrap {
  overflow-wrap: anywhere;
}

.scrape-history-error {
  max-width: 320px;
}

.scrape-history-error-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* ============================================================================
   Subscription plans (Shared/_SubscriptionPricingCards.cshtml, shared by
   /Payments and /Settings) — ported 2026-09-17 verbatim (structure + styling,
   not just "inspired by") from Matt's own reference mockup: plans.html/
   plans.css in his "LoopaPulse design export" zip. Every class name below
   (.billing/.seg/.plan/.feat-*/etc.) is that mockup's own.

   2026-09-17 (later same day): rewritten to use plain literal colour/size
   values instead of CSS custom properties (the mockup's own approach, and
   what this block originally used too). Chrome DevTools on the live page
   showed every var(--token) here resolving to "is not defined" even though
   the .subscription {} rule that declares them was confirmed present,
   byte-for-byte, in the actual deployed site.css — something in this
   project's build/bundling step is stripping "--token: value;" custom
   property declarations before the file reaches the browser, while leaving
   ordinary declarations and var(...) *usages* intact (so every rule that
   only used literal values, e.g. .plan--current's background: #fbfbfd,
   still rendered fine, and every rule that depended on a var() silently did
   nothing — exactly the pattern Matt's screenshots showed: card layout and
   text correct, but no borders/backgrounds/button colours anywhere except
   the one literal-colour exception). Hardcoding every value below sidesteps
   that pipeline issue entirely rather than depending on it being fixed.
   Values are unchanged from the custom-property version (including the
   border darkening from --border-sub/--border-strong-sub's original
   mockup values, needed for these colours to actually show up against
   this app's own page background — see the r-sm/r-md/r-lg radii, --ink,
   --pink etc. below inlined at every call site instead of declared once).
   ============================================================================ */
.subscription {
  background: #ffffff;
  border-radius: 12px;
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  color: #030229;
  font-family: 'Mona Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  /* Without this, the white .subscription card blends into the page's own
     off-white background (--surface-0, #f5f5f0) with nothing to mark its
     edges as a distinct card. */
  box-shadow: 0 1px 2px rgba(3, 2, 41, 0.04), 0 1px 3px rgba(3, 2, 41, 0.06);
}

@media (max-width: 700px) {
  .subscription { padding: 18px; }
}

.subscription :focus-visible {
  outline: 2px solid #fa36cd;
  outline-offset: 2px;
}

/* --- Billing toggle --------------------------------------------------------- */
.subscription .billing {
  display: flex;
  align-items: center;
  gap: 12px;
}

.subscription .billing__label {
  font-size: 13px;
  font-weight: 500;
}

.subscription .seg {
  display: inline-flex;
  border: 1px solid #d7dae4;
  border-radius: 6px;
  overflow: hidden;
}

.subscription .seg__opt {
  padding: 8px 18px;
  background: #ffffff;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: #4a5372;
}

.subscription .seg__opt:hover {
  background: #f2f4f8;
}

.subscription .seg__opt--active,
.subscription .seg__opt--active:hover {
  background: #030229;
  font-weight: 600;
  color: #ffffff;
}

/* --- Plan grid --------------------------------------------------------------- */
.subscription .plans {
  background: #f7f8fa;
  border-radius: 12px;
  padding: 28px;
}

/* The mockup's own plans.css used minmax(220px, 1fr) with a 40px .plans
   padding, sized for a full-bleed page with no side navigation. This app's
   .app-main sits beside a 220px .app-sidebar inside a 1440px-max .app-body,
   so the real content width available here tops out around ~1050-1100px —
   not enough room for all 5 tiers at 220px columns (5 × 220px + 4 × 16px
   gaps = 1164px needed), which is exactly why a 5th tier used to wrap onto
   its own row and stretch to fill it. Narrowing the column minimum and the
   surrounding padding keeps every tier on one row on a normal desktop
   viewport while still reflowing normally on narrower ones (and collapsing
   to a single column under the existing 700px breakpoint below). */
.subscription .plans__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  align-items: stretch;
}

/* --- Plan card --------------------------------------------------------------- */
.subscription .plan {
  position: relative;
  padding: 22px 18px;
  background: #ffffff;
  border: 1px solid #cfd4e2;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
}

/* 2026-09-17: there's no "recommended tier" feature any more (it was a
   hardcoded SystemName == "GOLD" check that never reflected what a Client
   actually bought — see _SubscriptionPricingCards.cshtml's own comment). The
   pink ribbon/border that used to mark the recommended tier now marks
   whichever tier tier.IsCurrentTier says is the real, actually-subscribed
   one, so .plan--recommended is gone and .plan--current takes over its pink
   treatment instead of its old plain grey one. */
.subscription .plan--current {
  border-color: #fa36cd;
}

.subscription .plan__ribbon {
  position: absolute;
  top: -13px;
  right: -1px;
  height: 26px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  background: #fa36cd;
  border-radius: 4px 4px 0 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #ffffff;
  white-space: nowrap;
}

.subscription .plan__head {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.subscription .plan__name {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
}

.subscription .plan__desc {
  font-size: 13px;
  line-height: 18px;
  color: #6b7391;
  margin: 0;
}

.subscription .plan__price {
  margin: 34px 0 0;
  display: flex;
  align-items: baseline;
  gap: 5px;
}

.subscription .plan__amount {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 40px;
}

.subscription .plan__unit {
  padding-bottom: 1px;
  border-bottom: 1px solid #d7dae4;
  font-size: 13px;
  color: #6b7391;
}

/* --- Plan CTA --------------------------------------------------------------- */
.subscription .plan__cta {
  margin-top: 20px;
  height: 44px;
  width: 100%;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
}

.subscription .plan__cta--ink {
  background: #081028;
  color: #ffffff;
}
.subscription .plan__cta--ink:hover { background: #16224a; }
.subscription .plan__cta--ink:active { background: #1f2c5c; }

.subscription .plan__cta--pink {
  background: #fa36cd;
  color: #ffffff;
}
.subscription .plan__cta--pink:hover { background: #e01fb5; }
.subscription .plan__cta--pink:active { background: #c7189f; }

.subscription .plan__cta--ghost {
  background: #ffffff;
  border: 1px solid #b7bdd1;
  color: #030229;
}
.subscription .plan__cta--ghost:hover { background: #f2f4f8; }
.subscription .plan__cta--ghost:active { background: #e8ebf2; }

.subscription .plan__cta--current {
  background: #ffffff;
  border: 1px solid #b7bdd1;
  color: #4a5372;
  cursor: default;
}

/* --- Features ---------------------------------------------------------------- */
.subscription .plan__lead {
  margin-top: 26px;
  font-size: 12px;
  line-height: 18px;
  color: #6b7391;
}

.subscription .plan__groups {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.subscription .feat-group {
  display: flex;
  flex-direction: column;
  gap: 11px;
}

.subscription .feat-group__title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
  margin: 0;
}

.subscription .feat-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.subscription .feat {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  color: #3d4560;
}

.subscription .feat__check {
  flex: 0 0 13px;
  margin-top: 3px;
  color: #fa36cd;
}

.subscription .feat__label {
  font-size: 12.5px;
  line-height: 18px;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-decoration-color: #c2c8d6;
  text-underline-offset: 3px;
}

@media (max-width: 700px) {
  .subscription .plans { padding: 24px 16px; }
  .subscription .plans__grid { grid-template-columns: 1fr; }
  .subscription .plan__ribbon { top: -13px; right: 12px; }
}

/* ============================================================================
   Legal pages (Pages/Privacy.cshtml, Pages/termsandconditions.cshtml) — long-form
   copy inside a .stat-card. Scoped to .legal-content so headings/lists here
   don't affect card markup elsewhere.
   ============================================================================ */
.legal-content {
  max-width: 900px;
  font-size: 0.9rem;
  line-height: 1.6;
}

.legal-content h2 {
  font-size: 1rem;
  font-weight: 600;
  margin: 1.75rem 0 0.6rem;
}

.legal-content h3 {
  font-size: 0.9rem;
  font-weight: 600;
  margin: 1.25rem 0 0.4rem;
}

.legal-content p,
.legal-content ul,
.legal-content ol {
  margin-bottom: 0.75rem;
}

.legal-content a {
  word-break: break-word;
}

/* ============================================================================
   Site footer (Pages/Shared/_Footer.cshtml), from the Loopa Pulse website design in
   Figma: black, centred logo, blurb, a link bar between hairlines, then the legal line.
   Rendered by _Layout, _LayoutAuth, _LayoutPublic and _LayoutWebsite. Boxed to the same
   1440px as .app-topnav/.app-body.
   ============================================================================ */
.site-footer {
  background: #000;
  color: #fff;
  max-width: 1440px;
  margin: 0 auto;
  font-size: 0.875rem;
}

.site-footer-inner {
  max-width: 806px;
  margin: 0 auto;
  padding: 85px 1.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 46px;
  text-align: center;
}

.site-footer-logo-link {
  display: block;
  line-height: 0;
}

.site-footer-logo {
  height: 86px;
  width: auto;
  max-width: 100%;
}

.site-footer-blurb {
  margin: 0;
  width: 100%;
  font-size: 16px;
  line-height: 1.55;
  letter-spacing: -0.48px;
}

.site-footer-menu {
  width: 100%;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 1rem 118px;
  padding: 18px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  font-weight: 700;
  font-size: 14px;
  line-height: 1.45;
  letter-spacing: -0.56px;
}

.site-footer a {
  color: #fff;
  text-decoration: none;
}

.site-footer a:hover {
  color: #fa36cd;
}

.site-footer-legal {
  font-size: 12px;
  line-height: 1.55;
  letter-spacing: -0.36px;
}

.site-footer-legal-links {
  display: flex;
  justify-content: center;
  gap: 0.6rem;
}

.site-footer-company {
  margin-top: 0.4rem;
  color: rgba(255, 255, 255, 0.6);
}

@media (max-width: 767.98px) {
  .site-footer-inner {
    padding: 56px 1rem;
    gap: 32px;
  }

  .site-footer-logo {
    height: 56px;
  }

  .site-footer-menu {
    gap: 0.75rem 2rem;
  }
}

/* _LayoutPublic has no sidebar, so let the content breathe a little more. */
.public-body .app-main {
  padding: 2rem 1.5rem;
}
