/* Poppins is Fillow's actual rendered body font (its dlabnav-init.js requests typography:"poppins"
   on every page load, overriding the Roboto fallback its settings.js otherwise defaults to).
   Imported here, in the one shared stylesheet, rather than editing every view file's own <head> —
   each page's existing Inter <link> tag becomes a harmless unused fetch until cleaned up per-page. */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap");
:root{
  --bg:#f6f7fa; --surface:#ffffff; --border:#e9ebf0; --text:#12151c; --muted:#6b7280;
  /* Fillow's own real primary purple family (--primary/--primary-hover/--rgba-primary-1 from its
     compiled :root), not an approximation of the previous brand purple. */
  --brand:#886cc0; --brand-dark:#6c4bae; --brand-light:rgba(136,108,192,.1);
  /* --accent was a purple-blue picked to complement the OLD brand purple — replaced with Fillow's
     own secondary pink family (--secondary:#FFA7D7, --secondary-light equivalent #ffdaee in its
     compiled :root). --accent itself is used directly as small icon/text color on a pale tint
     background (.icon-accent, .stat-icon.accent) — Fillow's own #FFA7D7 is too light to read as
     text, so this is a darker rose from the same hue family instead of the literal fill value. */
  --accent:#c2368a; --accent-light:#ffdaee;
  /* Fillow's own actual semantic colors (--bs-warning/--bs-danger/--bs-info/--bs-success in its
     compiled :root) — note info is a magenta/pink in Fillow, not the teal previously used here.
     Each *-light tint/legible-text-on-tint pairing is derived from that same real hue, same pattern
     as --brand/--brand-dark above. */
  --warn:#a66a00; --warn-light:#fff6d9;
  --danger:#c81a3b; --danger-light:#ffe0e6;
  --info:#9c2f8f; --info-light:#fbe6f8;
  --success:#0d8f2f; --success-light:#e3f9e8;
  --slate:#64748b; --slate-light:#eef1f5;
  /* --radius matches Fillow's actual .card radius (0.625rem); --shadow its actual card shadow
     (0rem .3125rem .3125rem 0rem rgba(82,63,105,.05)) — real extracted values, not approximations. */
  --radius:10px; --radius-sm:12px; --radius-lg:28px;
  --shadow:0 5px 5px rgba(82,63,105,.05);
  --shadow-hover:0 10px 20px rgba(82,63,105,.1);
  /* Bootstrap's own default blue, recoloured to the brand purple — covers focus rings, checked
     switches/checkboxes/radios, links, spinners, and anything else Bootstrap itself drives off
     these tokens. Loaded after bootstrap.min.css on every page, so this wins the cascade. */
  --bs-primary:#886cc0; --bs-primary-rgb:136,108,192;
  --bs-primary-text-emphasis:#6c4bae; --bs-primary-bg-subtle:#f3eefb; --bs-primary-border-subtle:#886cc0;
  --bs-link-color:#6c4bae; --bs-link-color-rgb:108,75,174;
  --bs-link-hover-color:#886cc0; --bs-link-hover-color-rgb:136,108,192;
  --bs-focus-ring-color:rgba(136,108,192,.25);
  /* Bootstrap's OWN semantic tokens (used by .alert-*/.btn-*/.badge.bg-*/.text-bg-* etc, which our
     own --warn/--danger/--info/--success above don't reach — those are only read by this app's own
     custom classes like .badge-soft/.stat-icon) — mapped to the same Fillow-sourced values so a
     plain Bootstrap alert/badge/button matches too, not just our own components. */
  --bs-warning:#ffbf00; --bs-warning-rgb:255,191,0;
  --bs-warning-text-emphasis:#a66a00; --bs-warning-bg-subtle:#fff6d9; --bs-warning-border-subtle:#ffbf00;
  --bs-danger:#fc2e53; --bs-danger-rgb:252,46,83;
  --bs-danger-text-emphasis:#c81a3b; --bs-danger-bg-subtle:#ffe0e6; --bs-danger-border-subtle:#fc2e53;
  --bs-info:#d653c1; --bs-info-rgb:214,83,193;
  --bs-info-text-emphasis:#9c2f8f; --bs-info-bg-subtle:#fbe6f8; --bs-info-border-subtle:#d653c1;
  --bs-success:#09bd3c; --bs-success-rgb:9,189,60;
  --bs-success-text-emphasis:#0d8f2f; --bs-success-bg-subtle:#e3f9e8; --bs-success-border-subtle:#09bd3c;
}
.btn-primary{--bs-btn-bg:var(--brand);--bs-btn-border-color:var(--brand);--bs-btn-hover-bg:var(--brand-dark);--bs-btn-hover-border-color:var(--brand-dark);--bs-btn-active-bg:var(--brand-dark);--bs-btn-active-border-color:var(--brand-dark);--bs-btn-focus-shadow-rgb:136,108,192}
.btn-outline-primary{--bs-btn-color:var(--brand-dark);--bs-btn-border-color:var(--brand);--bs-btn-hover-bg:var(--brand);--bs-btn-hover-border-color:var(--brand);--bs-btn-active-bg:var(--brand);--bs-btn-active-border-color:var(--brand)}
.text-primary{color:var(--brand)!important}
.bg-primary{background-color:var(--brand)!important}
.border-primary{border-color:var(--brand)!important}
.form-check-input:checked{background-color:var(--brand);border-color:var(--brand)}
.form-check-input:focus{border-color:var(--brand);box-shadow:0 0 0 .25rem var(--brand-light)}
.form-control:focus,.form-select:focus{border-color:var(--brand);box-shadow:0 0 0 .25rem var(--brand-light)}
.accordion-button:not(.collapsed){background-color:var(--brand-light);color:var(--brand-dark);box-shadow:inset 0 -1px 0 var(--border)}
.accordion-button:focus{border-color:var(--brand);box-shadow:0 0 0 .25rem var(--brand-light)}
.list-group-item.active{background-color:var(--brand);border-color:var(--brand)}
.progress-bar{background-color:var(--brand)}
.spinner-border,.spinner-grow{color:var(--brand)}
html{overflow-x:hidden}
body{background:var(--bg);color:var(--text);font-family:'Poppins',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;letter-spacing:-.011em;font-size:.95rem}
/* A faint accent glow in the corner, same idea as the reference dashboard's page background — subtle enough to not fight with card content sitting on top of it. */
body.bg-light{background:radial-gradient(1100px 550px at 100% -8%,rgba(136,108,192,.07),transparent),var(--bg)}
/* ---- pagination — Bootstrap defaults to blue; recolour to the brand green ---- */
.pagination{gap:.25rem}
.page-link{color:var(--brand-dark);border-color:var(--border);border-radius:var(--radius-sm)!important;margin-left:0}
.page-link:hover{color:var(--brand-dark);background:var(--brand-light);border-color:var(--border)}
.page-link:focus{box-shadow:0 0 0 .2rem var(--brand-light)}
.page-item.active .page-link{background:var(--brand);border-color:var(--brand);color:#fff}
.page-item.disabled .page-link{color:var(--muted);background:var(--surface);border-color:var(--border)}
/* Sticky footer: on short pages the footer sits at the bottom of the viewport instead of right after the content with empty space below it. Scoped to body.bg-light (every admin/client portal page) so the auth/login split-screen layout is untouched. */
body.bg-light{min-height:100vh;display:flex;flex-direction:column}
body.bg-light > main{flex:1 0 auto}
/* Room for the fixed left sidebar (.app-topbar) — padding on body rather than a margin on <main>
   itself so Bootstrap's own .container auto-centering still centers correctly within the remaining
   width, and any other in-flow sibling of the nav (e.g. the outdated-storefront-domain banner) gets
   the same offset for free without needing its own rule. Removed on the mobile breakpoint where the
   sidebar itself stops being fixed (see .app-topbar's own mobile override above). */
body.bg-light{padding-left:250px}
@media (max-width:900px){body.bg-light{padding-left:0}}
h1,h2,h3,h4,h5,h6{letter-spacing:-.025em;font-weight:800}
a{color:var(--brand-dark)}

/* ---- left sidebar navigation (desktop) — Fillow's actual default look: a white/light fixed
   column with a soft lavender header strip behind the logo, NOT a dark sidebar (an earlier revision
   here used a dark gradient — replaced to match Fillow's real [data-sidebar-style="full"] .dlabnav
   colors: --sidebar-bg:#FFFFFF, --nav-headbg:#e9e2f8, nav-link color var(--text-gray), active item
   gets a soft var(--rgba-primary-1) pill with primary-colored text, per Fillow's own
   .dlabnav .metismenu > li.mm-active > a rule). Main content is offset by its width via the sibling
   rules under "page shell" below, rather than touching every view file's markup. Falls back to the
   original horizontal top bar under the mobile breakpoint at the bottom of this section, so a
   narrow screen never has to fit a fixed 250px rail plus content side by side. ---- */
/* height:100vh alongside top:0/bottom:0 — belt-and-suspenders against the sidebar falling short of
   the actual viewport bottom (seen on some browser/zoom combinations where top+bottom alone left a
   gap of page background visible beneath it); this forces the box's own height explicitly rather
   than relying solely on the two-offset shorthand to compute it. */
.app-topbar{position:fixed;left:0;top:0;bottom:0;height:100vh;width:250px;background:var(--surface);border-right:1px solid var(--border);box-shadow:0 15px 30px rgba(0,0,0,.02);z-index:1030;overflow-y:hidden;transition:width .18s ease}
/* No scroll at all, by design — the spacing below is tight enough that the whole sidebar fits a
   normal viewport height outright. overflow-y:auto here previously caused a 1-2px "wobble" scroll
   whenever content landed exactly at (or a hair past) the container's height, which read as the
   sidebar's own content shifting on its own; hidden removes that possibility entirely rather than
   trying to shave the last pixel off. */
.app-topbar>div{display:flex;flex-direction:column;height:100%;padding:0 .8rem;gap:0}
/* The lavender header strip Fillow's --nav-headbg paints behind the logo row specifically — full
   bleed (negative margin cancels the column's own side padding) so the tint reaches the sidebar's
   actual edges instead of floating as an inset rectangle. */
.app-topbar .brand{background:var(--brand-strip-bg,#e9e2f8);color:var(--text);font-weight:800;font-size:1.05rem;text-decoration:none;display:flex;align-items:center;gap:.5rem;letter-spacing:-.02em;padding:1.1rem .8rem;margin:0 -.8rem .4rem;min-width:0}
.app-topbar .brand .dot{width:9px;height:9px;border-radius:50%;background:var(--brand);box-shadow:0 0 0 4px rgba(136,108,192,.25);flex:none}
.app-topbar .brand .label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.app-topbar .brand img{max-width:100%}
/* Shown only when collapsed (see body.sidebar-collapsed below) — the platform's own small favicon
   mark, or a lettered fallback square if none has been uploaded; either way this is what replaces
   the full wordmark logo, which doesn't fit a 76px icon-only rail. */
.app-topbar .brand-favicon{display:none;width:28px;height:28px;border-radius:8px;flex:none;align-items:center;justify-content:center;background:linear-gradient(135deg,#886cc0,#6c4bae);color:#fff;font-weight:800;font-size:.85rem;object-fit:contain}

/* ---- collapse toggle — sits just under the logo; collapses the sidebar to an icon-only rail.
   State lives on <body> (sidebar-collapsed) so one class also drives the body padding-left offset
   below, and is persisted to localStorage by the nav's own inline script. ---- */
.app-sidebar-toggle{display:flex;align-items:center;justify-content:center;width:100%;padding:.5rem;margin-top:.5rem;border-radius:10px;background:var(--bg);border:none;color:var(--muted);cursor:pointer;transition:background .15s ease,color .15s ease}
.app-sidebar-toggle:hover{background:var(--brand-light);color:var(--brand-dark)}
.app-sidebar-toggle svg{transition:transform .18s ease}

/* flex:1 + min-height:0 is what actually makes this region absorb the leftover height inside the
   fixed-height sidebar and scroll on its own — without min-height:0 a flex child never shrinks
   below its content size, so an expanded dropdown group (e.g. Affiliates/Qualiphy) would instead
   grow the whole sidebar and push the toggle button + profile card out of view below it. */
.app-nav-scroll{display:flex;flex-direction:column;gap:.1rem;flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding-top:.5rem;scrollbar-width:thin;scrollbar-color:var(--border) transparent}
.app-nav-scroll::-webkit-scrollbar{width:6px}
.app-nav-scroll::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
/* Fillow's signature active-item shape: a soft primary-tinted pill whose right edge is rounded
   differently top vs bottom (border-top-right-radius:.5rem / border-bottom-right-radius:2.5rem on
   .mm-active > a) — a distinctive detail, not a plain rounded-rect highlight. */
.app-nav-link{display:flex;align-items:center;gap:.7rem;color:var(--muted);text-decoration:none;font-size:.87rem;font-weight:600;padding:.6rem .9rem;border-radius:10px;transition:background .15s ease,color .15s ease;white-space:nowrap}
.app-nav-link:hover{color:var(--brand)}
.app-nav-link.active{color:var(--brand-dark);background:var(--brand-light);font-weight:700;border-top-right-radius:.5rem;border-bottom-right-radius:2.5rem}
.app-nav-link svg{flex:none}
/* Subscription-required state — cosmetic only (see App\Filters\SubscriptionFilter for the real, server-side enforcement). Greys the item out and shows a small lock icon instead of navigating. */
.app-nav-link.locked,.app-nav-group-toggle.locked,.app-icon-btn.locked{opacity:.45;cursor:not-allowed;pointer-events:none}
.app-nav-link.locked .lock-icon,.app-nav-group-toggle.locked .lock-icon{margin-left:auto;flex:none}

/* ---- nav "Qualiphy" group — an inline expand/collapse (Bootstrap's collapse component, not
   dropdown) since a floating popper menu has nowhere sensible to open from inside a 250px-wide
   fixed column when the sidebar itself is expanded; the sub-links just indent in place instead.
   (When the sidebar is COLLAPSED instead, this same group becomes a genuine Fillow-style hover
   flyout — see the .app-nav-flyout rules further down.) ---- */
.app-nav-group-toggle{cursor:pointer}
.app-nav-group-toggle .chev{margin-left:auto;transition:transform .15s ease;flex:none}
.app-nav-group-toggle[aria-expanded="true"] .chev{transform:rotate(180deg)}
/* Scoped to collapses inside the nav (not a blanket .collapse rule — that class is also used for
   unrelated things like accordions) — without this gap, an active sub-item's highlight pill sits
   flush against the group toggle row above it with no breathing room, reading as one merged shape. */
.app-nav-scroll .collapse{padding-top:.3rem}
.app-nav-subitem{display:block;color:var(--muted);text-decoration:none;font-size:.83rem;font-weight:500;padding:.45rem .7rem .45rem 2.5rem;border-radius:10px}
.app-nav-subitem:hover{color:var(--brand)}
.app-nav-subitem.active{color:var(--brand-dark);background:var(--brand-light);font-weight:700}

/* ---- header bar — a slim strip above the page content (offset by the sidebar's width the same
   way <main> is, via body's own padding-left, so it needs no per-view-file changes) holding the
   icon buttons (Client Hub / notifications / announcements / support) and, on the client side, the
   rotating notification ticker. A real surface (white + brand-gradient top edge + shadow) rather
   than blending flat into the plain grey page background. Sticky so both stay reachable on a long,
   scrolled page, same as the old horizontal nav used to be. ---- */
.app-header-bar{position:sticky;top:0;z-index:1020;display:flex;justify-content:space-between;align-items:center;gap:1rem;padding:.9rem 2rem;background:var(--surface);border-bottom:1px solid var(--border);box-shadow:var(--shadow)}
.app-header-bar::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--brand),var(--accent))}
.app-icon-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:11px;color:var(--muted);background:var(--bg);border:1px solid var(--border);text-decoration:none;font-size:1.1rem;flex:none;transition:background .15s ease,color .15s ease}
.app-icon-btn:hover{background:var(--brand-light);color:var(--brand-dark)}
.app-icon-btn.active{background:var(--brand-light);color:var(--brand-dark)}
/* Color variants — each header-bar icon gets its own soft tint (same brand/accent/info language as
   .stat-icon elsewhere) instead of one flat grey, so they're easier to tell apart at a glance. */
.app-icon-btn.icon-brand{color:var(--brand-dark);background:var(--brand-light);border-color:transparent}
.app-icon-btn.icon-accent{color:var(--accent);background:var(--accent-light);border-color:transparent}
.app-icon-btn.icon-info{color:var(--info);background:var(--info-light);border-color:transparent}
.app-icon-btn.icon-warn{color:var(--warn);background:var(--warn-light);border-color:transparent}
.app-icon-btn.icon-brand:hover,.app-icon-btn.icon-brand.active{background:var(--brand);color:#fff}
.app-icon-btn.icon-accent:hover,.app-icon-btn.icon-accent.active{background:var(--accent);color:#fff}
.app-icon-btn.icon-info:hover,.app-icon-btn.icon-info.active{background:var(--info);color:#fff}
.app-icon-btn.icon-warn:hover,.app-icon-btn.icon-warn.active{background:var(--warn);color:#fff}
/* ---- header profile avatar dropdown trigger — Fillow's .header-profile is just the bare avatar
   with no button chrome around it (no border/background of its own), a ring appearing only on
   hover/open. ---- */
.app-header-profile{display:inline-flex;border:none;background:none;padding:2px;border-radius:50%;transition:box-shadow .15s ease}
.app-header-profile:hover,.app-header-profile[aria-expanded="true"]{box-shadow:0 0 0 3px var(--brand-light)}
/* Fillow's actual dropdown treatment: no border, a wide soft shadow instead — applies to every
   Bootstrap dropdown app-wide (notification/hub/profile panels, filter dropdowns, table row actions,
   etc.), not just these header ones, so any dropdown anywhere in the app already reads this. */
.dropdown-menu{border:0;box-shadow:0 0 2.3125rem rgba(8,21,66,.08)}
.dropdown-item{border-radius:8px}
.dropdown-item:active,.dropdown-item.active{background:var(--brand);color:#fff}
[data-theme="dark"] .dropdown-menu{box-shadow:0 0 0 1px rgba(255,255,255,.1)}
.app-icon-btn .notif-dot{position:absolute;top:-5px;right:-5px;background:var(--danger,#e5484d);color:#fff;border-radius:999px;font-size:.64rem;font-weight:700;min-width:17px;height:17px;display:inline-flex;align-items:center;justify-content:center;padding:0 .3rem;border:2px solid var(--surface)}

/* Logout — the rightmost item in the header bar on every dashboard, deliberately distinct from
   the brand/accent/info icon tints (a danger tint) since ending your session isn't just another
   nav shortcut. */
.app-logout-btn{display:inline-flex;align-items:center;gap:.4rem;height:38px;padding:0 .9rem;border-radius:11px;background:var(--danger-light);color:var(--danger);border:1px solid transparent;font-size:.82rem;font-weight:700;white-space:nowrap;transition:background .15s ease,color .15s ease}
.app-logout-btn:hover{background:var(--danger);color:#fff}

/* ---- notification ticker — one line, rotating through whatever's actually new (order/message/
   announcement/support), each entry stacked in the same box and swapped via a vertical slide. ---- */
.app-notif-ticker{position:relative;height:24px;overflow:hidden;flex:1 1 auto;min-width:0}
.app-notif-ticker-item{position:absolute;inset:0;display:flex;align-items:center;gap:.4rem;font-size:.85rem;font-weight:600;color:var(--text);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:0;transform:translateY(100%);transition:transform .5s ease,opacity .4s ease;pointer-events:none}
.app-notif-ticker-item.current{opacity:1;transform:translateY(0);pointer-events:auto}
.app-notif-ticker-item.leaving{opacity:0;transform:translateY(-100%)}
.app-notif-ticker-item .label{color:var(--brand-dark);font-weight:800}
.app-notif-ticker-item:hover{color:var(--brand-dark)}

/* ---- user card + logout, pinned to the bottom of the sidebar via margin-top:auto ---- */
/* Now the way to reach Profile/Settings — pulled out of the main nav list, reachable by clicking
   your own name/avatar instead, the same "account menu lives with the account" pattern most
   dashboards use. */
.app-user-card{margin-top:auto;margin-bottom:.8rem;display:flex;align-items:center;gap:.6rem;padding:.6rem;border-radius:12px;background:var(--bg);text-decoration:none;transition:background .15s ease}
.app-user-card:hover{background:var(--brand-light)}
.app-user-card.active{background:var(--brand-light)}
.app-user-avatar{width:34px;height:34px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.8rem;color:#fff;background:linear-gradient(135deg,#886cc0,#6c4bae)}
.app-user-name{font-size:.82rem;font-weight:700;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.app-user-role{font-size:.72rem;color:var(--muted)}

/* ---- collapsed state — icon-only rail; toggled by JS adding/removing this class on <body>,
   persisted in localStorage so it survives navigation between pages. ---- */
body.sidebar-collapsed{padding-left:76px}
body.sidebar-collapsed .app-topbar{width:76px}
body.sidebar-collapsed .app-sidebar-toggle svg{transform:rotate(180deg)}
body.sidebar-collapsed .brand .label,
body.sidebar-collapsed .brand .dot,
body.sidebar-collapsed .brand img.brand-logo,
body.sidebar-collapsed .app-nav-link .label,
body.sidebar-collapsed .app-nav-subitem,
body.sidebar-collapsed .chev,
body.sidebar-collapsed .app-user-name,
body.sidebar-collapsed .app-user-role{display:none}
/* The full wordmark logo doesn't fit a 76px rail — swap it for the platform's own small favicon
   mark instead of letting the wordmark image just overflow/clip against the narrow column. */
body.sidebar-collapsed .brand-favicon{display:flex}
body.sidebar-collapsed .brand{justify-content:center}
/* ---- Fillow-style collapsed-sidebar flyout — a group's submenu (e.g. Qualiphy) floats beside the
   icon rail on hover instead of disappearing. Mechanics adapted from Fillow's
   [data-sidebar-style="mini"] .metismenu li:hover>ul rule: display:none by default, revealed via
   :hover on the wrapping .app-nav-group (not the toggle itself, so the pointer can travel from icon
   to flyout without it closing), positioned absolute flush against the collapsed rail's own width,
   background/shadow/radius pulled from Fillow's actual values rather than approximated. The click-to-
   expand behavior (Bootstrap's own .collapse/.show) is untouched for the non-collapsed sidebar —
   these rules only apply once body.sidebar-collapsed is active. */
/* Both .app-topbar (overflow-y:hidden) and .app-nav-scroll (overflow-x:hidden) clip anything that
   tries to visually escape the collapsed 76px rail — including this flyout, which needs to extend
   past it. Setting overflow:visible only in the collapsed state lets the flyout render outside the
   rail; the expanded sidebar's own scrollbar is untouched since these rules are scoped to
   body.sidebar-collapsed. */
body.sidebar-collapsed .app-topbar{overflow:visible}
body.sidebar-collapsed .app-nav-scroll{overflow:visible}
body.sidebar-collapsed .app-nav-group{position:relative}
body.sidebar-collapsed .app-nav-flyout{display:none!important;position:absolute;left:76px;top:0;min-width:13rem;margin:0;padding:.5rem;background:var(--surface);border-radius:var(--radius-sm);box-shadow:0 0 2.5rem rgba(82,63,105,.16);z-index:1040}
/* Driven by JS (.js-open), not :hover — a fast/diagonal mouse path from the icon to a lower
   flyout item can land on a frame where the pointer isn't over EITHER box for an instant, and
   plain :hover has no memory of "was just here a moment ago", so it snaps shut mid-move. JS tracks
   mouseenter/mouseleave on the group with a short close delay instead, so the flyout survives that
   momentary gap. */
body.sidebar-collapsed .app-nav-group.js-open .app-nav-flyout{display:block!important}
body.sidebar-collapsed .app-nav-flyout .app-nav-subitem{display:block;padding:.5rem .7rem;color:var(--text)}
body.sidebar-collapsed .app-nav-flyout .app-nav-subitem:hover{color:var(--brand-dark);background:var(--brand-light)}
body.sidebar-collapsed .app-nav-flyout .app-nav-subitem.active{color:var(--brand-dark);background:var(--brand-light);font-weight:700}
[data-theme="dark"] body.sidebar-collapsed .app-nav-flyout{box-shadow:0 0 0 1px rgba(255,255,255,.1)}
body.sidebar-collapsed .app-nav-link,
body.sidebar-collapsed .app-nav-group-toggle{justify-content:center;padding-left:0;padding-right:0}
body.sidebar-collapsed .app-user-card{justify-content:center;padding:.5rem}
@media (max-width:900px){body.sidebar-collapsed{padding-left:0}body.sidebar-collapsed .app-topbar{width:100%}}

/* Hard CSS backstop for the nav icon tooltips (see _nav.php's customClass:'app-nav-tooltip') — the
   JS enable()/disable() toggle can lose a hover-vs-toggle timing race the same way the notification
   bell's tooltip once could, so this guarantees one can never render while the sidebar isn't
   collapsed, independent of whatever state the JS side thinks it's in. */
body:not(.sidebar-collapsed) .app-nav-tooltip{display:none !important}

/* ---- mobile fallback: below this width there's no room for a fixed 250px rail alongside content,
   so the sidebar becomes a normal, non-fixed block that flows above the page content instead of
   beside it — still a vertical list (nothing needs to fit side-by-side, so nothing can overflow),
   just taller, with the page scrolling past it like any other in-flow section. ---- */
@media (max-width:900px){
  .app-topbar{position:static;width:100%;height:auto;box-shadow:0 2px 16px rgba(82,63,105,.18)}
  .app-topbar>div{padding:1rem;height:auto}
  .app-user-card{display:none}
  .app-sidebar-toggle{margin-top:.75rem}
  .app-header-bar{flex-wrap:wrap;padding:.9rem 1rem}
}

/* ---- footer ---- */
.app-footer{background:transparent;margin-top:2.5rem;border-top:1px solid var(--border)}
.app-footer-inner{display:flex;align-items:center;gap:1rem;padding:1.35rem 0;flex-wrap:wrap}
.app-footer-brand{display:flex;align-items:center;gap:.5rem;font-weight:800;color:var(--text);flex:1 1 0;min-width:160px;letter-spacing:-.02em;font-size:.9rem}
.app-footer-brand img{max-height:20px}
.app-footer-brand .dot{width:8px;height:8px;border-radius:50%;background:var(--brand);box-shadow:0 0 0 4px var(--brand-light)}
/* Swaps to the light-background-suited logo variant in dark mode — only when both variants were
   actually uploaded (.has-theme-logos), so a client/admin who's only ever set one logo still sees it
   in both themes instead of the footer going blank in dark mode. */
.app-footer-brand .footer-logo-dark-mode{display:none}
[data-theme="dark"] .app-footer-brand.has-theme-logos .footer-logo-light-mode{display:none}
[data-theme="dark"] .app-footer-brand.has-theme-logos .footer-logo-dark-mode{display:inline-block}
.app-footer-copy{flex:1 1 0;text-align:center;font-size:.82rem;color:var(--muted);white-space:nowrap}
.app-footer-email{flex:1 1 0;text-align:right;font-size:.82rem;min-width:160px}
.app-footer-email a{color:var(--text);text-decoration:none;font-weight:600}
.app-footer-email a:hover{color:var(--brand-dark)}
@media (max-width:700px){.app-footer-inner{flex-direction:column;text-align:center}.app-footer-brand,.app-footer-copy,.app-footer-email{text-align:center;justify-content:center}}

/* ---- surfaces — Fillow's cards are borderless, relying on box-shadow alone for separation from
   the page background (border:0rem in its compiled .card rule) rather than a border+shadow combo. ---- */
.card{border:0;border-radius:var(--radius);box-shadow:var(--shadow);transition:box-shadow .2s ease,transform .2s ease}
.card.hover-lift:hover{box-shadow:var(--shadow-hover);transform:translateY(-3px)}
/* Bootstrap's stock .card-header has a subtle background tint and tight padding — Fillow's is
   transparent with roomier padding and a plain border, matching its actual .card-header/.card-title. */
.card-header{background:transparent;border-color:var(--border);padding:1.5rem 1.875rem 1.25rem}
.card-title{font-size:1.25rem;font-weight:600;color:var(--text);text-transform:capitalize}
.card-footer{background:transparent;border-color:var(--border);padding:1.25rem 1.875rem}
/* Scoped to just cards wrapping a stat-card (via :has(), not a blanket rule on .card) so the
   stat-card's own decorative corner blur — which deliberately bleeds past its own inner box — gets
   clipped to the outer card's rounded corner instead of squaring it off, without risking clipping
   something like a dropdown menu nested inside an unrelated .card elsewhere. */
.card:has(>.card-body.stat-card),.card:has(>.stat-card){overflow:hidden}
/* Lets a stat card itself be the <a> (clickable tile through to its detail page) instead of just a div. */
a.card{display:block;color:inherit;text-decoration:none}
a.card:hover{color:inherit}
.card-body{padding:1.6rem}

/* ---- stat cards ---- */
/* No background here on purpose — this sits inside a separate .card wrapper (<a class="card"><div
   class="card-body stat-card">), and painting an opaque background on THIS inner div (a plain
   rectangle, no border-radius of its own) covered up the outer .card's rounded corners entirely,
   making every tile look square despite .card's own border-radius being correct. The outer .card
   already gets a white background from Bootstrap's own .card rule, which IS properly rounded. */
/* Layout matches Fillow's actual .widget-stat tile (widget-basic.html): a large round tinted icon
   to the left, label+value stacked to its right — not a vertical icon-then-text stack, and no
   decorative corner-blur (that was this app's own invention, not part of Fillow's design). Grid
   only kicks in when a .stat-card-top/.stat-icon is actually present (:has()) — several pages use
   .stat-card with just a label+value and no icon at all, which keeps the plain vertical stack. */
.stat-card{position:relative;display:flex;flex-direction:column;gap:.4rem;overflow:hidden}
.stat-card:has(.stat-card-top){display:grid;grid-template-columns:auto 1fr;column-gap:1rem;align-items:center}
.stat-card:has(.stat-card-top) .stat-card-top{grid-column:1;grid-row:1/3}
.stat-card:has(.stat-card-top) .stat-label{grid-column:2;grid-row:1}
.stat-card:has(.stat-card-top) .stat-value{grid-column:2;grid-row:2}
.stat-card-top{display:flex;align-items:center;justify-content:space-between;gap:.75rem}
/* 64px round icon — Fillow's own is 5.3125rem/85px inside a roomier 1.875rem card padding; scaled
   down slightly to fit this app's tighter card padding while keeping the same "big circle" language. */
.stat-icon{width:64px;height:64px;border-radius:50%;font-size:1.4rem;display:flex;align-items:center;justify-content:center;flex:none}
.stat-icon svg{width:28px;height:28px}
.stat-icon.brand{background:var(--brand-light);color:var(--brand-dark);--stat-accent:var(--brand)}
.stat-icon.accent{background:var(--accent-light);color:var(--accent);--stat-accent:var(--accent)}
.stat-icon.warn{background:var(--warn-light);color:var(--warn);--stat-accent:var(--warn)}
.stat-icon.info{background:var(--info-light);color:var(--info);--stat-accent:var(--info)}
.stat-icon.danger{background:var(--danger-light);color:var(--danger);--stat-accent:var(--danger)}
.stat-label{color:var(--muted);font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em}
.stat-value{font-size:2.1rem;font-weight:800;line-height:1.1;letter-spacing:-.03em}
.stat-sub{color:var(--muted);font-size:.8rem;margin-top:.1rem;display:flex;align-items:center;gap:.35rem}
.stat-trend{font-weight:700;padding:.1rem .45rem;border-radius:999px;font-size:.74rem}
.stat-trend.up{background:var(--brand-light);color:var(--brand-dark)}
.stat-trend.down{background:var(--danger-light);color:var(--danger)}

/* ---- Client Hub category filter cards ---- */
.hub-cat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:.75rem;padding:1.1rem}
.hub-cat-card{position:relative;display:flex;align-items:center;gap:.7rem;background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:.85rem 1rem;text-decoration:none;color:inherit;transition:border-color .15s ease,box-shadow .15s ease,transform .15s ease}
.hub-cat-card:hover{box-shadow:var(--shadow-hover);transform:translateY(-2px);color:inherit}
.hub-cat-card.active{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-light)}
.hub-cat-card.active::after{content:"";position:absolute;left:50%;bottom:-1px;transform:translateX(-50%);width:34px;height:3px;border-radius:3px 3px 0 0;background:var(--brand)}
.hub-cat-icon{position:relative;width:44px;height:44px;border-radius:13px;display:flex;align-items:center;justify-content:center;flex:none}
.hub-cat-icon .notif-dot{position:absolute;top:-4px;right:-4px;background:var(--danger);color:#fff;border-radius:999px;font-size:.62rem;font-weight:700;min-width:15px;height:15px;display:inline-flex;align-items:center;justify-content:center;padding:0 .25rem;border:2px solid var(--surface)}
.hub-cat-icon.brand{background:var(--brand-light);color:var(--brand-dark)}
.hub-cat-icon.accent{background:var(--accent-light);color:var(--accent)}
.hub-cat-icon.success{background:var(--success-light);color:var(--success)}
.hub-cat-icon.warn{background:var(--warn-light);color:var(--warn)}
.hub-cat-icon.info{background:var(--info-light);color:var(--info)}
.hub-cat-icon.danger{background:var(--danger-light);color:var(--danger)}
.hub-cat-icon.slate{background:var(--slate-light);color:var(--slate)}
.hub-cat-body{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.hub-cat-label{font-weight:700;font-size:.86rem;line-height:1.2}
.hub-cat-count{flex:none;min-width:26px;height:26px;padding:0 .4rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-weight:800;font-size:.78rem}
.hub-cat-count.brand{background:var(--brand-light);color:var(--brand-dark)}
.hub-cat-count.accent{background:var(--accent-light);color:var(--accent)}
.hub-cat-count.success{background:var(--success-light);color:var(--success)}
.hub-cat-count.warn{background:var(--warn-light);color:var(--warn)}
.hub-cat-count.info{background:var(--info-light);color:var(--info)}
.hub-cat-count.danger{background:var(--danger-light);color:var(--danger)}
.hub-cat-count.slate{background:var(--slate-light);color:var(--slate)}

/* ---- image attachment lightbox controls ---- */
.app-lightbox-close{position:absolute;top:-14px;right:-14px;width:38px;height:38px;border-radius:50%;background:#fff;color:var(--brand-dark);border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,.3);z-index:1}
.app-lightbox-close:hover{background:var(--brand-light)}
.app-lightbox-download{display:inline-flex;align-items:center;gap:.4rem;background:var(--brand);color:#fff;font-weight:700;font-size:.85rem;padding:.55rem 1.15rem;border-radius:999px;text-decoration:none;box-shadow:0 4px 14px rgba(0,0,0,.3)}
.app-lightbox-download:hover{background:var(--brand-dark);color:#fff}

/* ---- chart panels ---- */
.chart-card .card-body{padding:1.75rem}
/* Weight/size matches Fillow's actual .card-title (1.25rem/600) + .subtitle (.875rem) pairing. */
.chart-title{font-weight:600;font-size:1.25rem;margin-bottom:.2rem;letter-spacing:-.01em;text-transform:capitalize}
.chart-sub{color:var(--muted);font-size:.875rem;margin-bottom:1.35rem}
.chart-canvas-wrap{position:relative;height:280px}
.chart-canvas-wrap.sm{height:220px}
.chart-empty{display:flex;align-items:center;justify-content:center;height:100%;color:var(--muted);font-size:.85rem}

/* ApexCharts renders its tooltips as plain unstyled DOM (no explicit text color), so they were
   inheriting body{color:var(--text)} — invisible pale-on-pale in dark mode, since the tooltip's own
   background stays ApexCharts' default light gray regardless of theme. Force the same always-dark
   tooltip look already used for this app's Chart.js tooltips (see Chart.defaults.plugins.tooltip in
   each dashboard's <script>), so contrast holds in both themes instead of just matching light mode. */
.apexcharts-tooltip{background:#202020!important;border:none!important;color:rgba(255,255,255,.9)!important;border-radius:10px!important;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.3)!important}
.apexcharts-tooltip-title{background:#202020!important;color:#fff!important;font-weight:700;border-bottom:1px solid rgba(255,255,255,.15)!important;margin-bottom:0}
.apexcharts-tooltip-series-group,.apexcharts-tooltip-y-group{color:rgba(255,255,255,.9)!important}
.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-z-value{color:#fff!important}
.apexcharts-xaxistooltip{background:#202020!important;color:#fff!important;border:none!important}
.apexcharts-xaxistooltip:before{border-bottom-color:#202020!important}
.apexcharts-xaxistooltip:after{border-bottom-color:#202020!important}
.apexcharts-yaxistooltip{background:#202020!important;color:#fff!important;border:none!important}

/* ---- tables: a tinted header row + borderless body rows separated only by hover state reads as
   a considered data list rather than a spreadsheet. Cards that hold nothing but a table should
   wrap it in a .card-body (not bleed the table to the card's rounded edge) — see .data-card. ---- */
.table{--bs-table-bg:transparent;margin-bottom:0}
.data-card .card-body{padding:0}
/* Matches Fillow's actual .table thead th — plain, capitalize (not uppercase), normal-weight-ish
   dark text with just a bottom border, not an uppercase/tinted-background header row. */
.table thead th{background:transparent;font-size:1rem;text-transform:capitalize;letter-spacing:.02em;color:var(--text);font-weight:500;border-bottom:1px solid var(--border);padding:1rem 1.6rem;white-space:nowrap}
.table td{padding:1.05rem 1.6rem;vertical-align:middle;border-top:1px solid var(--border);border-bottom:none}
.table tbody tr:first-child td{border-top:none}
.table-hover tbody tr{transition:background .12s ease}
.table-hover tbody tr:hover{background:#f3f5f8}
.table-sm td,.table-sm th{padding-left:1rem;padding-right:1rem}

/* ---- badges ---- */
.badge-soft{display:inline-flex;align-items:center;gap:.4rem;padding:.35rem .7rem;border-radius:999px;font-size:.73rem;font-weight:700;white-space:nowrap}
.badge-soft::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.7}
.badge-soft.brand{background:var(--brand-light);color:var(--brand-dark)}
.badge-soft.warn{background:var(--warn-light);color:var(--warn)}
.badge-soft.danger{background:var(--danger-light);color:var(--danger)}
.badge-soft.info{background:var(--info-light);color:var(--info)}
.badge-soft.muted{background:#eef0f4;color:var(--muted)}
.badge-soft.muted::before{display:none}

/* ---- solid status pill (orders tables): Fillow's actual .badge-success/.badge-primary/
   .badge-warning/.badge-secondary — solid fill + white text + trailing icon, not the soft-tint
   .badge-soft used elsewhere. Colors match style.css's literal values (#09BD3C/#FFBF00/#FFA7D7). ---- */
.badge-status{display:inline-flex;align-items:center;gap:.35rem;padding:.35rem .8rem;border-radius:999px;font-size:.78rem;font-weight:700;color:#fff;white-space:nowrap}
.badge-status.success{background:var(--success)}
.badge-status.brand{background:var(--brand)}
.badge-status.warn{background:#FFBF00}
.badge-status.pink{background:#FFA7D7}

/* ---- table row action button ("sharp"): Fillow's .btn.light.btn-{status}.sharp — a small
   rounded-square icon button tinted to match the row's own status, not one flat neutral button for
   every row regardless of state. Values pulled from style.css's .light.btn-* rules directly. ---- */
.table-action-btn{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border:none;border-radius:var(--radius);cursor:pointer;transition:background-color .15s ease,color .15s ease}
.table-action-btn.success{background:#d7fde2;color:var(--success)}
.table-action-btn.success:hover,.table-action-btn.success.show{background:var(--success);color:#fff}
.table-action-btn.warn{background:var(--warn-light);color:var(--warn)}
.table-action-btn.warn:hover,.table-action-btn.warn.show{background:var(--warn);color:#fff}
.table-action-btn.danger{background:var(--danger-light);color:var(--danger)}
.table-action-btn.danger:hover,.table-action-btn.danger.show{background:var(--danger);color:#fff}
.table-action-btn.brand{background:var(--brand-light);color:var(--brand-dark)}
.table-action-btn.brand:hover,.table-action-btn.brand.show{background:var(--brand);color:#fff}
.table-action-btn.muted{background:#eef0f4;color:var(--muted)}
.table-action-btn.muted:hover,.table-action-btn.muted.show{background:var(--muted);color:#fff}

/* ---- buttons ---- */
/* Fillow's actual button shape: 0.625rem rounded-rect (var(--radius)), not a full pill — was 999px. */
.btn{border-radius:var(--radius);font-weight:700;letter-spacing:-.008em;white-space:nowrap;padding:.55rem 1.15rem;transition:background .15s ease,border-color .15s ease,box-shadow .15s ease,transform .15s ease}
.btn-sm{padding:.4rem .9rem}
.btn-success{background:var(--brand);border-color:var(--brand);box-shadow:0 2px 10px -2px rgba(136,108,192,.45)}
.btn-success:hover{background:var(--brand-dark);border-color:var(--brand-dark);box-shadow:0 4px 16px -2px rgba(136,108,192,.5);transform:translateY(-1px)}
.btn-outline-success{color:var(--brand-dark);border-color:var(--brand)}
.btn-outline-success:hover{background:var(--brand);border-color:var(--brand)}
.btn-outline-secondary{border-color:var(--border);color:var(--text)}
.btn-outline-secondary:hover{background:var(--text);border-color:var(--text);color:#fff}
/* .btn-warning/.btn-danger/.btn-info — Bootstrap's compiled CDN button classes bake in literal stock
   hex values at build time (not a live var(--bs-warning) reference), so overriding the root token
   alone doesn't retint them — same reason .btn-success above needs its own explicit override rather
   than relying on inheritance. (.btn-success itself is this app's existing "primary action" button,
   intentionally mapped to --brand, not literal semantic green — left untouched.) */
.btn-warning{--bs-btn-bg:var(--warn);--bs-btn-border-color:var(--warn);--bs-btn-color:#fff;--bs-btn-hover-bg:#8a5900;--bs-btn-hover-border-color:#8a5900;--bs-btn-hover-color:#fff;--bs-btn-active-bg:#8a5900;--bs-btn-active-border-color:#8a5900;--bs-btn-active-color:#fff}
.btn-outline-warning{--bs-btn-color:var(--warn);--bs-btn-border-color:var(--warn);--bs-btn-hover-bg:var(--warn);--bs-btn-hover-border-color:var(--warn);--bs-btn-hover-color:#fff;--bs-btn-active-bg:var(--warn);--bs-btn-active-border-color:var(--warn)}
.btn-danger{--bs-btn-bg:var(--danger);--bs-btn-border-color:var(--danger);--bs-btn-hover-bg:#a01530;--bs-btn-hover-border-color:#a01530;--bs-btn-active-bg:#a01530;--bs-btn-active-border-color:#a01530}
.btn-outline-danger{--bs-btn-color:var(--danger);--bs-btn-border-color:var(--danger);--bs-btn-hover-bg:var(--danger);--bs-btn-hover-border-color:var(--danger);--bs-btn-active-bg:var(--danger);--bs-btn-active-border-color:var(--danger)}
.btn-info{--bs-btn-bg:var(--info);--bs-btn-border-color:var(--info);--bs-btn-color:#fff;--bs-btn-hover-bg:#7d2571;--bs-btn-hover-border-color:#7d2571;--bs-btn-hover-color:#fff;--bs-btn-active-bg:#7d2571;--bs-btn-active-border-color:#7d2571;--bs-btn-active-color:#fff}
.btn-outline-info{--bs-btn-color:var(--info);--bs-btn-border-color:var(--info);--bs-btn-hover-bg:var(--info);--bs-btn-hover-border-color:var(--info);--bs-btn-hover-color:#fff;--bs-btn-active-bg:var(--info);--bs-btn-active-border-color:var(--info)}
/* .alert-* — same "compiled classes bake in literal colors" issue as buttons above. */
.alert-warning{--bs-alert-color:var(--warn);--bs-alert-bg:var(--warn-light);--bs-alert-border-color:var(--warn-light)}
.alert-danger{--bs-alert-color:var(--danger);--bs-alert-bg:var(--danger-light);--bs-alert-border-color:var(--danger-light)}
.alert-info{--bs-alert-color:var(--info);--bs-alert-bg:var(--info-light);--bs-alert-border-color:var(--info-light)}
.alert-success{--bs-alert-color:var(--success);--bs-alert-bg:var(--success-light);--bs-alert-border-color:var(--success-light)}

/* ---- floating action button ---- */
.btn-float{position:fixed;bottom:1.5rem;right:1.5rem;z-index:1035;box-shadow:0 6px 20px rgba(20,24,40,.22);padding:.7rem 1.5rem}

/* ---- auth (login) screens ---- */
.auth-body{background:var(--bg)}
.auth-shell{min-height:100vh;display:flex}
.auth-hero{display:none;flex:1;background:linear-gradient(135deg,var(--auth-hero-1,#2d2440),var(--auth-hero-2,#1f1a2e) 55%,var(--auth-hero-3,#241f35));color:#fff;align-items:center;justify-content:center;padding:3rem;position:relative;overflow:hidden}
.auth-hero::before{content:"";position:absolute;width:520px;height:520px;border-radius:50%;background:radial-gradient(circle,rgba(var(--bs-primary-rgb,136,108,192),.22),transparent 70%);top:-140px;right:-160px}
.auth-hero::after{content:"";position:absolute;width:380px;height:380px;border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.08),transparent 70%);bottom:-140px;left:-110px}
.auth-hero-inner{position:relative;max-width:420px}
.auth-hero-logo{max-height:44px;margin-bottom:2.25rem}
.auth-hero-brand{display:flex;align-items:center;gap:.5rem;font-weight:800;font-size:1.2rem;margin-bottom:2.25rem}
.auth-hero-brand .dot{width:10px;height:10px;border-radius:50%;background:#a590cf;box-shadow:0 0 0 4px rgba(165,144,207,.3)}
.auth-hero h1{font-size:2.1rem;margin-bottom:.75rem}
.auth-hero p{color:rgba(255,255,255,.78);font-size:1.03rem;line-height:1.55;margin-bottom:0}
.auth-panel{flex:1;display:flex;align-items:center;justify-content:center;padding:2rem}
.auth-card{width:100%;max-width:380px}
.auth-card-logo{max-height:40px;margin-bottom:1.75rem}
.auth-card h2{font-size:1.5rem;margin-bottom:.25rem}
.auth-sub{color:var(--muted);margin-bottom:1.75rem}
.auth-alert{background:var(--danger-light);color:var(--danger);padding:.75rem 1rem;border-radius:var(--radius-sm);font-size:.88rem;margin-bottom:1.25rem}
.auth-alert-success{background:var(--brand-light);color:var(--brand-dark)}
.auth-form label{display:block;font-weight:600;font-size:.85rem;margin-bottom:1.15rem;color:var(--text)}
.auth-form input{display:block;width:100%;margin-top:.4rem;padding:.7rem .9rem;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:.95rem;font-family:inherit;background:#fff;transition:border-color .15s ease,box-shadow .15s ease}
.auth-form input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-light)}
.auth-submit{display:block;width:100%;background:var(--brand);color:#fff;border:none;border-radius:999px;padding:.8rem;font-weight:700;font-size:.98rem;cursor:pointer;transition:background .15s ease}
.auth-submit:hover{background:var(--brand-dark)}
@media (min-width:992px){.auth-hero{display:flex}}

/* ---- page shell ---- */
main.container,main.container-fluid{max-width:1360px;padding-top:2.25rem!important;padding-bottom:3rem!important;padding-left:10px!important;padding-right:10px!important}
/* Fillow's actual .page-titles is a white card (padded/rounded/shadowed) with the title colored in
   brand purple, not plain text sitting on the page background — kept this app's larger two-line
   title+subtitle proportions (Fillow's own is a compact one-liner) since most pages here carry a
   real descriptive subtitle, but adopted the card treatment and purple title, both real Fillow traits. */
.page-head{margin-bottom:1.875rem;background:var(--surface);border-radius:var(--radius);box-shadow:var(--shadow);padding:1.25rem 1.5rem;display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.page-head h1{font-size:1.6rem;margin-bottom:.3rem;letter-spacing:-.025em;color:var(--brand-dark)}
.page-head p{color:var(--muted);margin-bottom:0;font-size:.95rem}
.page-head-actions{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
/* A page with only actions (its title moved up into the header bar by the shared nav script) loses
   the card treatment entirely — it's just a slim actions row, not an empty white box. */
.page-head.page-head-actions-only{background:transparent;box-shadow:none;padding:0;justify-content:flex-end}

/* ---- header-bar page title: Fillow's actual .dashboard_bar sits directly in the same sticky row
   as the header icons, not in a separate card below — moved here by the shared nav script instead
   of a per-page rewrite, since .page-head's h1/p is already consistent everywhere. ---- */
.app-header-title-main{font-size:1.35rem;font-weight:700;color:var(--text);line-height:1.2}
.app-header-title-sub{font-size:.85rem;color:var(--muted)}

/* ---- action bar: for headers with several possible actions — 1-2 stay as visible buttons,
   the rest collapse into a "More" dropdown so every action isn't given equal visual weight ---- */
.action-bar{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.action-bar .dropdown-toggle::after{margin-left:.5rem}
.action-bar .dropdown-menu{border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-hover);padding:.4rem}
.action-bar .dropdown-item{border-radius:8px;padding:.5rem .75rem;font-size:.9rem;font-weight:500}
.action-bar .dropdown-item:hover{background:var(--brand-light);color:var(--brand-dark)}
.action-bar .dropdown-item.text-danger:hover{background:var(--danger-light);color:var(--danger)}

/* ---- empty states: replaces a bare line of muted text wherever a list/table can be empty ---- */
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:3rem 1.5rem}
.empty-state-icon{width:56px;height:56px;border-radius:50%;background:var(--brand-light);color:var(--brand-dark);display:flex;align-items:center;justify-content:center;margin-bottom:1.1rem}
.empty-state h3{font-size:1.05rem;margin-bottom:.35rem}
.empty-state p{color:var(--muted);font-size:.9rem;max-width:360px;margin-bottom:0}
.empty-state .btn{margin-top:1.25rem}

/* ---- avatars: for the first column of people-tables (customers, affiliates, orders) ---- */
.avatar{width:38px;height:38px;border-radius:50%;background:var(--brand-light);color:var(--brand-dark);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:.85rem;flex:none}
.avatar-sm{width:30px;height:30px;font-size:.72rem}
.avatar.brand{background:var(--brand);color:#fff}
.name-cell{display:flex;align-items:center;gap:.7rem}

/* ---- refined form fields: consistent focus ring + calmer borders everywhere ---- */
.form-control,.form-select{border-color:var(--border);border-radius:var(--radius)}
.form-control:focus,.form-select:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-light)}
.form-check-input:checked{background-color:var(--brand);border-color:var(--brand)}
.form-check-input:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-light)}

/* ---- search pill: Fillow's actual header .search-area — fully rounded input-group with the icon
   segment in its own rounded pill on the trailing edge, height ~3rem, light border. Reused here for
   table filter bars' search field instead of a plain square input. ---- */
.search-pill{border-radius:999px;overflow:visible}
.search-pill .form-control{height:3rem;border-radius:999px 0 0 999px;border-right:0}
.search-pill .form-control:focus{box-shadow:none}
.search-pill .input-group-text{height:3rem;border-radius:999px;background:#fff;border-color:var(--border);padding:0 1.1rem;margin-left:-1px}
.form-switch{padding-left:2.75em}
.form-switch .form-check-input{width:2.75em;height:1.5em;margin-top:0;margin-right:.6rem;background-color:#e4e6ec;border:none;box-shadow:inset 0 1px 2px rgba(20,24,40,.10);cursor:pointer;transition:background-color .18s ease,box-shadow .18s ease}
.form-switch .form-check-input:hover{background-color:#d7dae2}
.form-switch .form-check-input:checked{background-color:var(--brand);box-shadow:0 3px 10px -2px rgba(136,108,192,.5)}
.form-switch .form-check-input:checked:hover{background-color:var(--brand-dark)}
.form-switch .form-check-input:focus{box-shadow:inset 0 1px 2px rgba(20,24,40,.10),0 0 0 3px var(--brand-light)}
.form-switch .form-check-label{cursor:pointer;padding-top:.15em}

/* ---- category sidebar (nav-pills, used only by the products-by-category picker) — black text,
   never Bootstrap's default blue, and the active pill is brand green, not Bootstrap's default blue ---- */
.nav-pills .nav-link{color:var(--text)}
.nav-pills .nav-link:hover{color:var(--text);background-color:var(--bg)}
.nav-pills .nav-link.active{background-color:var(--brand);color:#fff}

/* ---- lavender-track pill group for the Project Statistics-style widget's period tabs ---- */
.project-stats-tabs{background:var(--brand-light);border-radius:999px;padding:.25rem;gap:0;margin:0}
.project-stats-tabs .nav-link{border:none;border-radius:999px;color:var(--brand-dark);font-weight:600;font-size:.85rem;padding:.4rem .9rem;background:transparent}
.project-stats-tabs .nav-link.active{background:var(--brand);color:#fff}

/* ---- inline data-grid inputs: for fields embedded directly in a table row (pricing grids,
   variation editors) — calmer than a full bordered form-control so the row reads as a refined
   grid instead of a raw form dropped into a table ---- */
.table input.form-control-plain,.table textarea.form-control-plain{border:1px solid transparent;background:transparent;padding:.4rem .55rem;border-radius:8px;transition:border-color .15s ease,background .15s ease}
.table input.form-control-plain:hover,.table textarea.form-control-plain:hover{background:var(--bg)}
.table input.form-control-plain:focus,.table textarea.form-control-plain:focus{background:#fff;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-light);outline:none}

/* ---- pill-style tabs, matching the badge/button rounded language used everywhere else ---- */
.nav-tabs{border-bottom:1px solid var(--border);gap:.35rem;flex-wrap:wrap}
.nav-tabs .nav-link{border:none;border-radius:999px;color:var(--muted);font-weight:600;font-size:.88rem;padding:.5rem 1rem}
.nav-tabs .nav-link:hover{background:var(--bg);color:var(--text)}
.nav-tabs .nav-link.active{background:var(--brand-light);color:var(--brand-dark)}

/* ---- image thumbnails: bordered, rounded frame for product/asset images in tables ---- */
.thumb{border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px;background:#fff;display:inline-block;line-height:0}
.thumb img{display:block;border-radius:6px;object-fit:contain}

/* ---- Client Hub / Support Center: two-panel messaging shell shared by admin and client ---- */
.hub-shell{display:flex;gap:1.25rem;align-items:flex-start}
.hub-sidebar{width:320px;flex:none;background:#fff;border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden;display:flex;flex-direction:column;max-height:calc(100vh - 140px)}
.hub-sidebar-search{padding:.9rem;border-bottom:1px solid var(--border)}
.hub-announce-btn{display:flex;align-items:center;gap:.5rem;margin:.9rem .9rem 0;padding:.65rem .9rem;border-radius:var(--radius-sm);background:var(--brand-light);color:var(--brand-dark);font-weight:700;text-decoration:none;font-size:.88rem}
.hub-announce-btn:hover{background:var(--brand);color:#fff}
.hub-client-list{overflow-y:auto;flex:1 1 auto}
.hub-client-item{display:flex;gap:.7rem;align-items:flex-start;padding:.85rem .9rem;border-bottom:1px solid var(--border);text-decoration:none;color:inherit;transition:background .12s ease}
.hub-client-item:hover{background:var(--bg)}
.hub-client-item.active{background:var(--brand-light)}
.hub-client-item .name{font-weight:700;font-size:.9rem;color:var(--text)}
.hub-client-item .preview{font-size:.8rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:190px}
.hub-client-item .meta{font-size:.72rem;color:var(--muted);margin-top:.15rem}
.hub-client-item .unread-dot{margin-left:auto;background:var(--danger);color:#fff;border-radius:999px;font-size:.68rem;font-weight:700;min-width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;padding:0 .4rem;flex:none}
.hub-panel{flex:1 1 auto;min-width:0;background:#fff;border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow);min-height:calc(100vh - 140px);display:flex;flex-direction:column}

.chat-thread{flex:1 1 auto;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:1rem;max-height:calc(100vh - 340px)}
.chat-date-sep{text-align:center;color:var(--muted);font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin:.5rem 0}
.chat-bubble{max-width:72%;padding:.75rem 1rem;border-radius:16px;font-size:.9rem;line-height:1.45}
.chat-bubble.from-admin{align-self:flex-end;background:var(--brand);color:#fff;border-bottom-right-radius:4px}
.chat-bubble.from-client{align-self:flex-start;background:var(--bg);color:var(--text);border-bottom-left-radius:4px}
.chat-bubble .meta{font-size:.72rem;opacity:.75;margin-top:.35rem}
.chat-bubble .attachments{margin-top:.5rem;display:flex;flex-direction:column;gap:.3rem}
.chat-bubble .attachments a{color:inherit;text-decoration:underline;font-size:.82rem}
.chat-composer{border-top:1px solid var(--border);padding:1rem 1.5rem}
.chat-empty{flex:1 1 auto;display:flex;align-items:center;justify-content:center;color:var(--muted);font-size:.9rem}

/* A fixed 320px sidebar next to a flexible panel doesn't fit a narrow viewport (now further
   narrowed by the app's own 250px sidebar) — stacks vertically instead of overflowing sideways. */
@media (max-width:1100px){
  .hub-shell{flex-direction:column}
  .hub-sidebar{width:100%;max-height:280px}
  .hub-panel{min-height:60vh}
}

/* ==================================================================================================
   DARK MODE — toggled by adding data-theme="dark" to <html> (persisted in localStorage, applied
   synchronously before paint by the nav's own inline script, same flash-prevention pattern already
   used for the sidebar-collapsed state). Almost every surface/text/border color in this file already
   reads off the --bg/--surface/--border/--text/--muted/etc. variables below, so redefining them here
   re-themes most of the app for free; the rest of this section is the handful of places that use a
   hardcoded color (Bootstrap's own defaults, or a literal #fff) instead of one of those variables.
   The sidebar/header gradients are already dark in both themes and are deliberately left alone. ---- */
:root[data-theme="dark"]{
  /* --muted is deliberately pure white here, not a dimmed grey — every "secondary/helper text"
     class in this file (.stat-sub, .chart-sub, .page-head p, .empty-state p, table headers, and
     Bootstrap's own .text-secondary/.text-muted via --bs-secondary-color below) reads off this one
     variable, so this single change makes every subtext/helper-text string pure white in dark mode
     without needing a per-class override. Sacrifices the usual visual hierarchy between primary and
     secondary text on purpose — readability was explicitly asked for over subtlety here. */
  /* Fillow's own real dark palette (extracted from its compiled [data-theme-version="dark"] block:
     bg #161717, card #202020, border #2B2B2B) — not an approximation. */
  --bg:#161717; --surface:#202020; --border:#2b2b2b; --text:#f1f2f5; --muted:#ffffff;
  /* --brand stays the same rich, saturated purple as light mode — it's the solid fill color for
     buttons/active-pills (paired with white text on top), and needs to stay strong regardless of
     theme. --brand-dark switches role here: in light mode it's a darker purple for text sitting on
     a white/tinted background; in dark mode that same "must contrast with the surrounding surface"
     job needs a LIGHTER purple instead (used for links, badge/icon text sitting on --brand-light's
     now-dark tint, page-link text, etc.) — reusing the light-mode value here made buttons go pale
     with low-contrast text, since both --brand and --brand-dark ended up light at the same time. */
  --brand:#886cc0; --brand-dark:#c3b1e6; --brand-light:#332a4d;
  /* Same Fillow secondary-pink family as light mode's --accent, lightened for dark-surface contrast
     the same way --brand-dark is (see comment above). */
  --accent:#f296c8; --accent-light:#3d2233;
  /* Same Fillow semantic hue families as light mode, lightened for dark-surface contrast (same
     pattern as --brand-dark above) — info is Fillow's magenta, not the previous teal. */
  --warn:#ffce3d; --warn-light:#3a2e10;
  --danger:#ff6b85; --danger-light:#3d1e1f;
  --info:#e685da; --info-light:#3d1e39;
  --success:#4fdb72; --success-light:#123420;
  --slate:#9aa1b0; --slate-light:#242832;
  --shadow:0 1px 2px rgba(0,0,0,.45),0 14px 32px -18px rgba(0,0,0,.65);
  --shadow-hover:0 6px 16px rgba(0,0,0,.55),0 28px 56px -24px rgba(0,0,0,.75);
  --bs-primary-bg-subtle:#332a4d; --bs-primary-text-emphasis:#c3b1e6; --bs-primary-border-subtle:#a590cf;
  /* Bootstrap's own core tokens — tables, list-groups, and the .bg-light utility read these
     directly instead of our own --text/--bg/--border, so redefining only our own app variables
     above silently left those components stuck in light-mode colors. This is what was causing
     dark-on-dark unreadable table text (Bootstrap's .table sets color from --bs-body-color, not
     --text) and a page background that refused to go black (.bg-light's background-color is
     !important and driven by --bs-light-rgb, which was never touched before). */
  --bs-body-color:var(--text); --bs-body-color-rgb:241,242,245;
  --bs-body-bg:var(--bg); --bs-body-bg-rgb:15,17,23;
  --bs-emphasis-color:var(--text); --bs-emphasis-color-rgb:241,242,245;
  --bs-secondary-color:var(--muted); --bs-secondary-color-rgb:154,161,176;
  --bs-secondary-bg:var(--surface); --bs-secondary-bg-rgb:26,29,38;
  --bs-tertiary-color:var(--muted); --bs-tertiary-bg:var(--surface);
  --bs-border-color:var(--border); --bs-border-color-translucent:var(--border);
  --bs-light:var(--surface); --bs-light-rgb:26,29,38;
  --bs-dark:var(--text); --bs-dark-rgb:241,242,245;
  --bs-heading-color:var(--text);
  color-scheme:dark;
}
[data-theme="dark"] .table{color:var(--text)}
/* .bg-white is a hardcoded literal-white Bootstrap utility (not driven by any --bs-* variable,
   unlike .bg-light) — used as a whole-form-card background on a few pages (new client, new
   announcement, new support ticket). Needs its own !important override to beat Bootstrap's own. */
[data-theme="dark"] .bg-white{background-color:var(--surface)!important}
/* The Quill rich-text editor (announcement message body) hardcodes background:#fff inline on
   #editor, which no class-based override can beat without !important — left alone, dark mode's
   global white text then sits on that same still-white background, invisible. Also covers the
   toolbar/border, which Quill's own quill.snow.css otherwise renders light-themed unconditionally. */
[data-theme="dark"] #editor{background:var(--surface)!important;color:var(--text)}
[data-theme="dark"] .ql-toolbar.ql-snow{background:var(--surface);border-color:var(--border)}
[data-theme="dark"] .ql-toolbar.ql-snow .ql-stroke{stroke:var(--text)}
[data-theme="dark"] .ql-toolbar.ql-snow .ql-fill{fill:var(--text)}
[data-theme="dark"] .ql-toolbar.ql-snow .ql-picker-label{color:var(--text)}
[data-theme="dark"] .ql-toolbar.ql-snow .ql-picker-options{background:var(--surface);color:var(--text)}
[data-theme="dark"] .ql-container.ql-snow{border-color:var(--border)}
[data-theme="dark"] .ql-editor.ql-blank::before{color:var(--muted)}
/* .btn-success:hover normally darkens via --brand-dark, but that variable now means "light purple
   for text on a dark surface" (see the root override above) — reusing it here would make the
   button paler on hover with the same low-contrast white-text problem this whole fix started from.
   Darken instead, same direction as the original light-mode hover. */
[data-theme="dark"] .btn-success:hover{background:color-mix(in srgb, var(--brand) 75%, black);border-color:color-mix(in srgb, var(--brand) 75%, black)}
[data-theme="dark"] body.bg-light{background:radial-gradient(1100px 550px at 100% -8%,rgba(136,108,192,.10),transparent),var(--bg)}
[data-theme="dark"] .card{background:var(--surface)}
[data-theme="dark"] .thumb{background:var(--surface)}
[data-theme="dark"] .hub-sidebar,[data-theme="dark"] .hub-panel{background:var(--surface)}
[data-theme="dark"] .table-hover tbody tr:hover{background:rgba(255,255,255,.045)}
[data-theme="dark"] .badge-soft.muted{background:#262a34;color:var(--muted)}
[data-theme="dark"] .chat-bubble.from-client{background:#242833}
[data-theme="dark"] .form-control,[data-theme="dark"] .form-select{background:var(--surface);color:var(--text);border-color:var(--border)}
[data-theme="dark"] .form-control::placeholder{color:var(--muted);opacity:1}
[data-theme="dark"] .form-control:disabled,[data-theme="dark"] .form-select:disabled,[data-theme="dark"] .form-control[readonly]{background:#15171e;color:var(--muted)}
[data-theme="dark"] .form-control:focus,[data-theme="dark"] .form-select:focus{background:var(--surface);color:var(--text)}
[data-theme="dark"] .input-group-text{background:var(--bg);border-color:var(--border);color:var(--muted)}
/* :not(:checked) is deliberate, not decorative — without it this has the exact same specificity as
   the light-mode :checked rule above (attribute+2 classes vs. 3 classes) and, being later in the
   file, would win and paint every ON toggle the same dark grey as the OFF state instead of purple. */
/* The light-mode version relies on an inset dark shadow for depth (rgba(20,24,40,.10)) — that shadow
   does nothing against an already-dark page, and the previous fill color was too close in luminance
   to the surrounding card/page background, so the OFF track all but disappeared. Lighter fill plus a
   faint light ring (standing in for the now-useless dark inset shadow) keeps it clearly visible
   against any dark surface it sits on. */
[data-theme="dark"] .form-switch .form-check-input:not(:checked){background-color:#4b5163;box-shadow:0 0 0 1px rgba(255,255,255,.10)}
[data-theme="dark"] .form-switch .form-check-input:not(:checked):hover{background-color:#5a6178;box-shadow:0 0 0 1px rgba(255,255,255,.16)}
/* :not(:checked), same reasoning as the form-switch rule above — otherwise this has equal
   specificity to the light-mode .form-check-input:checked rule and, being later, would win and
   paint every checked checkbox the same dark surface color as unchecked instead of purple. */
/* border-color:var(--border) alone was too close to the card's own --surface background (the
   checkbox sits directly on a card, so a 1px border barely darker than that same background nearly
   disappeared) — same fix as the toggle switch above: a visibly lighter border. */
[data-theme="dark"] .form-check-input:not(:checked){background-color:var(--surface);border-color:#4b5163}
[data-theme="dark"] .auth-form input{background:var(--surface);color:var(--text);border-color:var(--border)}
[data-theme="dark"] .dropdown-menu{background:var(--surface);border-color:var(--border);color:var(--text);box-shadow:var(--shadow-hover)}
[data-theme="dark"] .dropdown-item{color:var(--text)}
[data-theme="dark"] .dropdown-item:hover,[data-theme="dark"] .dropdown-item:focus{background:rgba(255,255,255,.06);color:var(--text)}
[data-theme="dark"] .dropdown-item.text-danger:hover{background:var(--danger-light)}
[data-theme="dark"] .modal-content{background:var(--surface);color:var(--text)}
[data-theme="dark"] .modal-header,[data-theme="dark"] .modal-footer{border-color:var(--border)}
/* Fillow's actual modal radius (0.625rem, same scale as cards/buttons/forms) — applies app-wide to
   every Bootstrap modal (confirm dialogs, the client-signup embed-code modal, package pricing, etc). */
.modal-content{border-radius:var(--radius)}
[data-theme="dark"] .btn-close{filter:invert(1) grayscale(1) brightness(1.6)}
[data-theme="dark"] .accordion-item{background:var(--surface);border-color:var(--border);color:var(--text)}
/* .collapsed, not the bare class — otherwise this has equal specificity to the light-mode
   :not(.collapsed) expanded-state rule above and, being later, would win and strip the expanded
   accordion section's brand-tinted highlight in dark mode. */
[data-theme="dark"] .accordion-button.collapsed{background:var(--surface);color:var(--text)}
[data-theme="dark"] .accordion-button::after{filter:invert(1) grayscale(1) brightness(1.8)}
[data-theme="dark"] .text-secondary,[data-theme="dark"] .text-muted{color:var(--muted)!important}
[data-theme="dark"] .text-dark,[data-theme="dark"] .text-body{color:var(--text)!important}
/* :not(.btn) is deliberate — without it this beats Bootstrap's own .btn{color:var(--bs-btn-color)}
   rule on specificity (attribute+element vs. a bare class) for any button styled as an <a> tag
   (e.g. <a class="btn btn-success">), overriding its intended solid white text with this light
   purple link color instead — on a purple button that reads as faded/low-contrast text. Buttons
   keep whatever color their own variant class (.btn-success, .btn-outline-secondary, etc.) gives
   them; only plain text links get this treatment. */
[data-theme="dark"] a:not(.btn){color:var(--brand-dark)}
[data-theme="dark"] .btn-link{color:var(--brand-dark)}
[data-theme="dark"] .btn-outline-secondary{border-color:var(--border);color:var(--text)}
[data-theme="dark"] .btn-outline-secondary:hover{background:var(--text);border-color:var(--text);color:var(--bg)}
[data-theme="dark"] .page-item.disabled .page-link{background:var(--surface);color:var(--muted);border-color:var(--border)}
/* :not(.active) on both — otherwise these have equal specificity to the light-mode .active rules
   above and, being later, would win, stripping an active pill/tab's brand highlight on hover. */
[data-theme="dark"] .nav-pills .nav-link:hover:not(.active){background-color:var(--bg)}
[data-theme="dark"] .nav-tabs .nav-link:hover:not(.active){background:var(--bg)}
[data-theme="dark"] .table input.form-control-plain:hover,[data-theme="dark"] .table textarea.form-control-plain:hover{background:var(--bg)}
[data-theme="dark"] .table input.form-control-plain:focus,[data-theme="dark"] .table textarea.form-control-plain:focus{background:var(--surface)}
[data-theme="dark"] .alert-success{background:var(--success-light);color:var(--success);border-color:transparent}
[data-theme="dark"] .alert-danger{background:var(--danger-light);color:var(--danger);border-color:transparent}
[data-theme="dark"] .alert-warning{background:var(--warn-light);color:var(--warn);border-color:transparent}
[data-theme="dark"] .alert-info{background:var(--info-light);color:var(--info);border-color:transparent}
[data-theme="dark"] .badge-soft.warn{color:var(--warn)}
[data-theme="dark"] .badge-soft.danger{color:var(--danger)}
[data-theme="dark"] .stat-trend.down{color:var(--danger)}
[data-theme="dark"] .auth-alert{color:var(--danger)}
[data-theme="dark"] .progress{background-color:#262a34}
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator{filter:invert(1) brightness(1.6)}
[data-theme="dark"] .auth-hero::before{background:radial-gradient(circle,rgba(var(--bs-primary-rgb,136,108,192),.22),transparent 70%)}

/* ---- theme toggle button — sun/moon swap driven purely by CSS off the [data-theme] attribute, no
   JS re-render needed on click beyond flipping the attribute itself. ---- */
.theme-toggle-btn .icon-moon{display:none}
[data-theme="dark"] .theme-toggle-btn .icon-sun{display:none}
[data-theme="dark"] .theme-toggle-btn .icon-moon{display:block}
