/* ============================================================
   QuickPledge Capital Limited — Shared App Styles
   Same brand system as the marketing site: ledger/paper aesthetic
   ============================================================ */

:root {
  --paper: #f6f1e6;
  --paper-2: #efe8d6;
  --ink: #16321f;
  --ink-soft: #3d4f42;
  --green-deep: #0d4d24;
  --green: #1b7a3d;
  --gold: #a97a20;
  --gold-soft: #c9932e;
  --rule: #cdbf9c;
  --white: #fffdf8;
  --danger: #8a2e21;
  --radius: 14px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Inter', -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .display {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600;
  color: var(--green-deep);
  margin: 0;
}

.mono { font-family: 'IBM Plex Mono', monospace; }

a { color: var(--green-deep); }

.wrap {
  max-width: 480px;
  margin: 0 auto;
  padding: 0 20px;
}

.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--rule);
  background: rgba(246, 241, 230, 0.95);
}

.app-header .brand-block { display: flex; align-items: center; gap: 10px; }

.app-header .logout-link {
  font-size: 13px; font-weight: 600; color: var(--ink-soft);
  text-decoration: none; font-family: 'Inter', sans-serif;
}
.app-header .logout-link:hover { color: var(--danger); }

.nav-tabs {
  display: flex; background: var(--white); border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 10;
}
.nav-tabs a {
  flex: 1; text-align: center; padding: 13px 6px; font-size: 13px; font-weight: 600;
  color: var(--ink-soft); text-decoration: none; border-bottom: 3px solid transparent;
  font-family: 'Inter', sans-serif;
}
.nav-tabs a.active { color: var(--green-deep); border-bottom-color: var(--green-deep); }
.nav-tabs a:hover { color: var(--green-deep); }

/* QuickPledge logo tile (Oct 2026) - admin sidebar, staff login, start page */
.seal {
  width: 34px; height: 34px; border-radius: 9px; padding: 4px;
  background: #fff; border: 1px solid var(--line, #E2E8E4);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; text-decoration: none; box-shadow: 0 1px 3px rgba(0,0,0,.12);
}
.seal img { width: 100%; height: 100%; object-fit: contain; display: block; }
a.seal:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 2px; }

.app-header .brand-name {
  font-family: 'Fraunces', serif; font-weight: 600; font-size: 16px; color: var(--green-deep);
}

.card {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 28px 24px;
  margin-top: 24px;
}

.card h2 { font-size: 22px; margin-bottom: 6px; }
.card .subtitle { color: var(--ink-soft); font-size: 14px; margin-bottom: 22px; }

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field label { font-size: 13px; font-weight: 600; color: var(--green-deep); }
.field input, .field select {
  font-family: 'Inter', sans-serif; font-size: 15px; color: var(--ink);
  padding: 12px 14px; border: 1px solid var(--rule); border-radius: 8px;
  background: var(--paper); outline: none; width: 100%;
}
.field input:focus, .field select:focus { border-color: var(--green); background: var(--white); }
.field .hint { font-size: 12px; color: var(--ink-soft); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 24px; border-radius: 9px; font-weight: 600; font-size: 15px;
  text-decoration: none; border: none; cursor: pointer; width: 100%;
  font-family: 'Inter', sans-serif;
}
.btn-primary { background: var(--green-deep); color: var(--white); }
.btn-primary:hover { background: var(--green); }
.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-ghost { background: transparent; color: var(--green-deep); border: 1px solid var(--green-deep); }

.status-msg {
  text-align: center; font-size: 13.5px; font-weight: 600; margin-top: 14px; min-height: 18px;
}
.status-msg.error { color: var(--danger); }
.status-msg.success { color: var(--green-deep); }
.status-msg.info { color: var(--ink-soft); }

.footer-link { text-align: center; margin-top: 18px; font-size: 13.5px; color: var(--ink-soft); }
.footer-link a { font-weight: 600; }

.badge {
  display: inline-block; font-family: 'IBM Plex Mono', monospace; font-size: 11px;
  padding: 4px 10px; border-radius: 5px; font-weight: 600;
}
.badge-active { background: #e3f0e6; color: var(--green-deep); }
.badge-blocked { background: #f5e2df; color: var(--danger); }
.badge-pending { background: var(--paper-2); color: var(--gold); }

.password-field { position: relative; }
.password-field input { padding-right: 46px; }
.password-toggle {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer; padding: 4px;
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 600;
  color: var(--green-deep);
}

/* ============================================================
   DESIGN SYSTEM EXTENSIONS — Sep 2026 UI/UX redesign
   ------------------------------------------------------------
   Everything above this line is untouched from the original
   stylesheet — every class name, every CSS custom property, every
   value is exactly as it was. Nothing above was renamed or removed,
   so any page not yet migrated to the new app-shell markup keeps
   rendering exactly as before.

   Everything below is ADDITIVE: new custom properties (all new
   names — none of the originals were redefined), a light visual
   polish pass on the existing shared components (.card, .btn,
   .field, focus states), and a new sidebar "app shell" layout
   system used by the redesigned pages. Business logic, data,
   routes, and JS hooks are unaffected — this file only ever
   controls appearance.
   ============================================================ */

:root {
  --radius-sm: 8px;
  --radius-lg: 20px;
  --shadow-sm: 0 1px 3px rgba(22, 50, 31, 0.07);
  --shadow-md: 0 6px 20px rgba(22, 50, 31, 0.10);
  --transition: 170ms ease;
  --sidebar-width: 264px;
  --content-max: 1180px;
  --header-height: 64px;
  --sidebar-active-bg: #e6f0e3;
  --success: var(--green-deep);
  --warning: #8a5a0f;
  --info: #3a6ea5;
}

/* Slightly refined shared components — same classes, added polish */

.card { box-shadow: var(--shadow-sm); }

.field input, .field select {
  transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
}
.field input:focus, .field select:focus {
  box-shadow: 0 0 0 3px rgba(27, 122, 61, 0.13);
}

.btn { transition: background var(--transition), opacity var(--transition), transform 100ms ease, box-shadow var(--transition); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn-ghost:hover { background: var(--paper-2); }

a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}

/* Page-level heading style used inside the new app shell — sans-serif
   and app-like, per the brand direction that this should read as an
   application rather than a marketing page. The old Fraunces serif
   h1/h2/h3 rule above is untouched and still used for card titles,
   which keeps a touch of the brand's editorial character without it
   dominating the whole screen. */
.page-heading { font-family: 'Inter', -apple-system, sans-serif; font-weight: 700; font-size: 24px; color: var(--ink); margin: 0; line-height: 1.25; }
.page-subheading { font-family: 'Inter', -apple-system, sans-serif; font-size: 14px; color: var(--ink-soft); margin-top: 4px; }

/* ------------------------------------------------------------
   App shell: sidebar (desktop) + collapsible drawer (tablet/mobile)
   Used by the authenticated customer pages (dashboard, profile,
   apply-loan, settings) in place of the old .app-header + .nav-tabs
   stack. Those two classes are left fully intact above for any page
   that hasn't been migrated yet (admin portal, Phase 2).
   ------------------------------------------------------------ */

.app-shell { display: flex; min-height: 100vh; align-items: stretch; }

.sidebar {
  width: var(--sidebar-width); flex-shrink: 0;
  background: var(--white); border-right: 1px solid var(--rule);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; z-index: 30;
}

.sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 22px 20px 16px; }
.sidebar-brand .brand-name { font-size: 14.5px; line-height: 1.25; }

.sidebar-section-label {
  font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--ink-soft); opacity: 0.75; padding: 6px 20px 8px;
}

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; padding: 0 12px; flex: 1; overflow-y: auto; }
.sidebar-link {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--radius-sm);
  color: var(--ink-soft); text-decoration: none; font-size: 14px; font-weight: 600;
  font-family: 'Inter', sans-serif; transition: background var(--transition), color var(--transition);
}
.sidebar-link .icon { flex-shrink: 0; width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.sidebar-link:hover { background: var(--paper-2); color: var(--green-deep); }
.sidebar-link.active { background: var(--sidebar-active-bg); color: var(--green-deep); }

.sidebar-footer { padding: 14px 16px 18px; border-top: 1px solid var(--rule); }
.sidebar-user { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; min-width: 0; }
.sidebar-user-avatar {
  width: 34px; height: 34px; border-radius: 50%; background: var(--green-deep); color: var(--white);
  display: flex; align-items: center; justify-content: center; font-family: 'Fraunces', serif;
  font-weight: 700; font-size: 13px; flex-shrink: 0;
}
.sidebar-user-name { font-size: 13px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-logout {
  display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink-soft);
  text-decoration: none; padding: 8px 4px; border-radius: 6px; transition: color var(--transition);
}
.sidebar-logout:hover { color: var(--danger); }
.sidebar-logout .icon { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.8; }

.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 14px; min-height: var(--header-height);
  padding: 0 28px; border-bottom: 1px solid var(--rule);
  background: rgba(246, 241, 230, 0.92); backdrop-filter: blur(4px);
  position: sticky; top: 0; z-index: 20;
}
.topbar-title { font-family: 'Inter', sans-serif; font-weight: 700; font-size: 18px; color: var(--ink); }

.mobile-menu-btn {
  display: none; background: var(--white); border: 1px solid var(--rule); border-radius: var(--radius-sm);
  width: 36px; height: 36px; align-items: center; justify-content: center; cursor: pointer;
  color: var(--green-deep); flex-shrink: 0; padding: 0;
}
.mobile-menu-btn .icon { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.8; }

.main-content { flex: 1; padding: 28px 32px 48px; max-width: var(--content-max); width: 100%; margin: 0 auto; }

.sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(22, 50, 31, 0.42); z-index: 29; }

@media (max-width: 1024px) {
  .sidebar {
    position: fixed; left: 0; top: 0; transform: translateX(-100%);
    transition: transform var(--transition); box-shadow: var(--shadow-md);
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-overlay.open { display: block; }
  .mobile-menu-btn { display: flex; }
  .main-content { padding: 20px 16px 40px; }
  .topbar { padding: 0 16px; }
}

@media (max-width: 480px) {
  .main-content { padding: 16px 12px 32px; }
  .page-heading { font-size: 21px; }
}

/* ------------------------------------------------------------
   Auth pages (login / register / staff login) — no sidebar, since
   there's no account/session yet. Just a calmer, centered shell
   around the existing .app-header + .wrap + .card pattern so these
   pages read as an application's sign-in screen rather than a bare
   form on a page.
   ------------------------------------------------------------ */

.auth-shell { min-height: 100vh; display: flex; flex-direction: column; }
.auth-shell .app-header { padding: 20px 24px; }
.auth-shell .auth-center {
  flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 24px 16px 48px;
}
.auth-shell .wrap { margin: 0; padding: 0; width: 100%; }
.auth-shell .card { margin-top: 0; }

@media (max-width: 480px) {
  .auth-shell .auth-center { padding: 12px 8px 32px; align-items: flex-start; }
}

/* ------------------------------------------------------------
   Round 2 visual pass — Sep 2026, following reference apps
   (OPay, Flow) the user shared: bolder auth screens, icon-led
   grouped-list rows instead of flat forms wherever the content is
   really a menu (not live data entry), and small quick-action
   tiles for one-tap navigation to existing pages. Everything below
   is additive — nothing above is renamed/removed, and no existing
   class changes meaning.
   ------------------------------------------------------------ */

/* Bolder auth screens (login / register / staff login) — bigger
   headline, larger "pill" inputs. Scoped to .auth-shell so the
   denser admin/customer app-shell forms are unaffected. */
.auth-shell h2 { font-size: 26px; line-height: 1.2; }
.auth-shell .field input,
.auth-shell .field select {
  border-radius: 14px;
  padding: 14px 16px;
  font-size: 15.5px;
}
.auth-shell .password-field input { padding-right: 50px; }

/* Primary action + a compact icon-only alternate action (e.g. the
   fingerprint/Face ID button) side by side, instead of stacked with
   a divider — matches how Flow pairs "Continue" with a fingerprint
   button rather than showing it as a second full-width step. */
.btn-row { display: flex; gap: 10px; align-items: stretch; }
.btn-row .btn { flex: 1; margin: 0; }
.btn-icon-square {
  flex-shrink: 0; width: 52px; display: flex; align-items: center; justify-content: center;
  border-radius: 12px; border: 1.5px solid var(--green-deep); background: var(--white);
  color: var(--green-deep); cursor: pointer; padding: 0;
  transition: background var(--transition), transform 100ms ease;
}
.btn-icon-square:hover { background: var(--paper-2); }
.btn-icon-square:active:not(:disabled) { transform: translateY(1px); }
.btn-icon-square:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-icon-square .icon { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 1.6; }

/* Icon-led grouped list rows — for menu-like content (Settings
   sections, a locked/verified Profile's read-only summary) rather
   than a flat stacked form. A "list-row" is a clickable row that
   toggles a sibling ".list-row-panel" open; a "summary-row" is the
   same visual shape but static (no click, no chevron) for pure
   display data. */
.list-card {
  background: var(--white); border: 1px solid var(--rule); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); overflow: hidden; margin-top: 20px;
}
.list-card + .list-card { margin-top: 16px; }
.list-row {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 14px 18px; border: none; border-bottom: 1px solid var(--rule);
  background: none; cursor: pointer; font-family: 'Inter', sans-serif; color: var(--ink);
}
.list-card > .list-row:last-child,
.list-card > .list-row-panel:last-child { border-bottom: none; }
.list-row:hover { background: var(--paper-2); }
.row-icon {
  width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0;
  background: var(--sidebar-active-bg); color: var(--green-deep);
  display: flex; align-items: center; justify-content: center;
}
.row-icon .icon { width: 19px; height: 19px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.row-text { flex: 1; min-width: 0; }
.row-title { font-weight: 600; font-size: 14.5px; display: block; }
.row-subtitle { font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; display: block; }
.row-chevron { flex-shrink: 0; width: 18px; height: 18px; stroke: var(--ink-soft); fill: none; stroke-width: 2; transition: transform var(--transition); }
.list-row[aria-expanded="true"] .row-chevron { transform: rotate(90deg); }
.list-row-panel { display: none; padding: 2px 18px 18px; border-bottom: 1px solid var(--rule); }
.list-row-panel.open { display: block; }

.summary-row { display: flex; align-items: flex-start; gap: 14px; padding: 14px 18px; border-bottom: 1px solid var(--rule); }
.list-card > .summary-row:last-child { border-bottom: none; }
.summary-row .row-value { font-size: 14.5px; font-weight: 600; margin-top: 2px; word-break: break-word; }

/* Masked sensitive fields (BVN / NIN) — dots by default with a small
   eye-icon toggle to reveal, both in the editable form and in the
   locked/verified read-only summary. Presentation-only: the toggle
   never changes what's stored, only what's currently shown on screen. */
.masked-input-row { display: flex; align-items: center; gap: 8px; }
.masked-input-row input { flex: 1; }
.reveal-input-btn {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 8px; border: 1px solid var(--rule);
  background: var(--white); color: var(--ink-soft); display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.reveal-input-btn:hover { background: var(--paper-2); }
.reveal-input-btn .icon { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.reveal-input-btn.revealed { color: var(--green-deep); border-color: var(--green-deep); }

.summary-row.masked-row { align-items: center; }
.summary-row.masked-row .row-value { font-family: 'IBM Plex Mono', monospace; letter-spacing: 0.5px; }
.reveal-toggle-btn {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--rule);
  background: var(--white); color: var(--ink-soft); display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.reveal-toggle-btn:hover { background: var(--paper-2); }
.reveal-toggle-btn .icon { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.reveal-toggle-btn.revealed { color: var(--green-deep); border-color: var(--green-deep); }

/* Quick-action tiles — one-tap shortcuts to pages that already
   exist in the app (no new routes), styled like a fintech app's
   home-screen action row. */
.quick-actions { display: flex; gap: 14px; margin: 18px 0 6px; flex-wrap: wrap; }
.quick-action { display: flex; flex-direction: column; align-items: center; gap: 8px; text-decoration: none; width: 76px; }
.quick-action .tile-icon {
  width: 52px; height: 52px; border-radius: 16px; background: var(--white); border: 1px solid var(--rule);
  box-shadow: var(--shadow-sm); display: flex; align-items: center; justify-content: center;
  color: var(--green-deep); transition: border-color var(--transition), transform 100ms ease;
}
.quick-action .tile-icon .icon { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.quick-action:hover .tile-icon { border-color: var(--green); }
.quick-action:active .tile-icon { transform: translateY(1px); }
.quick-action .tile-label { font-size: 11.5px; font-weight: 600; color: var(--ink-soft); text-align: center; }

/* ============================================================
   ROUND 3 — Brighter, more open visual pass (Sep 2026)
   ------------------------------------------------------------
   Scoped ENTIRELY to ".customer-portal" (added to <body> on the
   6 customer-facing pages only — login, register, dashboard,
   profile, apply-loan, settings). Nothing above this block is
   renamed, removed, or globally overridden: CSS custom properties
   only cascade to descendants of the element they're redefined
   on, so the Admin Portal (no ".customer-portal" anywhere in its
   markup) keeps rendering exactly as it does today.

   Direction: keep QuickPledge's own brand family (fonts, the gold
   accent, the hand-drawn icon set) but move the surface —
   background, card borders, shadows, and the dominant green —
   toward a brighter, airier register (inspired by a reference the
   user liked), plus a small motion system: page fade-in,
   scroll-reveal, hover/press lift, and skeleton loading states.
   ============================================================ */

.customer-portal {
  --paper: #f8faf7;
  --paper-2: #eef5f0;
  --ink: #142a1d;
  --green-deep: #127a3e;
  --green: #18974d;
  --rule: #dde8e0;
  --sidebar-active-bg: #e4f3e9;
  --radius: 18px;
  --radius-lg: 24px;
  --shadow-sm: 0 1px 3px rgba(18, 122, 62, 0.08), 0 1px 2px rgba(18, 122, 62, 0.04);
  --shadow-md: 0 10px 28px rgba(18, 122, 62, 0.12), 0 2px 8px rgba(18, 122, 62, 0.06);
}

/* Page-load fade-in — the main content area (or the auth card on
   pre-login pages) eases in on load instead of appearing flat. */
@keyframes qpFadeIn {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
.customer-portal .main-content,
.customer-portal .auth-center .wrap {
  animation: qpFadeIn 520ms cubic-bezier(.16,1,.3,1) both;
}

/* Scroll-reveal — elements marked ".reveal" fade + rise into place
   as they enter the viewport. Toggled by shared/scroll-reveal.js,
   which only ever adds/removes the ".is-visible" class — no data
   or business logic involved. If JS never runs (disabled, or an
   ancient browser with no IntersectionObserver) the script's own
   fallback marks everything visible immediately, so content is
   never stuck hidden. */
.customer-portal .reveal {
  opacity: 0; transform: translateY(16px);
  transition: opacity 520ms cubic-bezier(.16,1,.3,1), transform 520ms cubic-bezier(.16,1,.3,1);
}
.customer-portal .reveal.is-visible { opacity: 1; transform: translateY(0); }

/* Hover/press lift — cards, list rows, and quick-action tiles feel
   tappable instead of static. */
.customer-portal .card,
.customer-portal .list-card,
.customer-portal .loan-card {
  transition: transform 200ms cubic-bezier(.16,1,.3,1), box-shadow 200ms cubic-bezier(.16,1,.3,1);
}
.customer-portal .card:hover,
.customer-portal .loan-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

.customer-portal .list-row { transition: background var(--transition), transform 120ms ease; }
.customer-portal .list-row:active { transform: scale(0.99); }

.customer-portal .quick-action .tile-icon {
  transition: transform 160ms cubic-bezier(.34,1.56,.64,1), box-shadow var(--transition), border-color var(--transition);
}
.customer-portal .quick-action:hover .tile-icon { transform: translateY(-3px) scale(1.04); box-shadow: var(--shadow-md); }
.customer-portal .quick-action:active .tile-icon { transform: translateY(0) scale(0.96); }

.customer-portal .sidebar-link { transition: background var(--transition), color var(--transition), transform 120ms ease; }
.customer-portal .sidebar-link:hover { transform: translateX(2px); }

.customer-portal .btn-primary { box-shadow: 0 4px 14px rgba(18, 122, 62, 0.24); }
.customer-portal .btn-primary:hover:not(:disabled) { box-shadow: 0 6px 18px rgba(18, 122, 62, 0.32); transform: translateY(-1px); }
.customer-portal .btn:active:not(:disabled) { transform: translateY(1px) scale(0.98); }

/* Skeleton loading — a shimmering placeholder used while real
   content (e.g. the dashboard's loan list) is still being fetched,
   instead of blank space or plain "Loading…" text. Purely
   presentational: pages only ever swap which markup is visible,
   never change what's fetched or how. */
.customer-portal .skeleton {
  border-radius: 8px;
  background: linear-gradient(90deg, var(--paper-2) 25%, #dcece1 37%, var(--paper-2) 63%);
  background-size: 400% 100%;
  animation: qpShimmer 1.4s ease infinite;
}
@keyframes qpShimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }

.customer-portal .skeleton-card {
  background: var(--white); border: 1px solid var(--rule); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 20px 22px; margin-top: 14px;
}
.customer-portal .skeleton-line1 { width: 130px; height: 22px; margin-bottom: 8px; }
.customer-portal .skeleton-line2 { width: 90px; height: 13px; }

@media (prefers-reduced-motion: reduce) {
  .customer-portal .main-content,
  .customer-portal .auth-center .wrap,
  .customer-portal .reveal { animation: none !important; opacity: 1 !important; transform: none !important; transition: none !important; }
  .customer-portal .card:hover,
  .customer-portal .loan-card:hover,
  .customer-portal .quick-action:hover .tile-icon,
  .customer-portal .btn-primary:hover:not(:disabled) { transform: none; }
}
