/* Charti App Styles
 *
 * Table of contents (section comments below match these titles):
 *   1. Fonts & design tokens (:root, [data-theme="dark"])
 *   2. Base (reset, body, typography, x-cloak, focus-visible, reduced motion)
 *   3. Layout: Header, Container, Navigation, Sidebar (desktop), Side Menu,
 *      Main content
 *   4. Components: Card, Button, Alert/Toast, Dialog, Loading/Spinners, Form,
 *      Tag, Icon, Utilities
 *   5. Features: Document list & expanded panel, Document detail, Pull-to-refresh,
 *      Processing tasks, Stats, Cloud sync/preferences, eBanking QR carousel,
 *      Document scanner, Recent scans, About page, Auth pages
 *   6. Responsive (mobile ≤768px; desktop ≥1024px sidebar; eBanking ≥769px)
 *   7. Third-party overrides: Tom Select (field theme), impersonation banner,
 *      Django debug toolbar
 *
 * TOKEN RULE: component rules use the semantic role tokens below — never raw
 * hex values. New colors go into BOTH the :root (light) and [data-theme="dark"]
 * blocks. The theme is resolved by an inline script in <head> (base.html) that
 * always stamps data-theme="light|dark" on <html> before this file loads.
 */

/*
 * Self-hosted Inter (variable font, weights 100-900 in one file).
 * Used for the brand voice: headings and logo. The dense app UI keeps the
 * native system stack (see --font-sans) so we pay no webfont cost there.
 * font-display: swap -> text renders immediately in the fallback, then
 * upgrades to Inter when it loads (no invisible-text flash).
 */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/InterVariable.2bf3d951bf9d.woff2") format('woff2');
}

:root {
  /* Body / dense app UI: native per-platform UI font, zero load cost. */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  /* Brand voice: Inter for headings and logo, system stack as fallback. */
  --font-brand: 'Inter', var(--font-sans);

  color-scheme: light;

  /*
   * Teal-led "modern" brand direction. Teal is the trust color (finance/
   * fintech) without red's "debt / error" baggage, on a clean Swiss-minimal
   * neutral base. Red is demoted to a functional accent: errors, destructive
   * actions, and genuine urgency only (--color-error), where its high-arousal
   * signal is an asset rather than an everyday background.
   */

  /* -- Color roles: brand -- */
  --color-primary: #0f766e;            /* deep teal - primary actions, links, accents */
  --color-primary-dark: #0c5d57;       /* teal hover/active */
  --color-on-primary: #fff;
  --color-primary-container: #e0f2f1;  /* light teal tint: paid tag, active field items */
  --color-on-primary-container: #0f766e;
  --color-primary-outline: #a7d8d2;    /* soft teal hairline (secondary buttons) */
  --color-header-bg: #0f766e;          /* app header / menu header surface */
  --color-on-header: #fff;

  /* -- Color roles: surfaces & text -- */
  --color-surface: #fff;               /* cards, nav, panels */
  --color-surface-dim: #f4f7f8;        /* cool near-white app canvas */
  --color-surface-container: #f0f2f5;  /* inset boxes, code blocks, spinner tracks */
  --color-surface-alt: #f9f9f9;        /* subtle alternate surface: stat boxes, info panels */
  --color-on-surface: #1a2027;         /* near-black for crisp Swiss-minimal text */
  --color-on-surface-variant: #5b6771; /* secondary text: meta lines, labels, help text */
  --color-on-surface-muted: #757575;   /* hints, separators (AA on white; never lighter) */
  --color-outline: #e2e8f0;            /* light cool border */
  --color-outline-strong: #c3cbd5;     /* hover borders, placeholder text, scroll thumbs */
  --color-inverse-surface: #1e1e1e;    /* tooltips */
  --color-on-inverse-surface: #fff;
  --color-scrim: rgba(0, 0, 0, 0.4);   /* menu/dialog overlays */

  /* -- Color roles: status -- */
  --color-error: #dc2626;              /* red - errors, destructive, urgency ONLY */
  --color-error-soft: #ef4444;         /* lighter red for non-destructive error text */
  --color-error-container: #fef2f2;
  --color-secondary: #334155;          /* slate for secondary text/UI */
  --color-success: #4caf50;
  --color-success-container: #edf7f6;  /* teal-tinted "good/in-progress" surface */
  --color-warning: #ff9800;
  --color-warning-container: #fff4e5;
  --color-on-warning-container: #b45309;
  --color-info: #1565c0;
  --color-info-container: #e3f2fd;
  --color-sync-synced: #2e7d32;
  --color-sync-moved: #6a1b9a;

  /* -- Shape scale -- */
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-full: 999px;

  /* -- Elevation scale -- */
  --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.1);
  --shadow-2: 0 2px 6px rgba(0, 0, 0, 0.12);
  --shadow-3: 0 4px 12px rgba(0, 0, 0, 0.12);
  --shadow-4: 0 10px 40px rgba(0, 0, 0, 0.12);

  /* -- Spacing scale (use for new rules; legacy literals migrate over time) -- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;

  /* -- Type scale -- */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.5rem;
  --text-2xl: 2rem;

  /* -- Motion -- */
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --duration-fast: 100ms;
  --duration-base: 200ms;

  /* -- Z scale -- */
  --z-header: 40;
  --z-nav: 50;
  --z-banner: 60;
  --z-overlay: 90;
  --z-menu: 100;

  /* -- Field metrics (form controls & Tom Select) -- */
  --field-height: 40px;
  --touch-target: 48px;

  /* -- Layout -- */
  --sidebar-width: 240px;
}

/*
 * Dark theme. The inline script in base.html <head> resolves the stored
 * preference (or the OS setting) and stamps data-theme BEFORE this stylesheet
 * applies, so there is no light flash. Shadows fade out in dark mode; surfaces
 * lift tonally instead (surface-container is lighter than surface).
 */
[data-theme="dark"] {
  color-scheme: dark;

  --color-primary: #2fbfae;
  --color-primary-dark: #4ecdbe;       /* hover = lighter in dark */
  --color-on-primary: #06211e;
  --color-primary-container: #123f39;
  --color-on-primary-container: #7edcd2;
  --color-primary-outline: #2a5f59;
  --color-header-bg: #0d3833;
  --color-on-header: #f0f4f4;

  --color-surface: #1c2226;
  --color-surface-dim: #12171a;
  --color-surface-container: #262e33;
  --color-surface-alt: #20272b;
  --color-on-surface: #e6e9eb;
  --color-on-surface-variant: #a6b0b5;
  --color-on-surface-muted: #8b959b;
  --color-outline: #323b41;
  --color-outline-strong: #4b565e;
  --color-inverse-surface: #e6e9eb;
  --color-on-inverse-surface: #1a2027;
  --color-scrim: rgba(0, 0, 0, 0.6);

  --color-error: #e05252;
  --color-error-soft: #f28b8b;
  --color-error-container: #3a2023;
  --color-secondary: #b9c4d0;
  --color-success: #66bb6a;
  --color-success-container: #16302c;
  --color-warning: #d98a2b;
  --color-warning-container: #3a2f1a;
  --color-on-warning-container: #ecb36c;
  --color-info: #64b5f6;
  --color-info-container: #16283a;
  --color-sync-synced: #81c784;
  --color-sync-moved: #ce93d8;

  --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-2: 0 2px 6px rgba(0, 0, 0, 0.45);
  --shadow-3: 0 4px 12px rgba(0, 0, 0, 0.5);
  --shadow-4: 0 10px 40px rgba(0, 0, 0, 0.55);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Alpine.js: hide x-cloak elements until Alpine initializes (prevents a flash
   of tooltips/error hints on page load; Alpine removes the attribute). */
[x-cloak] { display: none !important; }

/* Reserve the scrollbar gutter so the page never reflows when a vertical
   scrollbar appears/disappears (e.g. a hover card opening near the bottom of a
   list). Without this, the right-aligned meta row jumps left as the scrollbar
   claims width. No-op on platforms with overlay scrollbars (mobile app). */
html {
  scrollbar-gutter: stable;
}

body {
  font-family: var(--font-sans);
  background-color: var(--color-surface-dim);
  color: var(--color-on-surface);
  line-height: 1.6;
  /* Safety net: a single over-wide element must never widen the layout
     viewport — that stretches the fixed header/bottom-nav past the screen
     edge on phones. `clip` avoids creating a scroll container. */
  overflow-x: clip;
}

/* Long unbroken strings (URLs, paths, tokens) in inline code must wrap
   instead of forcing horizontal overflow on narrow screens. */
code {
  overflow-wrap: anywhere;
}

/*
 * Brand typeface for headings and logo only. Keeps the dense document
 * lists on the fast system stack while giving Charti an identity on the
 * surfaces that carry brand voice.
 */
h1, h2, h3,
.header h1 {
  font-family: var(--font-brand);
  letter-spacing: -0.01em;
}

/*
 * Tabular (monospaced) figures for financial data: amounts, IBANs, dates,
 * QR values. Digits share a fixed width so numbers align in columns and are
 * easier to scan. 'zero' enables Inter's slashed zero (0 vs O clarity).
 */
.tabular-nums,
.amount,
.iban,
.qr-amount {
  font-variant-numeric: tabular-nums slashed-zero;
  font-feature-settings: 'tnum' 1, 'zero' 1;
}

/* Visible keyboard focus everywhere; invisible for mouse/touch. */
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Screen-reader-only text (state labels next to icons, etc.). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Respect the OS "reduce motion" setting: drop transitions/transforms but
   keep spinners (progress feedback) at a slower, calmer speed. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  .spinner, .spinner-sm, .qr-spinner-inner {
    animation: spin 2s linear infinite !important;
  }
}

/* Header */
.header {
  background-color: var(--color-header-bg);
  color: var(--color-on-header);
  padding: 1rem;
  padding-top: calc(1rem + env(safe-area-inset-top, 0px));
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: var(--shadow-1);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-header);
  will-change: transform;
}

/* Extend header background above to mask the brief gap during gesture bar animation */
.header::before {
  content: '';
  position: absolute;
  top: -100px;
  left: 0;
  right: 0;
  height: 100px;
  background-color: var(--color-header-bg);
}

.header h1 {
  font-size: 1.5rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.header-username {
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40vw;
}

/* Container */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 1rem;
}

/* Card */
.card {
  background-color: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 1rem;
  margin-bottom: 1rem;
  box-shadow: var(--shadow-1);
}
.card.mb-sm { margin-bottom: var(--space-3); }

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--color-outline);
}

.card-title {
  font-size: 1.1rem;
  font-weight: 600;
}

.card-body {
  font-size: 0.9rem;
}

.card-inset {
  box-shadow: none;
  border: 1px solid var(--color-outline);
  margin-bottom: 0;
  padding: 0.5rem 0.75rem;
}
.card-inset .card-header { padding-bottom: 0.25rem; margin-bottom: 0.25rem; border-bottom: none; }
.card-header .btn { background: transparent; color: var(--color-on-surface-muted); border: none; padding: 0 0.25rem; box-shadow: none; }
.card-inset .card-title { font-size: 0.875rem; }
.doc-id-badge { font-size: 0.75rem; color: var(--color-on-surface-muted); }

/* Button */
.btn {
  /* inline-flex (not the browser default `inline` for <a>) so vertical padding
     and margins take up layout space instead of painting over adjacent lines.
     An inline <a class="btn"> otherwise overlaps the text above it. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  border: 1px solid transparent;  /* variants set the edge color; keeps all buttons the same size */
  border-radius: var(--radius-md);
  font-size: 1rem;
  /* Browsers don't give <button> the body's font-family/line-height the way
     <a> inherits them by default — a <button class="btn"> next to an
     <a class="btn"> in the same row (e.g. a checklist-actions pair) otherwise
     renders visibly shorter. Force both element types onto the same metrics. */
  font-family: inherit;
  line-height: inherit;
  cursor: pointer;
  transition: background var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
  font-weight: 500;
  text-decoration: none;
}
a.btn, a.btn:hover, a.btn:visited { text-decoration: none; }

/*
 * Variation C - the restrained "modern SaaS" system (shadcn/Linear/Stripe):
 * a whisper of vertical gradient, a hairline darker edge and a small colored
 * shadow. Hover uses a state-layer color shift (M3-style) instead of a
 * transform lift, so rows don't jiggle and touch devices get the same cue.
 * All solid variants (primary/danger/success) share this treatment; secondary
 * is a clean neutral outline that recedes so the primary leads.
 */
/* Shared structure of the solid variants; each variant only sets its colors. */
.btn-primary,
.btn-success,
.btn-danger {
  color: var(--color-on-primary);
}

.btn-primary {
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-primary) 90%, #fff) 0%, var(--color-primary) 100%);
  border-color: var(--color-primary-dark);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--color-primary) 25%, transparent);
}

.btn-primary:hover {
  background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
  box-shadow: 0 3px 8px color-mix(in srgb, var(--color-primary) 30%, transparent);
}

.btn-primary:active {
  box-shadow: 0 1px 2px color-mix(in srgb, var(--color-primary) 25%, transparent);
}

.btn-danger {
  color: #fff;
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-error) 90%, #fff) 0%, var(--color-error) 100%);
  border-color: color-mix(in srgb, var(--color-error) 85%, #000);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--color-error) 25%, transparent);
}

.btn-danger:hover {
  background: linear-gradient(180deg, var(--color-error) 0%, color-mix(in srgb, var(--color-error) 85%, #000) 100%);
  box-shadow: 0 3px 8px color-mix(in srgb, var(--color-error) 30%, transparent);
}

.btn-danger:active {
  box-shadow: 0 1px 2px color-mix(in srgb, var(--color-error) 25%, transparent);
}

/* Secondary = teal outline: transparent surface, soft teal hairline, teal text. */
.btn-secondary {
  background-color: transparent;
  color: var(--color-primary);
  border-color: var(--color-primary-outline);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--color-primary) 8%, transparent);
}

.btn-secondary:hover {
  background-color: color-mix(in srgb, var(--color-primary) 8%, transparent);
  border-color: var(--color-primary);
}

.btn-success {
  color: #fff;
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-success) 90%, #fff) 0%, var(--color-success) 100%);
  border-color: color-mix(in srgb, var(--color-success) 85%, #000);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--color-success) 25%, transparent);
}

.btn-success:hover {
  background: linear-gradient(180deg, var(--color-success) 0%, color-mix(in srgb, var(--color-success) 85%, #000) 100%);
  box-shadow: 0 3px 8px color-mix(in srgb, var(--color-success) 30%, transparent);
}

.btn-success:disabled {
  opacity: 0.7;
  cursor: default;
}

.btn-icon {
  padding: 0.5rem;
  background: transparent;
  color: var(--color-on-header);
  border: 1px solid var(--color-on-header);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.btn-sm {
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
}

/* Icon system: Lucide symbols from the static sprite (partials/icon.html).
   Sized in em so icons track the text size of their context; stroke follows
   currentColor so they recolor with the theme for free. */
.icon {
  display: inline-block;
  width: 1.2em;
  height: 1.2em;
  vertical-align: -0.24em;
  flex-shrink: 0;
}

/* Pull-to-refresh */
.ptr-indicator {
  display: flex;
  justify-content: center;
  padding: 0.5rem 0;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity 0.15s, max-height 0.15s;
  pointer-events: none;
}
.ptr-indicator.ptr-visible {
  opacity: 1;
  max-height: 3rem;
}
.ptr-indicator .spinner-sm {
  width: 40px;
  height: 40px;
}

/* Document List */
.document-list {
  /* Shared with .document-item.is-removing, which cancels this gap as a row collapses. */
  --document-list-gap: 0.4rem;
  display: flex;
  flex-direction: column;
  gap: var(--document-list-gap);
}

/* Bulk selection bar above the inbox list. Hidden controls are x-cloak'd until the
   Select toggle turns selection mode on. */
.selection-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.4rem;
}

.selection-all {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.875rem;
  color: var(--color-on-surface-variant);
  cursor: pointer;
}

.selection-count {
  font-size: 0.875rem;
  color: var(--color-on-surface-variant);
}

/* Pushed to the trailing edge so destructive actions never sit under the pointer
   on its way to a checkbox. */
.selection-actions {
  display: flex;
  gap: 0.5rem;
  margin-left: auto;
}

/* Inline escalation link in the selection bar: appears once every loaded row is
   ticked, and is the only way to widen the selection past what is on screen. */
.selection-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--color-primary);
  text-decoration: underline;
  cursor: pointer;
}

.selection-link:hover {
  color: var(--color-primary-dark);
}

/* Checkbox column in front of each row; the body takes the remaining width and
   keeps min-width:0 so the title still ellipsises. */
.document-item-head {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
}

.document-item-body {
  flex: 1 1 auto;
  min-width: 0;
}

.document-select {
  display: flex;
  align-items: center;
  padding-top: 0.2rem;
}

.selection-all input,
.document-select input {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--color-primary);
  cursor: pointer;
}

.document-item {
  background-color: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 0.5rem 0.75rem;
  box-shadow: var(--shadow-1);
  border-left: 3px solid transparent;
  transition: background-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard);
}

/* Hover = state layer + slight lift in elevation; no lateral movement. */
.document-item:hover {
  background-color: color-mix(in srgb, var(--color-primary) 4%, var(--color-surface));
  box-shadow: var(--shadow-2);
}

/* Expanded rows get a teal rail so the open item is scannable in the list
   (class bound to the Alpine `expanded` state in document_item.html). */
.document-item.is-expanded {
  border-left-color: var(--color-primary);
}

/* Bulk-action removal: the row collapses out of the list rather than vanishing, so it
   reads as "these are the ones that went". JS pins the row's measured pixel height
   first — a transition cannot run from `auto` — then adds this class and drops the
   element on transitionend. height needs !important to beat that inline style. The
   negative margin swallows the flex gap the row would otherwise keep holding open
   while its height animates to 0.
   Under the global prefers-reduced-motion rule the duration collapses to ~0ms and
   transitionend still fires, so the row is removed either way. */
.document-item.is-removing {
  overflow: hidden;
  height: 0 !important;
  min-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: calc(-1 * var(--document-list-gap, 0.4rem));
  opacity: 0;
  transform: translateX(-1.5rem);
  box-shadow: none;
  pointer-events: none;
  transition: height var(--duration-base) var(--ease-standard),
              padding var(--duration-base) var(--ease-standard),
              margin var(--duration-base) var(--ease-standard),
              opacity var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}

.document-item-publishing {
  opacity: 0.5;
  cursor: default;
  pointer-events: none;
}

.document-title {
  font-weight: 600;
  margin-bottom: 0.2rem;
  color: var(--color-on-surface);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.document-title-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1 1 0;
  min-width: 0;
}

/* Split the title into WHO (correspondent) and WHAT (document name):
   correspondent takes the teal accent, the separator recedes, the name stays dark. */
.document-title-correspondent {
  color: var(--color-primary);
}
.document-title-sep {
  color: var(--color-on-surface-variant);
}

.document-title-field {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1 1 0;
  min-width: 0;
  /* Anchor for the full-title hover card. */
  position: relative;
}

/* Read-only counterpart of .document-title-field: the title span clips its own
   overflow, so the hover card needs a non-clipping positioned ancestor. */
.document-title-wrap {
  position: relative;
  display: flex;
  min-width: 0;
  flex: 1 1 0;
}

.document-title-field .document-title-text {
  flex: 0 1 auto;
  max-width: 100%;
  cursor: text;
  border-radius: var(--radius-xs);
  padding: 0.1rem 0.3rem;
  margin: -0.1rem -0.3rem;
}

.document-title-field .document-title-text:hover,
.document-title-field .document-title-text:focus-visible {
  background-color: color-mix(in srgb, var(--color-primary) 8%, transparent);
  outline: none;
}

.document-title-edit-input {
  flex: 0 1 auto;
  max-width: 100%;
  font: inherit;
  font-weight: inherit;
  padding: 0.1rem 0.3rem;
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-xs);
  background-color: var(--color-surface);
  color: var(--color-on-surface);
}

.document-title-edit-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 15%, transparent);
}

.document-title-meta {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--color-on-surface-variant);
  white-space: nowrap;
  flex-shrink: 0;
}

.document-title-meta span {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
}

.document-summary-wrap {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
}

.document-summary {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8rem;
}

/* Shared hover card: document summary (summary_30) and the title-meta items. */
.hover-card {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  z-index: 20;
  width: max-content;
  max-width: min(360px, 80vw);
  background: var(--color-inverse-surface);
  color: var(--color-on-inverse-surface);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.45;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  white-space: normal;
  text-align: left;
  pointer-events: none;
}
/* Title tooltip: its whole point is reading the title the ellipsis cut off, so it
   fills the row width and wraps rather than capping at the shared 360px. */
.hover-card-title {
  max-width: max(100%, 360px);
  overflow-wrap: anywhere;
}
/* Descendant spans of the meta rows are forced to inline-flex; keep cards block. */
.document-meta .hover-card,
.document-title-meta .hover-card { display: block; }
/* Anchor for a meta item's hover card. */
.document-title-meta .meta-tip { position: relative; }
/* The meta row ends flush with the row's right edge, so the last chip's card
   would run past the viewport and get cut off (body sets overflow-x: clip).
   Open it leftward instead — same reasoning as .document-date-popover.
   The document-date chip is included separately (document_date.html) and so
   is never :last-child even though it sits just as close to the right edge -
   target it explicitly alongside the structural :last-child case. */
.document-title-meta .meta-tip:last-child .hover-card,
.document-title-meta .meta-tip.document-date .hover-card {
  left: auto;
  right: 0;
}

.document-meta {
  font-size: 0.875rem;
  color: var(--color-on-surface-variant);
  display: flex;
  gap: 1rem;
  margin-bottom: 0;
  align-items: center;
}

.document-meta span {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 0.25em;
}


.document-meta-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-left: auto;
}

.document-meta-cloud {
  font-size: 0.75rem;
  white-space: nowrap;
}

.cloud-synced   { color: var(--color-sync-synced); }
.cloud-in_progress { color: var(--color-info); }
.cloud-failed   { color: var(--color-error); }
.cloud-pending  { color: var(--color-on-surface-muted); }
.cloud-moved    { color: var(--color-sync-moved); }
.cloud-none     { color: var(--color-on-surface-muted); }

.cloud-synced-label {
  position: relative;
  cursor: default;
}
.cloud-path-tooltip {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background: var(--color-inverse-surface);
  color: var(--color-on-inverse-surface);
  font-size: 0.7rem;
  padding: 4px 8px;
  border-radius: var(--radius-xs);
  white-space: nowrap;
  z-index: 10;
  pointer-events: none;
}

.document-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.tag {
  display: inline-block;
  padding: 0.25rem 0.75rem;
  background-color: var(--color-surface-container);
  border-radius: var(--radius-lg);
  font-size: 0.75rem;
  font-weight: 500;
}

.tag-sm {
  padding: 0.05rem 0.5rem;
  border-radius: var(--radius-md);
}

/*
 * "A payer" (unpaid) is a pending task, not an error - most invoices sit here,
 * so amber ("needs attention") keeps the list calm and reserves red for real
 * problems. "Payé" (done) uses a light teal that ties into the brand color.
 */
.tag-to-pay {
  background-color: var(--color-warning-container);
  color: var(--color-on-warning-container);
}

.tag-paid {
  background-color: var(--color-primary-container);
  color: var(--color-on-primary-container);
}

/* Loading */
.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 2rem;
}

.spinner {
  border: 3px solid var(--color-surface-container);
  border-top: 3px solid var(--color-primary);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  animation: spin 1s linear infinite;
}

/* Small variant (pull-to-refresh, processing tasks); same track/accent pair as .spinner. */
.spinner-sm {
  width: 16px;
  height: 16px;
  border: 2px solid var(--color-surface-container);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 1s linear infinite;
  flex-shrink: 0;
}

/* eBanking QR placeholder variant (neutral grey, faster spin). */
.qr-spinner-inner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--color-outline);
  border-top-color: var(--color-on-surface-variant);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* Alert */
.alert {
  padding: 1rem;
  border-radius: var(--radius-sm);
  margin-bottom: 1rem;
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}
.alert > :first-child { flex: 1; }

.alert-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

/* Manual dismiss button on flash messages (a11y: no more 5s auto-dismiss). */
.alert-dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 0.25rem;
  opacity: 0.7;
}
.alert-dismiss:hover { opacity: 1; }

/* Success = same teal-tinted surface as .btn-secondary, for visual consistency. */
.alert-success {
  background-color: var(--color-success-container);
  color: var(--color-primary);
  border-left: 4px solid var(--color-primary);
}

/* Error = lighter red than --color-error, which is reserved for destructive
 * actions/genuine urgency. A flash message doesn't need that much alarm. */
.alert-error {
  background-color: var(--color-error-container);
  color: var(--color-error-soft);
  border-left: 4px solid var(--color-error-soft);
}

.alert-warning {
  background-color: var(--color-warning-container);
  color: var(--color-on-warning-container);
  border-left: 4px solid var(--color-warning);
}

.alert-info {
  background-color: var(--color-info-container);
  color: var(--color-info);
  border-left: 4px solid var(--color-info);
}

/* Flash messages render as toasts: fixed above the bottom nav on small
   screens (thumb zone, matches the mobile-app feel), in-flow on desktop. */
@media (max-width: 768px) {
  #messages {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    z-index: var(--z-banner);
  }
  #messages .alert {
    box-shadow: var(--shadow-3);
  }
}

/* Confirm dialog (replaces native hx-confirm browser dialogs; see app.js). */
.confirm-dialog {
  /* The global `* { margin: 0 }` reset above zeroes the UA stylesheet's
     `dialog:modal { margin: auto }`, which is what centers showModal() on
     screen — restore it here or the dialog docks to the top-left instead. */
  margin: auto;
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-on-surface);
  padding: 1.5rem;
  max-width: 420px;
  width: calc(100vw - 2rem);
  box-shadow: var(--shadow-4);
}
.confirm-dialog::backdrop {
  background: var(--color-scrim);
}
.confirm-dialog-message {
  margin-bottom: 1.25rem;
  line-height: 1.5;
}
.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

/* First-login welcome modal (templates/charti/partials/onboarding/welcome_modal.html) */
.onboarding-modal-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: var(--z-menu);
}
.onboarding-modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--color-scrim);
}
.onboarding-modal {
  position: relative;
  z-index: 1;
  max-width: 440px;
  width: calc(100vw - 2rem);
  padding: var(--space-8) var(--space-6) var(--space-6);
  text-align: center;
  background: var(--color-surface);
  color: var(--color-on-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-4);
}
.onboarding-modal-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-full);
  background: var(--color-primary-container);
  color: var(--color-primary);
}
.onboarding-modal-title {
  margin-bottom: var(--space-3);
}
.onboarding-modal p {
  color: var(--color-on-surface-variant);
  line-height: 1.5;
  margin-bottom: var(--space-3);
}
.onboarding-modal p.onboarding-modal-trial {
  font-weight: 600;
  color: var(--color-on-surface);
}
.onboarding-modal-actions {
  margin-top: var(--space-6);
}

/* Getting Started checklist (templates/charti/partials/onboarding/checklist.html) */
.onboarding-checklist .card-header {
  align-items: center;
}
.checklist-progress {
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  color: var(--color-primary);
  background: var(--color-primary-container);
}
.onboarding-checklist-intro {
  margin-bottom: var(--space-4);
}
.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.checklist-item {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}
.checklist-check {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-top: 2px;
  border-radius: var(--radius-full);
  background: var(--color-surface-container);
  color: var(--color-on-surface-muted);
}
.checklist-item.is-done .checklist-check {
  background: var(--color-primary);
  color: #fff;
}
.checklist-body {
  flex: 1 1 auto;
  min-width: 0;
}
.checklist-title {
  font-weight: 600;
  color: var(--color-on-surface);
}
.checklist-item.is-done .checklist-title {
  color: var(--color-on-surface-muted);
  text-decoration: line-through;
}
.checklist-desc {
  margin-top: 2px;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--color-on-surface-variant);
}
.checklist-actions,
.checklist-inbox {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.checklist-sublist {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.checklist-sublist a {
  color: var(--color-primary);
  text-decoration: none;
}
.checklist-sublist a:hover {
  text-decoration: underline;
}

/* "Get Started" nav progress ring (templates/charti/partials/onboarding/nav_progress_ring.html):
   a small donut that fills clockwise as core checklist steps get done. Built from a
   conic-gradient (0% -> --pct in primary, the rest in the outline color) with a
   mask-image punching a transparent hole through the middle, so it reads correctly
   regardless of what's behind it (sidebar hover/active backgrounds, menu panel, ...). */
.nav-progress-ring {
  --pct: 0%;
  flex: 0 0 auto;
  display: inline-block;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  background: conic-gradient(var(--color-primary) var(--pct), var(--color-outline) 0);
  -webkit-mask-image: radial-gradient(closest-side, transparent 62%, black 63%);
  mask-image: radial-gradient(closest-side, transparent 62%, black 63%);
}
.nav-progress-ring.is-done {
  background: var(--color-primary);
}
/* Push the ring to the item's trailing edge; .sidebar-item is already a flex row
   (icon + label), .menu-item-get-started needs to become one since plain .menu-item
   links are block-level text only. */
.sidebar-item-get-started .nav-progress-ring,
.menu-item-get-started .nav-progress-ring {
  margin-left: auto;
}
.menu-item-get-started {
  display: flex;
  align-items: center;
}

/* Tom Select – field theme (tokens live in the :root block at the top) */

/* Wrapper */
.ts-wrapper {
  font-weight: 400;
}

/* Vertical alignment: label and Tom Select sit side-by-side */
.custom-field-inline .ts-wrapper {
  display: flex;
  align-items: center;
}

.ts-wrapper.multi .ts-control,
.ts-wrapper.single .ts-control {
  background-color: var(--color-surface);
  border: none;
  border-radius: var(--radius-xs);
  min-height: var(--field-height);
  padding: 2px 8px !important;
  color: var(--color-secondary);
  font-size: 0.8125rem;
  cursor: pointer;
  box-shadow: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  align-items: center;
}

/* Caret on single selects only (not on multi/tags) */
.ts-wrapper.single .ts-control {
  padding-right: 28px !important;
  position: relative;
  border: 2px solid var(--color-outline);
}

.ts-wrapper.single .ts-control:hover {
  border-color: var(--color-outline-strong);
}

.ts-wrapper.single.focus .ts-control {
  border-color: var(--color-primary);
}

.ts-wrapper.single .ts-control::after {
  content: '';
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%23C3CBD5'/%3E%3C/svg%3E");
  background-size: 20px;
  background-repeat: no-repeat;
  pointer-events: none;
}

/* Focused state */
.ts-wrapper.multi.focus .ts-control,
.ts-wrapper.single.focus .ts-control {
  box-shadow: none;
}

.ts-wrapper.single.focus .ts-control::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%23546478'/%3E%3C/svg%3E");
}

/* Dark theme carets (background-image can't use currentColor). */
[data-theme="dark"] .ts-wrapper.single .ts-control::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%234B565E'/%3E%3C/svg%3E");
}
[data-theme="dark"] .ts-wrapper.single.focus .ts-control::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%23A6B0B5'/%3E%3C/svg%3E");
}

/* Search input inside control */
.ts-control > input {
  color: var(--color-secondary);
  font-size: 0.8125rem;
}

.ts-control > input::placeholder {
  color: var(--color-outline-strong);
}

/* Selected tag items (multi-select) */
.ts-wrapper.multi .ts-control > .item {
  background: var(--color-surface-container);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-xs);
  color: var(--color-secondary);
  font-size: 0.75rem;
  padding: 1px 6px;
  margin: 2px 2px;
  line-height: 1.5;
}

.ts-wrapper.multi .ts-control > .item.active {
  background: var(--color-primary-container);
  border-color: var(--color-primary-outline);
  color: var(--color-on-primary-container);
}

/* Remove button on tags */
.ts-wrapper.multi .ts-control > .item .remove {
  border-left: 1px solid var(--color-outline);
  color: var(--color-outline-strong);
  font-size: 14px;
  padding: 0 4px;
  margin-left: 4px;
}

.ts-wrapper.multi .ts-control > .item .remove:hover {
  color: var(--color-error);
  background: transparent;
}

/* Dropdown panel */
.ts-dropdown {
  z-index: var(--z-header) !important;
  border: 2px solid var(--color-outline);
  border-top: none;
  border-radius: 0 0 var(--radius-xs) var(--radius-xs);
  box-shadow: var(--shadow-3);
  background: var(--color-surface);
  margin-top: -2px;
}

/* Dropdown options */
.ts-dropdown .option {
  padding: 6px 10px;
  font-size: 0.8125rem;
  color: var(--color-secondary);
  cursor: pointer;
  transition: background-color 0.1s ease;
}

.ts-dropdown .option:hover,
.ts-dropdown .option.active {
  background-color: var(--color-primary-container);
  color: var(--color-on-primary-container);
}

.ts-dropdown .option.selected {
  background-color: var(--color-surface-container);
  color: var(--color-on-surface-variant);
}

/* "Create" option at bottom */
.ts-dropdown .create {
  padding: 6px 10px;
  font-size: 0.8125rem;
  color: var(--color-primary);
  border-top: 1px solid var(--color-outline);
}

.ts-dropdown .create:hover {
  background-color: var(--color-primary-container);
}

/* No results */
.ts-dropdown .no-results {
  padding: 6px 10px;
  font-size: 0.8125rem;
  color: var(--color-on-surface-muted);
}

/* Thin scrollbar */
.ts-dropdown-content {
  max-height: 200px;
  scrollbar-width: thin;
  scrollbar-color: var(--color-outline-strong) var(--color-surface-container);
  scroll-behavior: smooth;
}

.ts-dropdown-content::-webkit-scrollbar {
  width: 4px;
}

.ts-dropdown-content::-webkit-scrollbar-track {
  background: var(--color-surface-container);
}

.ts-dropdown-content::-webkit-scrollbar-thumb {
  background: var(--color-outline-strong);
  border-radius: 2px;
}

/* Disabled state */
.ts-wrapper.disabled .ts-control {
  background-color: var(--color-surface-container);
  border-color: var(--color-outline);
  color: var(--color-on-surface-variant);
  cursor: not-allowed;
  opacity: 1;
}

/* Navigation */
.nav-bottom {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: var(--color-surface);
  box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.1);
  display: flex;
  justify-content: space-around;
  padding: 0.5rem 0;
  padding-bottom: 0.5rem;
  z-index: var(--z-nav);
  will-change: transform;
}

/* Extend nav background below to mask the brief gap during gesture bar animation */
.nav-bottom::after {
  content: '';
  position: absolute;
  bottom: -100px;
  left: 0;
  right: 0;
  height: 100px;
  background-color: var(--color-surface);
}

.nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Equal quarters that can shrink: long labels (fr "Télécharger") must never
     push the last tab off-screen on narrow phones. */
  flex: 1 1 0;
  min-width: 0;
  padding: 0.5rem 0.25rem;
  color: var(--color-on-surface-variant);
  text-decoration: none;
  font-size: 0.75rem;
  transition: color 0.2s;
  border-radius: var(--radius-md);
}

.nav-item span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Active destination: color + a pill indicator (not color alone; WCAG 1.4.1). */
.nav-item.active,
.nav-item[aria-current="page"] {
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
}

.nav-item svg {
  width: 24px;
  height: 24px;
  margin-bottom: 0.25rem;
}

/* Desktop sidebar (≥1024px replaces the bottom nav; see Responsive section).
   Rendered always, hidden below the breakpoint. */
.sidebar {
  display: none;
}

/* Form */
.form-group {
  margin-bottom: 1rem;
}

.form-label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
}

/* A form-label wrapping its own checkbox (e.g. preferences toggles), rather than
   labelling a separate input via `for` - laid out as a row instead of a block. */
.form-label-inline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  font-weight: 500;
  cursor: pointer;
}
.form-label-inline input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--color-primary);
  cursor: pointer;
}

.form-input,
.auth-form input:not([type="checkbox"], [type="radio"], [type="hidden"]) {
  width: 100%;
  padding: 0.75rem;
  background-color: var(--color-surface);
  border: 2px solid var(--color-outline);
  border-radius: var(--radius-xs);
  font-size: 1rem;
  color: var(--color-secondary);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.form-input:hover,
.auth-form input:not([type="checkbox"], [type="radio"], [type="hidden"]):hover {
  border-color: var(--color-outline-strong);
}

.form-input:focus,
.auth-form input:not([type="checkbox"], [type="radio"], [type="hidden"]):focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 15%, transparent);
}

.form-input::placeholder,
.auth-form input:not([type="checkbox"], [type="radio"], [type="hidden"])::placeholder {
  color: var(--color-outline-strong);
}

.form-input-sm {
  padding: 0.25rem 0.5rem;
  font-size: 0.8125rem;
  min-height: var(--field-height);
}

/* Datalist inputs (Type, Correspondent, Industry) – select caret */
.custom-field-inline .form-input[list] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%23C3CBD5'/%3E%3C/svg%3E");
  background-position: right 4px center;
  background-repeat: no-repeat;
  background-size: 16px;
  padding-right: 24px;
  cursor: pointer;
}

.custom-field-inline .form-input[list]:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%23546478'/%3E%3C/svg%3E");
}

[data-theme="dark"] .custom-field-inline .form-input[list] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%234B565E'/%3E%3C/svg%3E");
}

[data-theme="dark"] .custom-field-inline .form-input[list]:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7h10l-5 7-5-7z' fill='%23A6B0B5'/%3E%3C/svg%3E");
}

/* Custom field row */
.custom-field-inline {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

/* Custom field labels */
.custom-field-inline label {
  font-size: 0.75rem;
  color: var(--color-on-surface-variant) !important;
  font-weight: 500;
}
.field-missing .ts-control {
  border-color: var(--color-error) !important;
}

/* Storage path input minimum width */
.storage-path-group .form-input[name="storage_path"] { min-width: 150px; }

/* Storage path group */
.storage-path-group {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  padding: 0.5rem 0.75rem;
  background-color: var(--color-surface-alt);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
}

/* Document custom fields row */
/* Grid wrapper: aligns all field labels in col 1, all inputs in col 2 */
.fields-form {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.4rem 0.75rem;
  align-items: center;
  margin-top: 0.5rem;
}

/* Dissolve wrappers so their children become direct grid items */
.fields-form > .custom-field-inline,
.fields-form > .document-custom-fields,
.document-custom-fields > .custom-field-inline,
.document-custom-fields > .storage-path-group,
.storage-path-group > .custom-field-inline {
  display: contents;
}

.document-custom-fields {
  display: contents;
}

/* Tom Select field widths */
.ts-field { min-width: 120px; }
.ts-field-wide { min-width: 150px; }

/* Utility classes */
.text-center { text-align: center; }
.mt-1 { margin-top: 0.5rem; }
.mt-2 { margin-top: 1rem; }
.ms-auto { margin-left: auto; }
.mb-2 { margin-bottom: 1rem; }
.p-2 { padding: 1rem; }
.text-muted { color: var(--color-on-surface-variant); }
.text-primary { color: var(--color-primary); }
.text-warning { color: var(--color-warning); }
.text-success { color: var(--color-success); }
.text-secondary { color: var(--color-secondary); }
.text-danger { color: var(--color-error); }
.cursor-pointer { cursor: pointer; }
.d-none { display: none; }
.list-indent { padding-left: 1.2em; }

/* Side Menu */
.menu-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-scrim);
  z-index: var(--z-overlay);
}

.menu-overlay-enter { transition: opacity 0.25s ease; }
.menu-overlay-enter-start { opacity: 0; }
.menu-overlay-enter-end { opacity: 1; }
.menu-overlay-leave { transition: opacity 0.2s ease; }
.menu-overlay-leave-start { opacity: 1; }
.menu-overlay-leave-end { opacity: 0; }

.menu-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 280px;
  max-width: 80vw;
  background: var(--color-surface);
  z-index: var(--z-menu);
  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.menu-panel-enter { transition: transform 0.25s ease; }
.menu-panel-enter-start { transform: translateX(100%); }
.menu-panel-enter-end { transform: translateX(0); }
.menu-panel-leave { transition: transform 0.2s ease; }
.menu-panel-leave-start { transform: translateX(0); }
.menu-panel-leave-end { transform: translateX(100%); }

.menu-header {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.5rem;
  padding: 1rem;
  border-bottom: 1px solid var(--color-outline);
  background: var(--color-header-bg);
  color: var(--color-on-header);
}

.menu-header-username {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-section {
  padding: 0.5rem 0;
}

.menu-section-title {
  padding: 0.5rem 1rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-on-surface-muted);
}

.menu-item {
  display: block;
  width: 100%;
  padding: 0.75rem 1rem;
  color: var(--color-on-surface);
  text-decoration: none;
  font-size: 0.95rem;
  transition: background 0.15s;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}

.menu-item:hover {
  background: var(--color-surface-dim);
}

.menu-item[aria-current="page"] {
  color: var(--color-primary);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--color-primary);
}

.menu-item-logout {
  color: var(--color-primary);
  font-weight: 500;
}

.menu-divider {
  height: 1px;
  background: var(--color-outline);
  margin: 0;
}

/* Client switcher (impersonation) — lives inside the teal .menu-header */
.client-switcher {
  position: relative;
  flex: 1;
  min-width: 0;
}

.client-switcher-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font-family: inherit;
  font-size: 1rem;
  cursor: pointer;
  text-align: left;
}

.client-switcher-toggle strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.client-switcher-chevron {
  font-size: 0.7rem;
  transition: transform 0.15s;
}

.client-switcher-chevron.is-open {
  transform: rotate(180deg);
}

.badge-impersonating,
.badge-staff {
  flex-shrink: 0;
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-full);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.badge-impersonating {
  background: var(--color-warning);
}

.badge-staff {
  background: var(--color-success);
}

.client-switcher-dropdown {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  right: 0;
  z-index: 10;
  background: var(--color-surface);
  color: var(--color-on-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-3);
  padding: 0.25rem 0;
  max-height: 60vh;
  overflow-y: auto;
}

.client-switcher-dropdown form {
  margin: 0;
}

/* Header-hosted variant: hidden on mobile (the switcher lives in the slide-in
   menu there); shown ≥1024px where the hamburger menu is hidden. */
.client-switcher-header {
  display: none;
}

/* Impersonation banner — injected by hijack middleware before </body> */
.impersonation-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: var(--z-banner);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 1rem;
  padding-bottom: calc(0.6rem + env(safe-area-inset-bottom, 0px));
  background: var(--color-warning);
  color: #fff;
  box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.2);
}

.impersonation-banner-message {
  font-size: 0.9rem;
}

/* While the bottom nav is visible (<1024px), the banner sits above it instead
   of covering it. */
@media (max-width: 1023px) {
  .impersonation-banner {
    bottom: calc(70px + env(safe-area-inset-bottom, 0px));
    padding-bottom: 0.6rem;
  }
}

.impersonation-banner .btn {
  flex-shrink: 0;
  background: var(--color-surface);
  color: var(--color-secondary);
}

/* (.btn-danger lives with the other button variants in the Button section) */
.btn-flex { flex: 1; }

/* Main content bottom padding (above nav bar) */
.main-content {
  padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
}

/* Processing tasks block */
.processing-tasks { margin-bottom: 1rem; }
.processing-tasks-title { font-size: 0.875rem; color: var(--color-on-surface-variant); margin-bottom: 0.5rem; }
.processing-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem;
  /* Teal-tinted "in progress" surface (same tint family as .alert-success). */
  background: linear-gradient(90deg, var(--color-success-container) 0%, var(--color-surface) 100%);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
  margin-bottom: 0.5rem;
}
.processing-item-info { flex: 1; min-width: 0; }
.processing-item-name {
  font-size: 0.875rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.processing-item-status { font-size: 0.75rem; color: var(--color-on-surface-variant); }

/* Document expanded panel */
.document-expanded {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-outline);
}

.document-expanded-layout {
  display: flex;
  flex-direction: row;
  gap: 0;
  align-items: flex-start;
}

.resize-handle {
  flex: 0 0 20px;
  align-self: stretch;
  cursor: col-resize;
  position: relative;
  flex-shrink: 0;
}

.resize-handle::after {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 0;
  bottom: 0;
  width: 9px;
  background: var(--color-outline);
  border-radius: var(--radius-xs);
  transition: background 0.15s;
}

.resize-handle::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--color-on-surface-muted);
  box-shadow: 0 -12px var(--color-on-surface-muted), 0 -6px var(--color-on-surface-muted), 0 6px var(--color-on-surface-muted), 0 12px var(--color-on-surface-muted);
  z-index: 1;
}

.resize-handle:hover::after {
  background: var(--color-outline-strong);
}

.resize-handle:hover::before {
  background: var(--color-on-surface-variant);
  box-shadow: 0 -12px var(--color-on-surface-variant), 0 -6px var(--color-on-surface-variant), 0 6px var(--color-on-surface-variant), 0 12px var(--color-on-surface-variant);
}

.document-thumb-col {
  flex: 0 0 50%;
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-xs);
  overflow: hidden;
}

.document-thumb {
  width: 100%;
  height: auto;
  display: block;
}

.document-fields-col {
  flex: 1;
  min-width: 0;
}

/* Document action buttons row */
.document-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }


/* Inline SVG icon (1em × 1em) */
.icon-inline { display: inline-block; width: 1em; height: 1em; }

/* Document title input in fields card */
.use-proposed-title { font-size: 0.75rem; color: var(--color-error); cursor: pointer; background: none; border: none; padding: 0; text-align: left; }
.use-proposed-title:hover { text-decoration: underline; }

/* Field value – read-only display */
.field-separator { font-size: 0.75rem; color: var(--color-on-surface-muted); }
.field-value-static {
  font-size: 0.75rem;
  padding: 0.25rem 0.5rem;
  min-width: 250px;
  background-color: var(--color-surface-container);
  border-radius: var(--radius-xs);
  color: var(--color-on-surface-variant);
}

/* Resulting storage path: teal (same accent as the correspondent) to emphasize
   the computed destination. */
.field-value-static.resolved-path-value {
  color: var(--color-primary);
  font-weight: 600;
}

/* Date inputs */
.date-inputs-group {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-shrink: 0;
}

.date-input {
  font-size: 0.75rem;
  padding: 0.25rem;
  text-align: center;
  width: auto;
  flex-shrink: 0;
}
.date-input-year { width: 60px; }
.date-input-month { width: 90px; }
.date-input-day { width: 45px; }
.date-hint { font-size: 0.7rem; color: var(--color-on-surface-muted); white-space: nowrap; align-self: center; }

/* Document-date chip (meta row) + its inline edit popover. */
.document-date-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
  background: none;
  border: 0;
  /* Match the title's editable affordance: padded pill with negative margin so
     the resting layout is unchanged and hover/focus reveals the green highlight. */
  padding: 0.1rem 0.3rem;
  margin: -0.1rem -0.3rem;
  border-radius: var(--radius-xs);
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.document-date-trigger:hover,
.document-date-trigger:focus-visible {
  background-color: color-mix(in srgb, var(--color-primary) 8%, transparent);
  color: var(--color-primary);
  outline: none;
}
.document-date-popover {
  position: absolute;
  /* Anchor to the right: the meta row is right-aligned, so open leftward to stay on-screen. */
  right: 0;
  left: auto;
  top: calc(100% + 4px);
  z-index: 30;
  width: max-content;
  max-width: min(320px, 90vw);
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-2);
  padding: 0.6rem 0.7rem;
}
.document-date-popover .custom-field-inline { flex-direction: column; align-items: flex-start; gap: 0.35rem; }
.document-date-popover .date-inputs-group { flex-wrap: wrap; }
/* Reserve room on the right so the label never runs under the close button. */
.document-date-popover { padding-right: 2.2rem; }
.document-date-done {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
  color: var(--color-primary);
  cursor: pointer;
}
.document-date-done:hover,
.document-date-done:focus-visible {
  background: var(--color-primary);
  color: #fff;
  outline: none;
}

/* Pagination */
.pagination { display: flex; justify-content: center; gap: 1rem; margin-top: 1rem; }
.pagination-label { padding: 0.5rem; }

#load-more-control { height: 1px; width: 100%; }

/* Stats grid (2-column) */
.stats-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; }
.stat-box { text-align: center; padding: 1rem; background: var(--color-surface-alt); border-radius: var(--radius-sm); }
.stat-value { font-size: 2rem; font-weight: bold; }

/* Cloud sync stats */
.sync-stats { background: var(--color-surface-alt); padding: 1rem; border-radius: var(--radius-sm); margin-bottom: 1rem; }
.sync-stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; text-align: center; }
.sync-stat-value { font-size: 1.5rem; font-weight: bold; }
.sync-stat-label { font-size: 0.875rem; color: var(--color-on-surface-variant); }
.sync-last-updated { text-align: center; margin-top: 0.5rem; font-size: 0.875rem; color: var(--color-on-surface-variant); }

/* Connected state indicator */
.connected-status { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; }
.connected-checkmark { color: var(--color-success); font-size: 1.25rem; }

/* Form help text */
.form-help { color: var(--color-on-surface-variant); display: block; margin-top: 0.25rem; }
.form-error { color: var(--color-error); display: block; margin-top: 0.25rem; font-size: 0.85rem; }

@keyframes saved-flash {
  0%   { border-color: inherit; box-shadow: none; }
  25%  { border-color: var(--color-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success) 20%, transparent); }
  100% { border-color: inherit; box-shadow: none; }
}
.input-saved { animation: saved-flash 1.2s ease forwards; }

/* Action button row */
.action-row { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 1rem; }

/* Individual cloud provider block (kDrive, Dropbox, Google Drive, OneDrive) */
.cloud-provider-card {
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-md);
  padding: 1rem;
  margin-bottom: 1rem;
}
.cloud-provider-card:last-child { margin-bottom: 0; }
.cloud-provider-title { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; }

/* Theme picker (preferences page): System / Light / Dark segmented control. */
.theme-picker { display: flex; gap: 0.5rem; }
.theme-picker-option {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem 0.5rem;
  border: 2px solid var(--color-outline);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-on-surface-variant);
  font-size: 0.875rem;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.theme-picker-option:hover { border-color: var(--color-outline-strong); }
.theme-picker-option[aria-pressed="true"] {
  border-color: var(--color-primary);
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  font-weight: 600;
}

/* OAuth error banner */
.oauth-error {
  background: var(--color-error-container);
  border: 1px solid var(--color-error);
  padding: 0.75rem;
  border-radius: var(--radius-sm);
  margin-bottom: 1rem;
  color: var(--color-error);
}

/* Inline code display */
code.code-block {
  background: var(--color-surface-container);
  padding: 0.5rem;
  display: inline-block;
  border-radius: var(--radius-xs);
}

/* About page */
.about-logo { width: 80px; height: 80px; margin-bottom: 1rem; }
.about-title { font-size: 1.5rem; font-weight: 700; margin-bottom: 0.25rem; }
.about-tagline { color: var(--color-on-surface-variant); font-size: 0.9rem; margin-bottom: 1rem; }
.about-version { font-size: 1.75rem; font-weight: 700; color: var(--color-primary); }
.about-commit { font-size: 0.75rem; color: var(--color-on-surface-muted); margin-top: 0.25rem; }
.feedback-intro { font-size: 0.875rem; color: var(--color-on-surface-variant); margin-bottom: 0.75rem; }

/* FAQ page */
.faq-intro { font-size: 0.9rem; color: var(--color-on-surface-variant); margin-bottom: 1rem; }
.faq-item { border-top: 1px solid var(--color-outline); }
.faq-item:first-of-type { border-top: none; }
.faq-question {
  list-style: none;
  cursor: pointer;
  padding: 0.9rem 1.75rem 0.9rem 0;
  position: relative;
  font-weight: 600;
  color: var(--color-on-surface);
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question::after {
  content: "";
  position: absolute;
  right: 0.25rem;
  top: 50%;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--color-primary);
  border-bottom: 2px solid var(--color-primary);
  transform: translateY(-70%) rotate(45deg);
  transition: transform 0.2s ease;
}
.faq-item[open] .faq-question::after { transform: translateY(-30%) rotate(-135deg); }
.faq-answer { padding: 0 0 1rem; }
.faq-answer p { margin: 0 0 0.5rem; color: var(--color-on-surface-variant); font-size: 0.9rem; }
.faq-link {
  display: inline-block;
  margin-right: 1rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-primary);
}
.faq-link:hover { text-decoration: underline; }

/* eBanking QR carousel */
.qr-carousel-nav { display: flex; justify-content: center; align-items: center; gap: 1rem; margin-bottom: 1rem; }
.qr-counter { font-weight: 500; }
.qr-hint { text-align: center; font-size: 0.875rem; color: var(--color-on-surface-variant); margin-bottom: 1rem; }
.qr-slide { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
/* Square QR stage: 50vh, but never wider than the card on narrow phones. */
.qr-frame { width: min(50vh, 100%); aspect-ratio: 1 / 1; position: relative; margin: 0 auto; }
/* QR codes must stay on white in both themes (scanner contrast). */
.qr-frame canvas, .qr-frame img { background: #fff; }
.qr-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface-container);
  z-index: 1;
}
/* (.qr-spinner-inner lives with the other spinners in the Loading section) */
.qr-info { text-align: center; }

/* Desktop: two-column layout */
@media (min-width: 769px) {
  .qr-slide { flex-direction: row; align-items: center; gap: 2rem; }
  .qr-info { text-align: left; flex: 1; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; }
  .qr-frame { margin: 0 0 0 auto; }
  .qr-frame-wrapper { flex: 1; display: flex; justify-content: flex-end; }
}
.qr-amount { font-weight: bold; font-size: 1.75rem; color: var(--color-primary); }
.qr-parties { margin-top: 0.5rem; font-size: 1.125rem; color: var(--color-on-surface-variant); }
.qr-summary { margin-top: 0.5rem; font-size: 0.9rem; color: var(--color-on-surface-muted); font-style: italic; }
.qr-link { margin-top: 0.75rem; }
.qr-mark-paid { text-align: center; margin-top: 1rem; }

/* Document scanner */
.upload-card { margin-bottom: 1rem; }
.upload-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  border: 2px dashed var(--color-outline);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: center;
}
.upload-zone-icon { opacity: 0.5; margin-bottom: 1rem; }
.upload-zone-hint { margin: 0 0 0.5rem 0; }
.upload-zone-types { margin: 0; opacity: 0.6; font-size: 0.875rem; }
.upload-zone-hint-text { opacity: 0.6; margin-bottom: 1rem; }
.upload-zone-input { display: none; }
.preview-wrap { position: relative; border-radius: var(--radius-md); overflow: hidden; }
.preview-img { width: 100%; height: auto; display: block; }
.preview-pdf { width: 100%; height: 70vh; display: block; border: 0; }
.file-list { list-style: none; margin: 0; padding: 0; }
.file-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--color-outline);
}
.file-item:last-child { border-bottom: 0; }
.file-item-icon { display: flex; flex-shrink: 0; color: var(--color-on-surface-variant); }
/* min-width:0 lets the flex item shrink so a long filename ellipsises instead of
   pushing the remove button off the card. */
.file-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Not .btn-icon: that one is styled for the header bar (--color-on-header). */
.file-item-remove {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.25rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-on-surface-variant);
  cursor: pointer;
}
.file-item-remove:hover:not(:disabled) { color: var(--color-error); background: var(--color-surface-container); }
.file-item-remove:disabled { opacity: 0.5; cursor: default; }
.scan-actions { display: flex; gap: 0.5rem; margin-top: 1rem; }
.scan-loading { margin: 2rem 0; }
.scan-loading-text { margin-top: 1rem; }

/* Native barcode scanner: the camera renders behind the webview, so the page
   must become transparent while scanning (toggled by capacitor-bridge.js). */
body.scanner-active,
body.scanner-active .header,
body.scanner-active .nav-bottom {
  background: transparent !important;
}
body.scanner-active .main-content,
body.scanner-active .header,
body.scanner-active .nav-bottom {
  visibility: hidden;
}

/* Document detail */
.doc-info-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.3rem 0.75rem;
  align-items: baseline;
}
.doc-info-label { font-weight: 600; white-space: nowrap; }
.doc-info-mono { font-family: monospace; font-size: 0.85em; word-break: break-all; }
.doc-payment-box {
  margin-top: 0.5rem;
  padding: 0.75rem;
  background-color: var(--color-surface-alt);
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  /* IBANs and QR references are long unbroken strings; let them wrap. */
  overflow-wrap: anywhere;
}
.doc-text-content {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 0.8rem;
  font-family: monospace;
  line-height: 1.5;
  margin: 0;
  color: var(--color-on-surface);
}
.doc-viewer { width: 100%; height: 70vh; border: none; border-radius: var(--radius-sm); }
.doc-viewer-text { height: 50vh; font-family: monospace; background: var(--color-surface-container); }
.doc-viewer-image { width: 100%; height: auto; display: block; border-radius: var(--radius-sm); }
.doc-viewer-unsupported { padding: 2rem; text-align: center; color: var(--color-on-surface-muted); }
.doc-viewer-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; justify-content: center; }

/* Filter/tab rows */
.filter-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* Documents header: narrowed search + filter dropdown + Select + New, one row.
   Wraps only if the row genuinely doesn't fit (small screens). */
.documents-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.documents-search {
  flex: 1 1 auto;
  min-width: 0;
  margin-bottom: 0;
}

/* Wrapper for a search input with an inline clear ("x") button, so the user can
   empty the field without selecting the text first. */
.search-input-wrap {
  position: relative;
}
.search-input-wrap .form-input {
  padding-right: 2.2rem;
}
.search-clear-btn {
  position: absolute;
  top: 50%;
  right: 0.4rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-on-surface-variant);
  cursor: pointer;
}
.search-clear-btn:hover,
.search-clear-btn:focus-visible {
  background: color-mix(in srgb, var(--color-on-surface-variant) 12%, transparent);
  color: var(--color-on-surface);
  outline: none;
}
.search-clear-btn .icon { width: 1rem; height: 1rem; }

.documents-toolbar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  margin-left: auto;
}

/* Filter dropdown: same popover pattern as .client-switcher-dropdown, but anchored
   to (and sized by) its own trigger button instead of stretching full-width. */
.filter-dropdown {
  position: relative;
}

.filter-dropdown-toggle {
  white-space: nowrap;
}

.filter-dropdown-chevron {
  display: inline-flex;
  font-size: 0.7rem;
  transition: transform 0.15s;
}

.filter-dropdown-chevron.is-open {
  transform: rotate(180deg);
}

.filter-dropdown-menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  z-index: 10;
  min-width: 180px;
  background: var(--color-surface);
  color: var(--color-on-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-3);
  padding: 0.25rem 0;
  overflow: hidden; /* clip .menu-item's full-width hover background to the rounded corners */
}

.filter-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.filter-option-check {
  display: inline-flex;
  color: var(--color-primary);
}

/* Preferences section tabs: space the tab row above the visible card. */
.settings-tabs { margin-bottom: 1rem; }

/* QR carousel container: focused programmatically on load (x-init $el.focus())
   so arrow keys work immediately, which would otherwise paint the global
   :focus-visible ring around the whole card. The ring is useless here — the
   keydown handlers are window-level and the real controls (Prev/Next) keep
   their own focus rings. */
.qr-carousel:focus,
.qr-carousel:focus-visible { outline: none; }

/* Recent scans */
.recent-scans-list { display: flex; flex-direction: column; gap: 0.5rem; }
.recent-scan-link { text-decoration: none; color: inherit; }
.recent-scan-item { padding: 0.75rem; background: var(--color-surface-alt); border-radius: var(--radius-sm); font-size: 0.875rem; }
.recent-scan-date { color: var(--color-on-surface-variant); font-size: 0.75rem; }
.recent-scans-empty { color: var(--color-on-surface-variant); text-align: center; padding: 1rem; }

/* Auth pages (login, signup, signup closed) — shared with account/base_auth.html */
.auth-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: linear-gradient(135deg, var(--color-surface-dim) 0%, var(--color-surface-container) 100%);
}

.auth-card {
  background: var(--color-surface);
  border-radius: var(--radius-xl);
  padding: 2.5rem;
  width: 100%;
  max-width: 400px;
  box-shadow: var(--shadow-4);
}

.auth-logo {
  text-align: center;
  margin-bottom: 2rem;
}

.auth-logo img {
  height: 72px;
  width: auto;
}

.auth-logo h1 {
  color: var(--color-primary);
  font-size: 2.5rem;
  font-weight: 700;
  margin: 0;
}

.auth-logo p {
  color: var(--color-on-surface-variant);
  margin-top: 0.5rem;
  font-size: 0.95rem;
}

/* The bare element selectors paired with .form-group / .form-label / .form-input in the
   rules below exist because allauth renders the forms on its own pages (password reset,
   ...) as Django `as_p` markup - <p><label>..</label><input></p>, with no Charti class to
   hook onto. They give those pages the same fields as the hand-written login form. */
.auth-form .form-group,
.auth-form > p {
  margin-bottom: 1.25rem;
}

.auth-form .form-label,
.auth-form label {
  display: block;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--color-on-surface-variant);
  margin-bottom: 0.5rem;
}

.auth-form .form-input,
.auth-form input:not([type="checkbox"], [type="radio"], [type="hidden"]) {
  padding: 1rem;
  font-size: 1rem;
}

.auth-form .btn-primary {
  width: 100%;
  padding: 1rem;
  font-size: 1.1rem;
  margin-top: 0.5rem;
}

.auth-links {
  text-align: center;
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-outline);
}

.auth-links a {
  color: var(--color-primary);
  text-decoration: none;
  font-weight: 500;
}

.auth-links a:hover {
  text-decoration: underline;
}

.auth-links p {
  color: var(--color-on-surface-variant);
  font-size: 0.9rem;
  margin: 0;
}

.auth-links p + p {
  margin-top: 0.75rem;
}

.auth-card .alert {
  margin-bottom: 1.5rem;
}

.social-login {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-outline);
}

.social-login p {
  text-align: center;
  color: var(--color-on-surface-variant);
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

.social-login .btn {
  width: 100%;
  margin-bottom: 0.5rem;
}

/* Centered informational variant (signup closed, etc.) */
.auth-card-center { text-align: center; }
.auth-message-icon { color: var(--color-on-surface-muted); margin-bottom: 1rem; }
.auth-message-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
.auth-message-text { color: var(--color-on-surface-variant); font-size: 0.95rem; margin-bottom: 1.5rem; }

/* Responsive */
@media (max-width: 768px) {
  .container {
    padding: 0.5rem;
  }

  .card-inset {
    border: none;
    padding-left: 0;
    padding-right: 0;
  }

  .header {
    padding: 0.75rem;
    padding-top: calc(0.75rem + env(safe-area-inset-top, 0px));
  }

  .header h1 {
    font-size: 1.25rem;
  }

  /* The hamburger menu header already shows the username (or the client
     switcher); dropping it here gives the page title room to breathe. */
  .header-username {
    display: none;
  }

  /* Document row: the meta chips (QR/pages/dates) are wider than a phone
     screen, so they move to their own line under the title instead of
     crushing it to zero width and overflowing the card. */
  .document-title {
    flex-wrap: wrap;
    gap: 0.2rem 1rem;
  }

  .document-title-meta {
    width: 100%;
    justify-content: space-between;
    flex-wrap: wrap;
    white-space: normal;
    gap: 0.25rem 0.6rem;
    font-size: 0.75rem;
  }

  .document-title-meta > span {
    white-space: nowrap;
  }

  /* The date-edit popover is anchored to its chip, which can sit anywhere in
     the meta row; centered on the viewport it can never clip off-screen. */
  .document-date-popover {
    position: fixed;
    left: 50%;
    right: auto;
    top: 35%;
    transform: translate(-50%, -50%);
    max-width: calc(100vw - 2rem);
    box-shadow: var(--shadow-4);
  }

  .document-meta {
    flex-wrap: wrap;
    gap: 0.25rem 0.75rem;
  }

  /* Read-only field values may hold long paths; never force a fixed width. */
  .field-value-static {
    min-width: 0;
  }

  .filter-row .btn {
    padding: 0.4rem 0.75rem;
    font-size: 0.8125rem;
  }

  .documents-toolbar-actions .btn {
    padding: 0.4rem 0.75rem;
    font-size: 0.8125rem;
  }

  .documents-search {
    flex-basis: 160px;
  }

  .document-expanded-layout {
    flex-direction: column;
  }

  .document-thumb-col {
    flex: none !important;
    width: 100%;
  }

  .resize-handle {
    display: none;
  }
}

/* Touch devices: bump small controls toward the 48px comfortable target. */
@media (pointer: coarse) {
  .card-header .btn,
  .alert-dismiss,
  .btn-icon {
    min-width: 44px;
    min-height: 44px;
  }
  .date-input {
    min-height: 40px;
  }
  .nav-item {
    min-height: var(--touch-target);
  }
}

/* Desktop (≥1024px): persistent left sidebar replaces the bottom nav.
   IMPORTANT: .header/.nav-bottom class names are load-bearing — the
   visualViewport pinning code in capacitor-bridge.js selects them. */
@media (min-width: 1024px) {
  .nav-bottom {
    display: none;
  }

  .sidebar {
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--sidebar-width);
    background: var(--color-surface);
    border-right: 1px solid var(--color-outline);
    z-index: var(--z-nav);
    overflow-y: auto;
    padding-bottom: 1rem;
  }

  .sidebar-brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 1.25rem 1rem 1rem;
    font-family: var(--font-brand);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--color-primary);
    text-decoration: none;
  }

  .sidebar-brand img {
    height: 36px;
    width: auto;
  }

  .sidebar .menu-section-title {
    padding-top: 1rem;
  }

  .sidebar-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.65rem 1rem;
    margin: 0.1rem 0.5rem;
    border-radius: var(--radius-md);
    color: var(--color-on-surface);
    text-decoration: none;
    font-size: 0.95rem;
    transition: background 0.15s;
  }

  .sidebar-item:hover {
    background: color-mix(in srgb, var(--color-primary) 6%, transparent);
  }

  .sidebar-item.active,
  .sidebar-item[aria-current="page"] {
    background: var(--color-primary-container);
    color: var(--color-on-primary-container);
    font-weight: 600;
  }

  .sidebar-item svg {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
  }

  .sidebar-item-button {
    width: calc(100% - 1rem);
    border: none;
    background: none;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.95rem;
    text-align: left;
  }

  .sidebar-footer {
    margin-top: auto;
  }

  /* The sidebar covers every hamburger-menu destination, so the hamburger
     (and the slide-in menu behind it) disappears on desktop. The client
     switcher — its only unique content — moves into the header instead. */
  .header-menu-toggle {
    display: none;
  }

  .client-switcher-header {
    display: block;
    min-width: 0;
    max-width: 320px;
  }

  .client-switcher-header .client-switcher {
    flex: 0 1 auto;
  }

  .client-switcher-header .client-switcher-dropdown {
    left: auto;
    right: 0;
    min-width: 260px;
  }

  /* The switcher already shows the user's name — drop the duplicate. */
  .header-username-mobile {
    display: none;
  }

  /* Shift the app shell right of the sidebar. */
  .header {
    left: var(--sidebar-width);
  }

  .main-content {
    margin-left: var(--sidebar-width);
    padding-bottom: 2rem;
  }

  .impersonation-banner {
    left: var(--sidebar-width);
  }
}

/* Django debug toolbar: push below the status bar on mobile */
#djDebug #djDebugToolbar {
  top: env(safe-area-inset-top, 0px) !important;
}

/* Django debug toolbar: collapsed handle defaults to top-right, which overlaps
   the app's hamburger menu. Pin it to the bottom-right, above the bottom nav
   so it never covers the last nav tab. */
#djDebug #djDebugToolbarHandle {
  top: auto !important;
  bottom: calc(90px + env(safe-area-inset-bottom, 0px)) !important;
  transform: translateY(100%) rotate(90deg) !important;
  transform-origin: right top !important;
}

/* -------------------------------------------------------------------------
 * Storage path editor (preferences.html)
 * ------------------------------------------------------------------------- */
.storage-path-item {
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border-color, #e5e7eb);
}
.storage-path-item:first-child {
  border-top: 1px solid var(--border-color, #e5e7eb);
}
.storage-path-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
}
.storage-path-info code {
  word-break: break-all;
}
.storage-path-actions {
  display: flex;
  gap: 0.5rem;
  flex-shrink: 0;
}
.storage-path-add-title {
  margin: 0 0 0.5rem;
}
.storage-path-vars {
  margin: 0.25rem 0 0.75rem;
}
.storage-path-vars-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  cursor: pointer;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--primary-color);
}
.storage-path-vars-toggle:hover {
  text-decoration: underline;
}
.storage-path-vars-body {
  margin-top: 0.5rem;
  padding: 0.75rem;
  border: 1px solid var(--border-color, #e5e7eb);
  border-radius: 8px;
  background: var(--color-surface-variant, #f4f7f8);
}
.storage-path-vars-hint {
  font-size: 0.8125rem;
  margin: 0 0 0.5rem;
}
.storage-path-vars-hint:last-child {
  margin: 0.5rem 0 0;
}
.storage-path-vars-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem 1rem;
}
.storage-path-vars-group h5 {
  margin: 0 0 0.35rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-on-surface-muted);
}
.storage-path-vars-group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.storage-path-vars-group code {
  font-size: 0.75rem;
  white-space: nowrap;
}
