/*
 * LoveByPDF design tokens - "Ink & Seal" identity (replaces the earlier
 * dark-glassmorphism/violet-cyan pass). Grounded in what LoveByPDF actually
 * does: recovering documents - garbled legacy-encoded Hindi text, faded
 * scans, unreadable tables - back into clean, correct, usable text. The
 * palette reads as paper, ink, and an official document seal rather than
 * a generic "AI dev tool" glow:
 *   - ink: near-black warm plum-black, the "wet ink" dark tone (surfaces
 *     in dark mode, text in light mode)
 *   - parchment: warm paper off-white (light mode surface)
 *   - marigold: the primary accent - warm saffron, used for every call
 *     to action, same hue family as a festival marigold or an official
 *     stamp's ink
 *   - seal: a deep vermilion, used sparingly for the flagship ribbon and
 *     AI accents - a wax-seal red, not a danger red (--danger stays a
 *     distinct, brighter red so errors are never ambiguous)
 *   - verdigris: a muted teal-green for OCR/"restored text" moments and
 *     dropzone accents
 *   - gold: a slightly deeper antique-gold reserved for the credit
 *     wallet on the dashboard, so real money/credits read as a notch
 *     more premium than the everyday marigold accent
 * Cards are flat, opaque "paper" surfaces with a soft lifted-off-the-desk
 * shadow - no backdrop blur, no neon glow - and both themes share this one
 * token contract so every component below adapts automatically.
 */
:root {
  color-scheme: light;

  /* ---- Brand scale (same hue family in both themes) ---- */
  --violet: #A83B2C;         /* "seal" red - flagship ribbon, AI accents */
  --violet-deep: #7C2B20;
  --cyan: #2F8F7A;           /* "verdigris" - OCR/restore accents */
  --gold: #A9711E;          /* premium accent - light theme */
  --gold-bright: #C68A2C;
  --gold-tint: #FBF0DC;
  --gold-tint-border: #EFD9AC;

  /* ---- Light theme (default): warm parchment paper ---- */
  --primary: #241F33;        /* deep ink - "document" */
  --primary-dark: #150F1F;
  --primary-light: #D98A34;  /* marigold, mid-gradient */
  --accent: #E2963C;         /* marigold - primary brand accent */
  --accent-light: #2F8F7A;   /* verdigris */
  --ink: var(--primary);     /* brand-colored text sitting directly on --bg/--card */

  --bg: #F3EEE2;
  --bg-elevated: #FBF8F1;
  --card: #FBF8F1;
  --card-solid: #FBF8F1;
  --text: #211D2C;
  --text-muted: #6B6377;
  --border: rgba(33, 29, 44, 0.12);
  --border-strong: rgba(226, 150, 60, 0.45);

  --tint: rgba(226, 150, 60, 0.12);       /* soft brand-tinted pill/hover bg */
  --tint-border: rgba(226, 150, 60, 0.30);
  --tint-violet: rgba(168, 59, 44, 0.10);  /* AI-flavoured pill bg (seal-tinted) */
  --tint-violet-border: rgba(168, 59, 44, 0.28);
  --surface-soft: #F6F1E4;                /* file rows, chat bubbles */
  --track: #E8E0CE;                       /* progress bar track */
  --nav-bg: rgba(251, 248, 241, 0.82);
  --dropzone-bg: #F7F2E6;
  --dropzone-border: #6FA895;

  --success: #3F7A4F;
  --success-bg: #E9F3E9;
  --success-border: #C3DFC7;
  --warn: #A9660E;
  --warn-bg: #FBF0DC;
  --warn-border: #EAD09A;
  --danger: #C23B32;
  --danger-bg: #FBEAE7;
  --danger-border: #EFC3BC;

  --glass-blur: 0px;
  --radius: 14px;
  --shadow: 0 2px 10px rgba(33, 22, 12, 0.06);
  --shadow-lg: 0 18px 40px rgba(33, 22, 12, 0.12);
  /* Kept as a soft warm lift instead of a neon ring - hover states still
     pay off (buttons, tool cards, stat cards, the premium dropdown) but
     read as a card lifting off the desk, not a glowing screen. */
  --glow: 0 10px 26px rgba(226, 150, 60, 0.16);
  --glow-lg: 0 16px 38px rgba(226, 150, 60, 0.22);
  --ease: cubic-bezier(.22, 1, .36, 1);
  --font-heading: "Bricolage Grotesque", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
  --font-body: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
}

/* ---- Dark theme: applied when the toggle sets data-theme="dark" directly
   (explicit-dark block below), or - with no explicit choice stored - when
   the OS itself prefers dark (media-query block, guarded so an explicit
   data-theme="light" always wins). Same token names, different values, so
   every component using var(--x) repaints with zero extra CSS. ---- */
:root[data-theme="dark"] {
  color-scheme: dark;
  /* The two decoration tokens (see "Site graphics" at the end of this
     file): on ink, the ruled paper grid has to be a faint highlight
     rather than a faint shadow, or it is simply invisible. */
  --paper-line: rgba(255, 248, 235, 0.045);
  --paper-seal: rgba(198, 84, 63, 0.12);
  --violet: #C6543F;
  --violet-deep: #94392A;
  --cyan: #45B39E;
  --gold: #E8B85C;          /* premium accent - dark theme */
  --gold-bright: #F2CB84;
  --gold-tint: rgba(232, 184, 92, 0.14);
  --gold-tint-border: rgba(232, 184, 92, 0.34);

  --primary: #E2963C;
  --primary-dark: #0E0C16;
  --primary-light: #EFAE5C;
  --accent: #EFAE5C;
  --accent-light: #45B39E;
  --ink: #F0C68A;

  --bg: #16131F;
  --bg-elevated: #1E1A2A;
  --card: #1E1A2A;
  --card-solid: #1E1A2A;
  --text: #F3EFE6;
  --text-muted: #A9A1B5;
  --border: rgba(255, 255, 255, 0.09);
  --border-strong: rgba(239, 174, 92, 0.4);

  --tint: rgba(239, 174, 92, 0.14);
  --tint-border: rgba(239, 174, 92, 0.32);
  --tint-violet: rgba(198, 84, 63, 0.18);
  --tint-violet-border: rgba(198, 84, 63, 0.38);
  --surface-soft: rgba(255, 255, 255, 0.04);
  --track: rgba(255, 255, 255, 0.08);
  --nav-bg: rgba(22, 19, 31, 0.72);
  --dropzone-bg: rgba(255, 255, 255, 0.02);
  --dropzone-border: rgba(69, 179, 158, 0.45);

  --success: #6FBF80;
  --success-bg: rgba(111, 191, 128, 0.12);
  --success-border: rgba(111, 191, 128, 0.3);
  --warn: #E8B85C;
  --warn-bg: rgba(232, 184, 92, 0.12);
  --warn-border: rgba(232, 184, 92, 0.3);
  --danger: #E2685C;
  --danger-bg: rgba(226, 104, 92, 0.12);
  --danger-border: rgba(226, 104, 92, 0.3);

  --shadow: 0 4px 18px rgba(0, 0, 0, 0.32);
  --shadow-lg: 0 22px 55px rgba(0, 0, 0, 0.5);
  --glow: 0 10px 30px rgba(239, 174, 92, 0.14);
  --glow-lg: 0 16px 46px rgba(239, 174, 92, 0.2);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    /* Same two decoration tokens as the explicit dark block above. */
    --paper-line: rgba(255, 248, 235, 0.045);
    --paper-seal: rgba(198, 84, 63, 0.12);
    --violet: #C6543F;
    --violet-deep: #94392A;
    --cyan: #45B39E;

    --primary: #E2963C;
    --primary-dark: #0E0C16;
    --primary-light: #EFAE5C;
    --accent: #EFAE5C;
    --accent-light: #45B39E;
    --ink: #F0C68A;

    --bg: #16131F;
    --bg-elevated: #1E1A2A;
    --card: #1E1A2A;
    --card-solid: #1E1A2A;
    --text: #F3EFE6;
    --text-muted: #A9A1B5;
    --border: rgba(255, 255, 255, 0.09);
    --border-strong: rgba(239, 174, 92, 0.4);

    --tint: rgba(239, 174, 92, 0.14);
    --tint-border: rgba(239, 174, 92, 0.32);
    --tint-violet: rgba(198, 84, 63, 0.18);
    --tint-violet-border: rgba(198, 84, 63, 0.38);
    --surface-soft: rgba(255, 255, 255, 0.04);
    --track: rgba(255, 255, 255, 0.08);
    --nav-bg: rgba(22, 19, 31, 0.72);
    --dropzone-bg: rgba(255, 255, 255, 0.02);
    --dropzone-border: rgba(69, 179, 158, 0.45);

    --success: #6FBF80;
    --success-bg: rgba(111, 191, 128, 0.12);
    --success-border: rgba(111, 191, 128, 0.3);
    --warn: #E8B85C;
    --warn-bg: rgba(232, 184, 92, 0.12);
    --warn-border: rgba(232, 184, 92, 0.3);
    --danger: #E2685C;
    --danger-bg: rgba(226, 104, 92, 0.12);
    --danger-border: rgba(226, 104, 92, 0.3);

    --shadow: 0 4px 18px rgba(0, 0, 0, 0.32);
    --shadow-lg: 0 22px 55px rgba(0, 0, 0, 0.5);
    --glow: 0 10px 30px rgba(239, 174, 92, 0.14);
    --glow-lg: 0 16px 46px rgba(239, 174, 92, 0.2);
  }
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
.icon {
  display: inline-block;
  vertical-align: -0.2em;
  flex-shrink: 0;
  line-height: 1;
}
.icon-lg { width: 32px; height: 32px; }
.icon-xl { width: 48px; height: 48px; }
html { background: var(--bg); }
body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-x: hidden;
  transition: background 0.3s ease, color 0.3s ease;
}
h1, h2, h3, h4, h5, h6 { font-family: var(--font-heading); letter-spacing: -0.02em; }

/* ---- Shared glass-surface utility: every card-like block below opts in
   via this one class instead of repeating the blur/border trio. ---- */
.glass {
  background: var(--card);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%);
  backdrop-filter: blur(var(--glass-blur)) saturate(160%);
  border: 1px solid var(--border);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: var(--card-solid); }
}

/* ---------------------------------------------------------------- */
/* Ambient background: paper grain, not floating glass orbs         */
/* ---------------------------------------------------------------- */
.bg-orbs { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
/* A single, quiet warm wash - replaces three animated blurred orbs.
   Mostly static; the page itself (paper cards, ink type, the hero's own
   glyph-resolve moment) carries the motion budget instead. */
.bg-orb {
  position: absolute; border-radius: 50%; filter: blur(90px); opacity: 0.16;
}
.bg-orb.orb-1 { width: 620px; height: 620px; top: -220px; left: -160px; background: radial-gradient(circle, var(--accent), transparent 72%); }
.bg-orb.orb-2 { width: 520px; height: 520px; top: 30%; right: -220px; background: radial-gradient(circle, var(--cyan), transparent 72%); opacity: 0.1; }
.bg-orb.orb-3 { display: none; }
/* Subtle paper-grain texture over the whole page - the one texture cue
   that says "paper", used instead of glassmorphism blur. */
.bg-orbs::after {
  content: ""; position: absolute; inset: -10%; opacity: 0.5; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.13  0 0 0 0 0.11  0 0 0 0 0.08  0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] .bg-orbs::after { mix-blend-mode: overlay; opacity: 0.35; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .bg-orbs::after { mix-blend-mode: overlay; opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
  .reveal, .float, .hero-badge-ring, .btn-primary::after,
  .lx-scan, .lx-scan-line, .lx-page, .lx-cycle span, .lx-orb, .qt-rail a,
  .wallet-ring-glow, .wallet-card::before, .resolve-glyph { animation: none !important; transition: none !important; }
}

/* ---------------------------------------------------------------- */
/* Topbar / nav                                                      */
/* ---------------------------------------------------------------- */
.topbar {
  background: var(--nav-bg);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  color: var(--text);
  padding: 14px 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid var(--border);
  transition: background 0.3s ease, border-color 0.3s ease;
}
@keyframes gradientShift {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}
.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--text); }
.brand-mark {
  width: 42px; height: 42px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 14px rgba(0,0,0,0.18);
  transition: transform 0.35s var(--ease);
  overflow: hidden;
}
.brand-mark img { width: 100%; height: 100%; display: block; }
.brand:hover .brand-mark { transform: scale(1.08) rotate(-4deg); }
.brand-text h1 {
  margin: 0; font-size: 20px; font-weight: 700; letter-spacing: 0.01em;
  background: linear-gradient(100deg, var(--text), var(--accent) 60%, var(--violet));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.brand-text h1 span { font-weight: 400; opacity: 0.85; }

.nav { display: flex; align-items: center; gap: 18px; }
.nav a { position: relative; color: var(--text); text-decoration: none; font-size: 14px; font-weight: 600; opacity: 0.82; padding: 4px 0; transition: opacity 0.2s ease, color 0.2s ease; }
.nav a:not(.nav-cta):not(.nav-dd-link):not(.nav-dd-viewall)::after {
  content: ""; position: absolute; left: 0; bottom: -4px; width: 100%; height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--violet)); border-radius: 2px; transform: scaleX(0); transform-origin: right;
  transition: transform 0.28s var(--ease);
}
.nav a:not(.nav-cta):not(.nav-dd-link):not(.nav-dd-viewall):hover::after { transform: scaleX(1); transform-origin: left; }
.nav a:hover { opacity: 1; }
.nav-cta {
  background: var(--accent); color: var(--primary-dark) !important; padding: 9px 18px; border-radius: 3px 10px 3px 10px;
  font-weight: 800 !important; opacity: 1 !important; border: 1.5px solid var(--primary); box-shadow: 3px 3px 0 0 var(--primary);
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.nav-cta:hover { transform: translate(-2px, -2px); box-shadow: 5px 5px 0 0 var(--primary); }
.credits-pill {
  background: var(--tint); color: var(--ink); padding: 6px 14px; border-radius: 3px; font-size: 13px; font-weight: 700;
  font-family: var(--font-mono); border: 1px solid var(--tint-border); display: inline-flex; align-items: center; gap: 6px;
}
.nav-admin-link {
  background: var(--tint-violet); border: 1px solid var(--tint-violet-border); color: var(--violet) !important;
  padding: 6px 14px !important; border-radius: 3px; font-weight: 700 !important; opacity: 1 !important;
  display: inline-flex !important; align-items: center; gap: 6px;
}

/* --- Theme toggle --- */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--tint); color: var(--text);
  cursor: pointer; transition: transform 0.25s var(--ease), background 0.2s ease, border-color 0.2s ease;
  flex-shrink: 0;
}
.theme-toggle:hover { transform: translateY(-2px) rotate(-8deg); border-color: var(--border-strong); }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: inline-block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: none; }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: inline-block; }
}

/* --- Tools nav dropdown (hover on desktop, tap on touch) ---
   Rebuilt to fix a real, reproduced bug: at common laptop window
   widths (~1000px) the old single 560px-wide translucent panel,
   centered under the "Tools" word rather than the viewport, ran past
   the right edge of the screen; combined with a glassy see-through
   background, the hero heading/CTA button behind it "ghosted" through
   right where it overlapped ("shading and cutting from right side").
   Fixed three ways: (1) the panel is now fully opaque, so nothing
   behind it bleeds through, (2) a dedicated scrim dims the rest of the
   page while it's open (a deliberate effect instead of an accidental
   one), and (3) it's anchored so it can never run past the viewport
   edge, at any width. */
/* Deliberately NOT position:relative here - the panel below anchors to
   .topbar (position:sticky also establishes a containing block) instead
   of to this small nav-item, so `right:0` lines it up with the true
   right edge of the page for every window width, regardless of where
   the "Tools" trigger itself happens to sit in the nav row. Anchoring
   to the nav-item directly (its old behavior) is what let the panel run
   past the right edge of the viewport at in-between window widths. */
.nav-item.nav-dropdown { /* intentionally not positioned - see note above */ }
.nav-dropdown-trigger { display: inline-flex; align-items: center; gap: 4px; }
.nav-dropdown-trigger .caret { font-size: 11px; transition: transform 0.25s var(--ease); display: inline-block; }
.nav-dropdown:hover .nav-dropdown-trigger .caret,
.nav-dropdown.nav-dropdown-open .nav-dropdown-trigger .caret { transform: rotate(180deg); }

.nav-dropdown-scrim {
  position: fixed; inset: 0; z-index: 39; background: rgba(6, 8, 18, 0.4);
  opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.22s ease;
}
@media (hover: hover) {
  .nav-dropdown:hover .nav-dropdown-scrim,
  .nav-dropdown:focus-within .nav-dropdown-scrim { opacity: 1; visibility: visible; }
}
.nav-dropdown.nav-dropdown-open .nav-dropdown-scrim { opacity: 1; visibility: visible; }

.nav-dropdown-panel {
  position: absolute; top: calc(100% + 14px); right: 28px; left: auto;
  transform: translateY(8px);
  width: min(920px, calc(100vw - 60px));
  background: var(--card-solid); border-radius: 16px; box-shadow: var(--shadow-lg);
  border: 1px solid var(--border); padding: 16px; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px 18px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
  z-index: 60;
}
@media (hover: hover) {
  .nav-dropdown:hover .nav-dropdown-panel,
  .nav-dropdown:focus-within .nav-dropdown-panel {
    opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(0);
  }
}
.nav-dropdown.nav-dropdown-open .nav-dropdown-panel {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(0);
}
.nav-dd-col { min-width: 0; }
.nav-dd-col-title {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); margin: 4px 0 6px; padding: 0 10px;
}
.nav-dd-col-title-spaced { margin-top: 16px; }
.nav-dd-link {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 10px;
  color: var(--text) !important; font-weight: 600 !important; font-size: 13.5px; opacity: 1 !important;
  transition: background 0.18s ease;
}
.nav-dd-link:hover { background: var(--tint); }
.nav-dd-link-flagship { color: var(--ink) !important; background: var(--tint); margin-bottom: 4px; }
.nav-dd-icon { font-size: 18px; line-height: 1; display: inline-flex; color: var(--accent); flex-shrink: 0; }
.nav-dd-viewall {
  grid-column: 1 / -1; text-align: center; font-weight: 700 !important; color: var(--ink) !important;
  padding: 10px; border-radius: 10px; background: var(--bg); margin-top: 10px;
}
.nav-dd-viewall:hover { background: var(--tint); }

/* --- Mobile hamburger toggle --- */
.nav-toggle {
  display: none; flex-direction: column; justify-content: center; gap: 5px; width: 34px; height: 34px;
  background: var(--tint); border: 1px solid var(--tint-border); border-radius: 9px; cursor: pointer;
  padding: 0; align-items: center;
}
.nav-toggle span { display: block; width: 18px; height: 2px; background: var(--text); border-radius: 2px; transition: transform 0.25s var(--ease), opacity 0.2s ease; }
.nav-toggle.is-active span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-active span:nth-child(2) { opacity: 0; }
.nav-toggle.is-active span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav-toggle { display: flex; }
  .nav {
    display: none; width: 100%; flex-direction: column; align-items: stretch; gap: 4px;
    background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%);
    border: 1px solid var(--border);
    border-radius: 14px; padding: 12px; margin-top: 10px; order: 3;
  }
  .nav.nav-open { display: flex; animation: fadeInUp 0.25s var(--ease) both; }
  .nav a, .nav .credits-pill { width: 100%; }
  .nav-dropdown-scrim { display: none; }
  .nav-dropdown-panel {
    position: static; transform: none !important; width: 100%; grid-template-columns: 1fr; margin-top: 6px;
    opacity: 1; visibility: visible; pointer-events: none; max-height: 0; overflow: hidden; padding: 0;
    box-shadow: none; border: none; background: transparent;
  }
  .nav-dropdown.nav-dropdown-open .nav-dropdown-panel { pointer-events: auto; max-height: 900px; padding: 6px 0 0; }
  .nav-dd-col-title { padding-left: 4px; }
  .nav-dd-link, .nav-dd-link-flagship { background: var(--tint); margin-bottom: 4px; }
  .nav-dd-link:hover { background: var(--tint-violet); }
}

.container { flex: 1; width: 100%; max-width: 900px; margin: 0 auto; padding: 32px 20px 60px; position: relative; z-index: 1; }
/* Tool-heavy pages (hub, dashboard, pricing) get real breathing room on
   wide screens instead of cramming into the 900px reading-width column
   meant for text-heavy pages - that narrow column was also the reason
   the tools grid's last, partial row of cards read as an odd empty
   block on the right ("cutting from right side"): see .tools-grid. */
.container.container-wide { max-width: 1180px; }

.flash-stack { margin-bottom: 20px; }
.flash { padding: 12px 16px; border-radius: 10px; margin-bottom: 8px; font-size: 14px; animation: fadeInUp 0.4s var(--ease) both; }
.flash-success { background: var(--success-bg); color: var(--success); border: 1px solid var(--success-border); }
.flash-error { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }

/* ---------------------------------------------------------------- */
/* Entrance animations                                               */
/* ---------------------------------------------------------------- */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: translateY(0); }
}
/* Hidden-until-revealed state only applies when JS has run (html.js,
   set by an inline script in <head>) — with JS off or blocked, .reveal
   content is plain, fully visible content from the start. */
.js .reveal { opacity: 0; transform: translateY(18px); }
.reveal { transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ---------------------------------------------------------------- */
/* Hero (full-bleed banner)                                          */
/* ---------------------------------------------------------------- */
.hero-band {
  width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw;
  background: radial-gradient(120% 180% at 50% -20%, var(--tint) 0%, var(--bg) 60%);
  padding: 56px 20px 20px;
  overflow: hidden;
}
.hero { text-align: center; margin-bottom: 8px; padding: 20px 0; max-width: 720px; margin-left: auto; margin-right: auto; position: relative; }
.hero-eyebrow {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700; color: var(--ink);
  background: var(--tint); padding: 6px 14px; border-radius: 3px 10px 3px 10px; margin-bottom: 18px;
  letter-spacing: 0.04em; text-transform: uppercase; border: 1px solid var(--tint-border);
  font-family: var(--font-mono);
  animation: fadeInUp 0.6s var(--ease) both;
}
.hero h2 {
  font-size: clamp(30px, 5vw, 46px); margin: 0 0 14px; font-weight: 800; line-height: 1.15;
  animation: fadeInUp 0.6s var(--ease) both; animation-delay: 0.08s;
}
.hero h2 .grad-text {
  background: linear-gradient(100deg, var(--primary), var(--violet) 45%, var(--accent) 90%);
  background-size: 200% auto;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: gradientShift 6s ease infinite;
}
.hero p { color: var(--text-muted); margin: 0 auto 26px; max-width: 560px; font-size: 16.5px; animation: fadeInUp 0.6s var(--ease) both; animation-delay: 0.16s; }
.hero-cta { max-width: 320px; margin: 0 auto; animation: fadeInUp 0.6s var(--ease) both; animation-delay: 0.24s; }
.trust-row {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 20px;
  margin-top: 26px; font-size: 12.5px; color: var(--text-muted); font-weight: 600;
  animation: fadeInUp 0.6s var(--ease) both; animation-delay: 0.32s;
}
.trust-row span { background: var(--card); border: 1px solid var(--border); padding: 6px 12px; border-radius: 3px; font-size: 12px; }

.float { animation: floaty 5s ease-in-out infinite; }
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }

/* ---------------------------------------------------------------- */
/* Hero signature: a restored-document card (homepage only)         */
/* .hero-split is an additive modifier on .hero - every other page  */
/* using plain .hero (tools hub, pricing, ...) is untouched.         */
/* ---------------------------------------------------------------- */
.hero-split {
  display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 48px; align-items: center;
  max-width: 1080px; text-align: left; padding: 12px 0 8px;
}
.hero-split .hero-copy { max-width: 560px; }
.hero-split .hero-cta { margin: 0; }
.hero-split .trust-row { justify-content: flex-start; margin-left: 0; }
.hero-split p { margin-left: 0; margin-right: 0; }

.hero-doc-card {
  background: var(--card-solid); border: 1px solid var(--border); border-radius: 16px;
  padding: 28px 26px 24px; box-shadow: var(--shadow-lg); position: relative;
  transform: rotate(1.1deg); transition: transform 0.4s var(--ease);
}
.hero-doc:hover .hero-doc-card { transform: rotate(0deg) translateY(-3px); }
.hero-doc-card::before {
  content: ""; position: absolute; inset: 14px 18px; pointer-events: none; border-radius: 4px;
  background: repeating-linear-gradient(var(--card-solid) 0 26px, var(--border) 26px 27px);
  opacity: 0.6; z-index: 0;
}
/* The animated toolkit-showcase GIF supplies its own content (a document
   plus every tool cycling past it) - the ruled-notebook-line texture above
   was built for the old fake-typed-document mockup and just reads as
   visual noise stacked underneath a GIF that's already busy. */
.hero-doc-card--gif::before { display: none; }
.hero-doc-card--gif { padding: 14px; line-height: 0; }
.hero-doc-gif { display: block; width: 100%; height: auto; border-radius: 10px; }
.hero-doc-head { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 18px; position: relative; z-index: 1; }
.hero-doc-badge {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 800;
  color: var(--success); background: var(--success-bg); border: 1px solid var(--success-border);
  padding: 4px 11px; border-radius: 3px; letter-spacing: 0.02em; font-family: var(--font-mono); text-transform: uppercase; font-size: 10.5px;
}
.hero-doc-line {
  font-family: var(--font-mono); font-size: 14.5px; font-weight: 600; color: var(--text);
  margin: 0 0 14px; position: relative; z-index: 1; background: var(--card-solid); display: inline-block; padding-right: 6px;
}
.hero-doc-line-muted { color: var(--text-muted); font-weight: 500; font-size: 12.5px; }
.hero-doc-skel { height: 10px; border-radius: 4px; background: var(--track); margin: 16px 0; width: 100%; position: relative; z-index: 1; }
.hero-doc-skel.short { width: 58%; }
.hero-doc-caption { font-size: 12.5px; color: var(--text-muted); margin-top: 18px; line-height: 1.65; max-width: 380px; }
.hero-doc-caption code { background: var(--tint-violet); color: var(--violet); padding: 1px 6px; border-radius: 5px; font-family: var(--font-mono); font-size: 12px; }

/* Glyph-resolve: characters cycle through a "corrupted legacy font"
   glyph set before landing on the real word - dramatizes LoveByPDF's actual
   Kruti-Dev-style font recovery feature instead of a generic type-in
   effect. See static/js/animations.js. Falls back to plain final text
   when JS or reduced-motion is off - see the .hero-doc-line text itself. */
.resolve-glyph span { display: inline-block; }

@media (max-width: 900px) {
  .hero-split { grid-template-columns: 1fr; text-align: center; gap: 34px; }
  .hero-split .hero-copy { max-width: 560px; margin: 0 auto; }
  .hero-split .trust-row { justify-content: center; }
  .hero-split .hero-cta { margin: 0 auto; }
  .hero-doc-card { transform: none; max-width: 440px; margin: 0 auto; }
  .hero-doc-caption { max-width: 440px; margin-left: auto; margin-right: auto; }
}

.how-it-works { margin-top: 44px; text-align: center; }
.how-it-works h3 { font-size: 22px; margin-bottom: 22px; font-weight: 800; }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.step {
  background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px 18px; text-align: left;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.step:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg), var(--glow); border-color: var(--tint-border); }
.step-num {
  width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(120deg, var(--primary), var(--accent));
  color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; margin-bottom: 12px;
  box-shadow: 0 4px 12px rgba(37, 99, 235, 0.28);
}
.step p { margin: 0; font-size: 13.5px; color: var(--text-muted); line-height: 1.5; }
.step p strong { color: var(--text); }

.panel {
  background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border-radius: var(--radius); box-shadow: var(--shadow); padding: 28px;
  border: 1px solid var(--border); margin-bottom: 24px; animation: fadeInUp 0.5s var(--ease) both;
}
.panel-narrow { max-width: 420px; margin: 0 auto; }
.panel h2 { margin-top: 0; }

form label { display: block; font-size: 13px; font-weight: 600; margin: 14px 0 6px; color: var(--text-muted); }
form input, form select {
  width: 100%; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border); font-size: 14px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease; background: var(--card-solid); color: var(--text);
}
form input:focus, form select:focus {
  outline: none; border-color: var(--primary-light); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.18);
}
.form-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 480px) { .form-row-2 { grid-template-columns: 1fr; } }
.auth-switch { text-align: center; margin-top: 18px; font-size: 13.5px; color: var(--text-muted); }
.auth-fineprint { text-align: center; margin-top: 10px; font-size: 11.5px; color: var(--text-muted); }
.auth-fineprint a { color: var(--text-muted); }
.forgot-link { text-align: right; margin: -6px 0 0; font-size: 12.5px; }
.forgot-link a { color: var(--text-muted); }
.referral-note {
  background: var(--success-bg); color: var(--success); border: 1px solid var(--success-border);
  border-radius: 10px; padding: 10px 14px; font-size: 13px; margin-bottom: 16px; text-align: center;
}

.promo-form { display: flex; gap: 10px; margin-top: 14px; }
.promo-form input {
  flex: 1; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border); font-size: 13.5px;
  font-weight: 700; letter-spacing: 0.03em;
}
@media (max-width: 520px) { .promo-form { flex-direction: column; } }

.referral-panel h3 { margin-top: 0; }
.referral-link-row { display: flex; gap: 10px; margin-top: 14px; }
.referral-link-row input {
  flex: 1; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border);
  font-size: 13.5px; background: var(--bg); color: var(--text-muted);
}
.referral-link-row .btn { white-space: nowrap; }
@media (max-width: 520px) {
  .referral-link-row { flex-direction: column; }
}

/* ---------------------------------------------------------------- */
/* Buttons                                                            */
/* ---------------------------------------------------------------- */
/* Buttons: a stamped-ticket shape (asymmetric corners, hard offset ink
   shadow) instead of the rounded-pill + diagonal shine every AI-generated
   SaaS button uses - it presses flat on click like a real stamp, not a
   glowing screen element. */
.btn {
  border: 1.5px solid var(--primary); border-radius: 3px 12px 3px 12px;
  padding: 11px 22px; font-size: 14.5px; font-weight: 700; cursor: pointer;
  text-decoration: none; display: inline-block; position: relative;
  transition: transform 0.16s var(--ease), box-shadow 0.16s var(--ease), background 0.16s var(--ease);
}
.btn-primary {
  background: var(--accent); color: var(--primary-dark);
  box-shadow: 4px 4px 0 0 var(--primary);
}
.btn-primary:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 0 var(--primary); background: var(--primary-light); }
.btn-primary:active { transform: translate(1px, 1px); box-shadow: 2px 2px 0 0 var(--primary); }
.btn-large { width: 100%; padding: 14px; font-size: 15.5px; margin-top: 10px; text-align: center; }
.btn-ghost { background: transparent; color: var(--text); border: 1.5px solid var(--border); box-shadow: none; }
.btn-ghost:hover { border-color: var(--primary); background: var(--tint); transform: translate(-1px, -1px); }
.btn-ghost:active { transform: translate(0, 0); }

.features { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.feature {
  background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border: 1px solid var(--border); border-radius: 12px; padding: 18px 12px; text-align: center;
  font-size: 12.5px; color: var(--text-muted); transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.feature:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg), var(--glow); }
.feature span { display: block; font-size: 24px; margin-bottom: 8px; }

.dash-header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.dash-sub { color: var(--text-muted); font-size: 13.5px; }
.free-badge { color: var(--success); font-weight: 600; margin-left: 8px; }
.free-badge-used { color: var(--text-muted); margin-left: 8px; }
/* Shown for any account that's ever completed a real, paid credit
   purchase (see User.has_purchased_credits()) - distinct from the
   "Unlimited plan active" free-badge above, which is about a flat-rate
   subscription instead. Reuses pricing.html's own gold "premium accent"
   token (--gold/--gold-tint) rather than inventing a second one. */
.premium-badge {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700;
  color: var(--gold); background: var(--gold-tint); border: 1px solid var(--gold-tint-border);
  padding: 5px 12px; border-radius: 999px; letter-spacing: 0.01em;
}
.premium-badge svg { flex: none; width: 13px; height: 13px; }
.ocr-warning { background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-border); padding: 10px 14px; border-radius: 10px; font-size: 13px; margin-bottom: 16px; }

/* Template-first notice for bulk tools (Bulk Rename, Bulk Password
   Removal) - shown ABOVE the dropzone, before any files are chosen,
   because people need the blank Excel template (and its exact-filename
   requirement) in hand before they can usefully add PDFs at all. */
.template-note { background: var(--tint); border: 1px solid var(--tint-border); border-radius: var(--radius); padding: 16px 18px; margin-bottom: 20px; }
.template-note .tn-step { font-weight: 700; font-size: 13.5px; margin: 0 0 8px; color: var(--ink); }
.template-note p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.55; color: var(--text); }
.template-note p:last-child { margin-bottom: 0; }
.template-note .btn { margin: 4px 0 10px; }

.dropzone {
  border: 2px dashed var(--dropzone-border); border-radius: var(--radius); padding: 40px 20px; text-align: center; cursor: pointer;
  background: var(--dropzone-bg); transition: border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
}
.dropzone:hover { border-color: var(--primary-light); box-shadow: var(--glow); }
.dropzone.dragover { border-color: var(--primary); background: var(--tint); transform: scale(1.01); }
.dz-icon { font-size: 40px; margin-bottom: 8px; color: var(--accent); }
.dz-title { font-size: 16px; font-weight: 600; margin: 4px 0; }
.dz-sub { color: var(--text-muted); margin: 6px 0; font-size: 13px; }
.dz-hint { color: var(--text-muted); font-size: 12px; margin-top: 12px; }

.file-info { margin-top: 20px; }
.file-info-row { display: flex; align-items: center; gap: 14px; background: var(--surface-soft); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; }
.file-icon { font-size: 24px; color: var(--accent); }
.file-meta { flex: 1; min-width: 0; }
.file-name { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-sub { font-size: 12px; color: var(--text-muted); }

.progress-box { margin-top: 20px; }
.progress-header { display: flex; justify-content: space-between; font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.progress-bar-track { width: 100%; height: 12px; background: var(--track); border-radius: 999px; overflow: hidden; }
.progress-bar-fill {
  height: 100%; width: 0%; background: linear-gradient(90deg, var(--primary), var(--accent)); border-radius: 999px;
  transition: width 0.3s ease; background-size: 200% 100%; animation: gradientShift 2.5s linear infinite;
}
.progress-eta { margin-top: 8px; font-size: 12px; color: var(--text-muted); text-align: right; }

.result-box, .error-box { text-align: center; margin-top: 20px; padding: 26px 20px; border-radius: 12px; animation: fadeInUp 0.4s var(--ease) both; }
.result-box { background: var(--success-bg); border: 1px solid var(--success-border); }
.error-box { background: var(--danger-bg); border: 1px solid var(--danger-border); }
.result-icon { font-size: 36px; }
.result-box .result-icon { color: var(--success); }
.error-box .result-icon { color: var(--danger); }
.result-box h3 { color: var(--success); margin: 8px 0 14px; }
.error-box h3 { color: var(--danger); margin: 8px 0 4px; }
.error-box p { color: var(--text-muted); font-size: 13.5px; margin-bottom: 14px; }
.hidden { display: none !important; }

.jobs-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.jobs-table th, .jobs-table td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--border); }
.status-badge { padding: 3px 10px; border-radius: 3px; font-size: 11.5px; font-weight: 700; font-family: var(--font-mono); }
.status-done { background: var(--success-bg); color: var(--success); }
.status-error { background: var(--danger-bg); color: var(--danger); }
.status-pending { background: var(--tint); color: var(--accent); }
.status-converting, .status-starting { background: var(--tint); color: var(--ink); }

.pricing { text-align: center; }
.pricing-sub { color: var(--text-muted); margin-bottom: 24px; }
.pricing-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 32px; }
.price-card {
  background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px 16px;
  box-shadow: var(--shadow); transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease); position: relative;
}
.price-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg), var(--glow); }
.price-card.featured { border: 2px solid var(--primary); transform: scale(1.03); }
.price-card.featured:hover { transform: scale(1.03) translateY(-4px); }
.price-badge {
  position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: var(--primary); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: 0.03em; padding: 3px 12px; border-radius: 999px; box-shadow: var(--shadow);
}
.price-amount { font-size: 28px; font-weight: 800; color: var(--ink); }
/* The visitor's own-currency approximate conversion (see currency_display.py) -
   deliberately smaller/muted so the real ₹ charge above it stays the
   visually primary number on the card. */
.price-amount-local { color: var(--text-muted); font-size: 13px; margin-top: 1px; }
.price-credits { color: var(--text-muted); margin: 6px 0 4px; font-size: 14px; }
.price-per-credit { color: var(--text-muted); font-size: 11.5px; margin-bottom: 8px; font-family: var(--font-mono); }
/* Called out on every single card, not just once in the page footnote -
   credits are a wallet with an expiry, not a forever-yours purchase, and
   that's the one fact about a price a buyer shouldn't have to scroll past
   everything else on the page to find. See credit_expiry.py. */
.price-validity {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
  color: var(--gold); background: var(--gold-tint); border: 1px solid var(--gold-tint-border);
  padding: 3px 10px; border-radius: 999px; margin-bottom: 14px; letter-spacing: 0.01em;
}
.price-validity svg { flex: none; width: 12px; height: 12px; }
.tier-table { max-width: 400px; margin: 0 auto; text-align: left; }
.tier-table table { width: 100%; border-collapse: collapse; }
.tier-table th, .tier-table td { padding: 8px; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.pricing-footnote { margin-top: 20px; font-size: 12.5px; color: var(--text-muted); }

/* Order-summary + promo-code modal, opened after clicking Buy Now/
   Subscribe on any package (see static/js/pricing.js) instead of a
   single always-visible "have a coupon?" box sitting above every price
   card - each package gets its own promo-code prompt, in context, right
   before checkout. */
.purchase-modal-overlay {
  display: none; position: fixed; inset: 0; background: rgba(20, 14, 8, 0.55);
  align-items: center; justify-content: center; z-index: 1000; padding: 16px;
}
.purchase-modal-overlay.open { display: flex; }
.purchase-modal {
  background: var(--card-solid); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 30px 26px 26px; max-width: 380px; width: 100%;
  position: relative; text-align: left; animation: fadeInUp 0.25s var(--ease) both;
}
.purchase-modal h3 { margin: 0 0 16px; font-size: 18px; color: var(--ink); }
.purchase-modal-close {
  position: absolute; top: 12px; right: 14px; background: transparent; border: none; font-size: 24px;
  line-height: 1; cursor: pointer; color: var(--text-muted); padding: 4px;
}
.purchase-modal-close:hover { color: var(--text); }
.purchase-summary {
  background: var(--surface-soft); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; margin-bottom: 18px;
}
.purchase-summary-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 15px; font-weight: 700; color: var(--ink); }
.purchase-summary-detail { margin-top: 4px; font-size: 12.5px; color: var(--text-muted); }
.purchase-promo label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--text-muted); }
.purchase-promo input {
  width: 100%; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border); font-size: 13.5px;
  font-weight: 700; letter-spacing: 0.03em; background: var(--card-solid); color: var(--text);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.purchase-promo input:focus {
  outline: none; border-color: var(--primary-light); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.18);
}

/* --- Business & Enterprise page --- */
.enterprise-grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 24px; align-items: start; }
@media (max-width: 860px) { .enterprise-grid { grid-template-columns: 1fr; } }
.enterprise-points { list-style: none; padding: 0; margin: 18px 0 0; display: grid; gap: 12px; }
.enterprise-points li { display: flex; gap: 10px; align-items: flex-start; font-size: 14.5px; color: var(--text); }
.enterprise-points .pt-icon { color: var(--primary); flex-shrink: 0; margin-top: 1px; }
.enterprise-custom-card {
  border: 1px dashed var(--border); border-radius: var(--radius); padding: 20px; text-align: center; margin-top: 4px;
}
.enterprise-custom-card h4 { margin: 0 0 6px; }
.enterprise-custom-card p { color: var(--text-muted); font-size: 13.5px; margin: 0 0 14px; }
form textarea, form select {
  width: 100%; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border); font-size: 14px;
  font-family: inherit; background: var(--card-solid); color: var(--text); transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
form textarea:focus, form select:focus { outline: none; border-color: var(--primary-light); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.18); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 520px) { .field-row { grid-template-columns: 1fr; } }
.hp-field { position: absolute; left: -9999px; top: -9999px; }

.footer { text-align: center; padding: 26px 18px 30px; font-size: 12px; color: var(--text-muted); position: relative; z-index: 1; }
.footer-links { display: flex; justify-content: center; gap: 18px; margin-bottom: 10px; flex-wrap: wrap; }
.footer-links a { color: var(--text-muted); text-decoration: none; font-weight: 600; font-size: 12.5px; transition: color 0.2s ease; }
.footer-links a:hover { color: var(--ink); }

/* Social icon row (see base.html + site_content.get_social_links).
   Only rendered when an admin has switched it on and filled in at
   least one link, so these rules cost nothing until then. */
.footer-social { display: flex; flex-direction: column; align-items: center; gap: 8px; margin: 4px 0 14px; }
.footer-social-label { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); opacity: 0.8; }
.footer-social-icons { display: flex; justify-content: center; align-items: center; gap: 8px; flex-wrap: wrap; }
.footer-social-icons a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  color: var(--text-muted);
  background: rgba(127, 127, 127, 0.09);
  transition: color 0.2s ease, background-color 0.2s ease, transform 0.2s ease;
}
.footer-social-icons a:hover, .footer-social-icons a:focus-visible { transform: translateY(-2px); color: #fff; }

/* Each platform's own colour on hover only - the resting row stays one
   calm monochrome block (see the social_icon macro's note). Keyed off
   the data-social attribute so the palette lives here in CSS rather
   than being baked into each SVG. */
.footer-social-icons a[data-social="facebook"]:hover  { background: #1877F2; }
.footer-social-icons a[data-social="instagram"]:hover { background: linear-gradient(45deg, #F58529, #DD2A7B 55%, #8134AF); }
.footer-social-icons a[data-social="x"]:hover         { background: #000; }
.footer-social-icons a[data-social="youtube"]:hover   { background: #FF0000; }
.footer-social-icons a[data-social="linkedin"]:hover  { background: #0A66C2; }
.footer-social-icons a[data-social="whatsapp"]:hover  { background: #25D366; }
.footer-social-icons a[data-social="telegram"]:hover  { background: #229ED9; }
.footer-social-icons a[data-social="threads"]:hover   { background: #000; }
.footer-social-icons a[data-social="pinterest"]:hover { background: #E60023; }
.footer-social-icons a[data-social="reddit"]:hover    { background: #FF4500; }
.footer-social-icons a[data-social="tiktok"]:hover    { background: #010101; }

@media (prefers-reduced-motion: reduce) {
  .footer-social-icons a { transition: color 0.2s ease, background-color 0.2s ease; }
  .footer-social-icons a:hover, .footer-social-icons a:focus-visible { transform: none; }
}

.legal { max-width: 720px; margin: 0 auto; }
.legal h3 { margin-top: 28px; margin-bottom: 8px; font-size: 16px; }
.legal p, .legal li { color: var(--text); font-size: 14px; line-height: 1.7; }
.legal ul { padding-left: 20px; }
.legal-updated { color: var(--text-muted); font-size: 12.5px; margin-top: -8px; }
.legal-note { background: var(--bg); border: 1px dashed var(--border); border-radius: 10px; padding: 12px 14px; font-size: 13px; }

/* Blog post body - admin-authored raw HTML (see models.BlogPost), same
   trust model as .legal above but with heading levels h2-h4 (a post is
   more likely to be structured with real subheadings than a legal page)
   and image handling, since a post body can embed inline screenshots. */
.blog-post-body { max-width: 720px; font-size: 15px; line-height: 1.75; color: var(--text); }
.blog-post-body h2 { margin-top: 32px; margin-bottom: 10px; font-size: 22px; }
.blog-post-body h3 { margin-top: 26px; margin-bottom: 8px; font-size: 18px; }
.blog-post-body h4 { margin-top: 20px; margin-bottom: 6px; font-size: 15.5px; }
.blog-post-body p { margin: 0 0 16px; }
.blog-post-body ul, .blog-post-body ol { padding-left: 22px; margin: 0 0 16px; }
.blog-post-body li { margin-bottom: 6px; }
.blog-post-body img { max-width: 100%; border-radius: 10px; margin: 12px 0; }
.blog-post-body a { color: var(--primary); text-decoration: underline; }
.blog-post-body blockquote { border-left: 3px solid var(--primary-light); margin: 16px 0; padding: 4px 16px; color: var(--text-muted); }
.blog-post-body code { background: var(--surface-soft); padding: 2px 6px; border-radius: 5px; font-size: 13px; }

.error-page { text-align: center; }
.error-page .btn { margin-top: 10px; }

/* ---------------------------------------------------------------- */
/* Admin panel                                                        */
/* ---------------------------------------------------------------- */
.admin-tabs {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-bottom: 20px;
  background: var(--card); border: 1px solid var(--border); border-radius: 6px; padding: 6px; box-shadow: var(--shadow);
}
.admin-tabs a {
  padding: 9px 18px; border-radius: 3px; font-size: 13.5px; font-weight: 700; color: var(--text-muted);
  text-decoration: none; transition: background 0.2s ease, color 0.2s ease;
}
.admin-tabs a:hover { background: var(--bg); color: var(--text); }
.admin-tabs a.active { background: var(--primary); color: var(--bg-elevated); }
.admin-tabs-exit { margin-left: auto; color: var(--text-muted) !important; background: none !important; }

.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 20px; }
.stat-card {
  background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px 20px;
  box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 4px;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.stat-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg), var(--glow); }
.stat-label { font-size: 12px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.stat-value { font-size: 26px; font-weight: 800; background: linear-gradient(100deg, var(--primary), var(--violet)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.stat-note { font-size: 11.5px; color: var(--text-muted); }

.status-row { display: flex; flex-wrap: wrap; gap: 10px; }
.status-chip { padding: 8px 14px; border-radius: 3px; font-size: 13px; font-weight: 700; font-family: var(--font-mono); }
.status-chip-ok { background: var(--success-bg); color: var(--success); border: 1px solid var(--success-border); }
.status-chip-bad { background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-border); }
/* "Working, but on a fallback engine" - a real third state on the admin
   health panel, distinct from both "fine" and "broken". */
.status-chip-warn {
  background: var(--tint); color: var(--text);
  border: 1px solid var(--tint-border);
}

.admin-search-form { display: flex; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
.admin-search-form input, .admin-search-form select {
  padding: 10px 14px; border-radius: 9px; border: 1px solid var(--border); font-size: 13.5px; min-width: 220px;
  background: var(--card-solid); color: var(--text);
}
.admin-pagination { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 16px; }
.admin-row-actions { display: flex; gap: 6px; }
.admin-row-actions form { display: inline; }
.admin-row-actions .btn { padding: 6px 12px; font-size: 12px; }

.jobs-table code { background: var(--bg); padding: 2px 8px; border-radius: 6px; font-size: 12.5px; font-weight: 700; letter-spacing: 0.02em; }

/* Manage Tools (admin/tools.html, admin/tool_edit.html) + Site Content
   (admin/content.html) editors. */
.admin-tools-section-title { margin: 26px 0 8px; font-size: 14px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.admin-tools-section-title:first-of-type { margin-top: 6px; }
.admin-tools-table { margin-bottom: 8px; }
.tier-rows { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.tier-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13.5px; color: var(--text-muted); }
.tier-row input { margin: 0; }
.admin-content-slot { border: 1px solid var(--border); border-radius: 12px; padding: 16px; margin-bottom: 14px; }
.admin-content-slot h4 { margin: 0 0 8px; }
.admin-content-image-preview { display: flex; align-items: center; gap: 16px; margin-bottom: 10px; }
.admin-content-image-preview img { max-width: 160px; max-height: 90px; object-fit: contain; background: var(--surface-soft); border-radius: 8px; padding: 8px; }

@media (max-width: 720px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .stat-grid { grid-template-columns: 1fr; }
  .jobs-table { display: block; overflow-x: auto; white-space: nowrap; }
}

/* --- Tools hub --- */
.tools-section-title { font-size: 15px; font-weight: 800; margin: 30px 0 12px; color: var(--text); }
.tools-section-title:first-of-type { margin-top: 8px; }
/* Flexbox, not a fixed 3-column grid: a category with a count that
   isn't a multiple of the column count (5 tools, or just 1-2 in the
   "Edit & Protect" group) used to leave a glaring empty grid cell on
   the right of its last row. Flex-wrap with a capped basis just lets
   a short row end early instead - normal trailing whitespace, not a
   phantom card-shaped gap. */
.tools-grid { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 8px; }
.tool-card {
  background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 22px 20px; text-decoration: none; color: var(--text);
  display: flex; flex-direction: column; gap: 0; position: relative;
  flex: 1 1 250px; max-width: 320px;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), border-color 0.25s var(--ease);
}
.tool-card:hover { transform: translateY(-5px); border-color: var(--primary-light); box-shadow: var(--shadow-lg), var(--glow); }
.tool-card .tool-icon { font-size: 30px; margin-bottom: 10px; transition: transform 0.3s var(--ease); color: var(--accent); }
.tool-card:hover .tool-icon { transform: scale(1.15) rotate(-4deg); }
.tool-card h3 { margin: 0 0 6px; font-size: 16.5px; }
.tool-card p { margin: 0; color: var(--text-muted); font-size: 13px; line-height: 1.5; flex: 1; }
.tool-price {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 14px; margin-right: 6px; font-size: 11.5px; font-weight: 700; color: var(--ink);
  font-family: var(--font-mono); background: var(--tint); padding: 5px 11px; border-radius: 3px; align-self: flex-start;
}
.tool-price-free { color: var(--success); background: var(--success-bg); }
.tool-price-ai { color: var(--violet); background: var(--tint-violet); }
.tool-price-warn { color: var(--warn); background: var(--warn-bg); }
/* Same .tool-price pill as the hub cards, just surfaced again on a
   tool's own run page (hub.html's price_pill() equivalent lives in
   tool.html as price_badge()) so the cost is visible without a trip
   back to /tools first. */
.tool-page-price { margin: -6px 0 18px; }
.tool-page-price .tool-price { margin-top: 0; }
/* "People also use" cross-links at the bottom of a tool page (see
   templates/tools/tool.html) - small pill-style cards, deliberately
   lighter-weight than the full .tool-card grid on the Tools Hub since
   these are a secondary "you might also want" nudge, not the main
   navigation for finding a tool. */
.related-tools-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.related-tool-card {
  display: inline-flex; align-items: center; gap: 8px; padding: 10px 16px;
  background: var(--tint); border: 1px solid var(--border); border-radius: 999px;
  color: var(--text); text-decoration: none; font-size: 13.5px; font-weight: 600;
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease);
}
.related-tool-card:hover { transform: translateY(-2px); border-color: var(--primary-light); color: var(--primary); }
.tool-card-badge {
  position: absolute; top: -9px; right: 16px; background: var(--violet);
  color: #fff; font-size: 10px; font-weight: 800; padding: 4px 11px; border-radius: 3px;
  font-family: var(--font-mono); text-transform: uppercase; box-shadow: 2px 2px 0 0 var(--primary); letter-spacing: 0.05em;
}
/* Dog-ear fold on every tool card - each one reads as its own little
   document/page, not a generic feature card. The one recurring "paper"
   detail, kept off every other card type so it stays a signature rather
   than a tic. */
.tool-card::after {
  content: ""; position: absolute; top: 0; right: 0; width: 0; height: 0;
  border-style: solid; border-width: 0 15px 15px 0; border-color: transparent var(--bg) transparent transparent;
  border-radius: 0 var(--radius) 0 0; transition: border-width 0.25s var(--ease);
}
.tool-card:hover::after { border-width: 0 20px 20px 0; }
.tool-card-flagship { border-color: var(--tint-border); background: linear-gradient(165deg, var(--card) 60%, var(--tint)); }
.tool-card-ai { border-color: var(--tint-violet-border); }
.tool-card-ai .tool-icon { filter: saturate(1.1); }

/* --- Generic tool page (upload + options + file list) --- */
.file-list { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.file-list-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--surface-soft); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 14px; font-size: 13.5px;
}
.file-remove-btn { padding: 4px 10px; font-size: 12px; border-radius: 8px; }

.tool-options { margin: 6px 0 18px; }
.tool-options label { display: block; font-size: 13px; font-weight: 600; margin: 14px 0 6px; color: var(--text-muted); }
.tool-options select, .tool-options input[type="text"] {
  width: 100%; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border); font-size: 14px;
  font-family: inherit; background: var(--card-solid); color: var(--text);
}
.tool-options .dz-hint { margin-top: 8px; }

/* --- Searchable PDF: document-language picker (see templates/tools/tool.html) --- */
.ocr-lang-checks { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.ocr-lang-check {
  display: flex !important; align-items: center; gap: 6px; font-size: 13px !important;
  font-weight: 500 !important; color: var(--text) !important; margin: 0 !important; cursor: pointer;
}
.ocr-lang-check input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.ocr-lang-check input[disabled] { cursor: default; opacity: 0.7; }

/* --- Reorder Pages: draggable thumbnail grid (static/js/reorder.js) --- */
.reorder-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 14px;
  margin: 10px 0 4px; padding: 4px; min-height: 40px;
}
.reorder-thumb {
  position: relative; display: flex; flex-direction: column; align-items: center;
  background: var(--card-solid); border: 1.5px solid var(--border); border-radius: 10px;
  padding: 8px; cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none;
  box-shadow: var(--shadow); transition: box-shadow 0.2s ease, border-color 0.2s ease;
}
.reorder-thumb:hover { border-color: var(--border-strong); }
.reorder-thumb canvas { max-width: 100%; height: auto; border-radius: 5px; display: block; pointer-events: none; box-shadow: 0 1px 4px rgba(0,0,0,0.15); }
.reorder-thumb.dragging {
  cursor: grabbing; z-index: 20; box-shadow: var(--shadow-lg); border-color: var(--accent);
  transition: none; opacity: 0.92;
}
.reorder-grid-active .reorder-thumb:not(.dragging) { transition: transform 0.15s ease; }
.reorder-thumb-num {
  margin-top: 6px; font-size: 12px; font-weight: 700; color: var(--ink);
  background: var(--tint); border-radius: 999px; padding: 2px 10px; line-height: 1.4;
}
.reorder-thumb-num[title] { cursor: help; }

/* Manual "type the order" field, e.g. "4,2,3,2,1" - an alternative to
   drag-and-drop that writes to the same #reorderOrderInput. */
.reorder-manual-row { display: flex; gap: 10px; align-items: center; }
.reorder-manual-row input[type="text"] {
  flex: 1; padding: 11px 14px; border-radius: 9px; border: 1px solid var(--border);
  font-size: 14px; font-family: inherit; background: var(--card-solid); color: var(--text);
}
.reorder-manual-error { color: #d64545; }

/* Click-a-thumbnail preview lightbox, reusing .pe-modal* (see pdf_edit.css) */
.reorder-preview-body { display: flex; align-items: center; justify-content: center; padding: 6px 0; }
.reorder-preview-body canvas {
  max-width: 100%; max-height: 70vh; border-radius: 6px; box-shadow: 0 2px 10px rgba(0,0,0,0.18);
}

/* ===================== Premium Select (custom dropdown) =====================
   Progressively enhanced by static/js/premium-select.js on every <select>
   site-wide - the plain native dropdown the "make this attractive" request
   called out becomes this glass-panel trigger + animated option list. The
   real <select> (still driving name/value/change for every existing
   script) sits underneath, invisible and out of the tab order. */
.pselect { position: relative; }
.pselect-native { position: absolute !important; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: none; }
.pselect-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 16px; border-radius: 11px; border: 1.5px solid var(--border);
  background: var(--card-solid); color: var(--text); font-family: inherit; font-size: 14.5px; font-weight: 600;
  cursor: pointer; text-align: left; transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.pselect-trigger:hover { border-color: var(--border-strong); }
.pselect-trigger:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--tint); }
.pselect.open .pselect-trigger { border-color: var(--accent); box-shadow: 0 0 0 4px var(--tint), var(--glow); }
.pselect-trigger:disabled { opacity: 0.55; cursor: not-allowed; }
.pselect-trigger-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pselect-chevron { display: inline-flex; color: var(--accent); flex-shrink: 0; transition: transform 0.25s var(--ease); }
.pselect.open .pselect-chevron { transform: rotate(180deg); }

.pselect-panel {
  position: absolute; left: 0; right: 0; top: calc(100% + 8px); z-index: 40;
  background: var(--card-solid); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-lg); padding: 6px; max-height: 260px; overflow-y: auto;
  opacity: 0; transform: translateY(-6px) scale(0.98); pointer-events: none;
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease);
}
.pselect.open .pselect-panel { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
.pselect-option {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 8px;
  font-size: 14px; color: var(--text); cursor: pointer; transition: background 0.15s ease;
}
.pselect-option:hover { background: var(--tint); }
.pselect-option.active { color: var(--accent); font-weight: 700; background: var(--tint); }
.pselect-check { width: 14px; height: 14px; flex-shrink: 0; color: var(--accent); opacity: 0; transition: opacity 0.15s ease; }
.pselect-option.active .pselect-check { opacity: 1; }

/* --- AI Chat --- */
.chat-log {
  display: flex; flex-direction: column; gap: 10px; max-height: 420px; overflow-y: auto;
  padding: 16px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  margin-bottom: 14px;
}
.chat-msg { max-width: 78%; padding: 10px 14px; border-radius: 14px; font-size: 14px; line-height: 1.5; white-space: pre-wrap; animation: fadeInUp 0.3s var(--ease) both; }
.chat-msg.chat-user {
  align-self: flex-end; background: linear-gradient(120deg, var(--primary), var(--primary-light));
  color: #fff; border-bottom-right-radius: 4px;
}
.chat-msg.chat-model {
  align-self: flex-start; background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border: 1px solid var(--border);
  color: var(--text); border-bottom-left-radius: 4px;
}
.chat-input-row { display: flex; gap: 10px; }
.chat-input-row input {
  flex: 1; padding: 12px 16px; border-radius: 999px; border: 1px solid var(--border); font-size: 14px;
  font-family: inherit; background: var(--card-solid); color: var(--text);
}
.chat-input-row button { border-radius: 999px; }

/* ---------------------------------------------------------------- */
/* Auth split-screen (login / signup) — the "wow" pages              */
/* ---------------------------------------------------------------- */
.auth-shell {
  width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw;
  min-height: calc(100vh - 200px);
  display: grid; grid-template-columns: 1.05fr 1fr; align-items: stretch;
}
.auth-visual {
  background: linear-gradient(150deg, var(--primary-dark) 0%, var(--primary) 45%, var(--violet) 78%, var(--accent) 130%);
  background-size: 220% 220%; animation: gradientShift 14s ease infinite;
  color: #fff; padding: 60px 52px; display: flex; flex-direction: column; justify-content: center;
  position: relative; overflow: hidden;
}
.auth-visual::before, .auth-visual::after {
  content: ""; position: absolute; border-radius: 50%; filter: blur(50px);
}
.auth-visual::before { width: 260px; height: 260px; background: rgba(255,255,255,0.16); top: -60px; right: -60px; animation: orbFloat 18s ease-in-out infinite; }
.auth-visual::after { width: 220px; height: 220px; background: rgba(6,182,212,0.35); bottom: -70px; left: -40px; animation: orbFloat 20s ease-in-out infinite reverse; }
.auth-visual-inner { position: relative; z-index: 1; max-width: 400px; }
.auth-visual-logo { display: flex; align-items: center; gap: 12px; margin-bottom: 40px; }
.auth-visual-logo img { width: 44px; height: 44px; border-radius: 12px; box-shadow: 0 6px 18px rgba(0,0,0,0.25); }
.auth-visual-logo span { font-size: 21px; font-weight: 800; letter-spacing: 0.02em; }
.auth-visual h2 { font-size: 30px; font-weight: 800; line-height: 1.25; margin: 0 0 16px; }
.auth-visual p { font-size: 15px; opacity: 0.88; line-height: 1.6; margin: 0 0 28px; }
.auth-visual-points { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.auth-visual-points li { display: flex; align-items: center; gap: 12px; font-size: 14px; font-weight: 600; opacity: 0.95; }
.auth-visual-points .pt-icon {
  width: 30px; height: 30px; border-radius: 9px; background: rgba(255,255,255,0.18);
  border: 1px solid rgba(255,255,255,0.3); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;
}
.auth-visual-doc {
  position: absolute; right: -30px; bottom: -20px; width: 220px; opacity: 0.9;
}

.auth-form-side { display: flex; align-items: center; justify-content: center; padding: 40px 24px; background: var(--bg); }
.auth-card {
  width: 100%; max-width: 380px; background: var(--card); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%); backdrop-filter: blur(var(--glass-blur)) saturate(160%); border-radius: 20px; box-shadow: var(--shadow-lg);
  border: 1px solid var(--border); padding: 40px 34px; animation: fadeInUp 0.6s var(--ease) both;
}
.auth-card h2 { margin: 0 0 6px; font-size: 24px; font-weight: 800; }
.auth-card .auth-sub { color: var(--text-muted); font-size: 13.5px; margin: 0 0 22px; }

/* --- Icon-adorned inputs (login/signup/reset) --- */
.input-icon-group { position: relative; display: flex; align-items: center; }
.input-icon-group input {
  padding-left: 40px !important;
}
.input-icon-group .input-icon {
  position: absolute; left: 13px; font-size: 15px; opacity: 0.75; pointer-events: none;
}
.input-icon-group .input-toggle-btn {
  position: absolute; right: 6px; background: none; border: none; cursor: pointer;
  font-size: 15px; padding: 6px 8px; border-radius: 8px; opacity: 0.6; transition: opacity 0.2s ease, background 0.2s ease;
}
.input-icon-group .input-toggle-btn:hover { opacity: 1; background: var(--bg); }
.input-icon-group input:focus + .input-toggle-btn,
.input-icon-group .input-toggle-btn:hover { opacity: 1; }

@media (max-width: 900px) {
  .auth-shell { grid-template-columns: 1fr; min-height: auto; }
  .auth-visual { padding: 44px 28px; text-align: center; align-items: center; }
  .auth-visual-inner { max-width: 480px; }
  .auth-visual-logo { justify-content: center; }
  .auth-visual-points { align-items: center; }
  .auth-visual-points li { flex-direction: column; gap: 6px; }
  .auth-visual-doc { display: none; }
  .auth-form-side { padding: 36px 20px 48px; }
}

@media (max-width: 720px) {
  .features { grid-template-columns: repeat(2, 1fr); }
  .pricing-grid { grid-template-columns: repeat(2, 1fr); }
  .price-card.featured { transform: none; }
  .steps { grid-template-columns: 1fr; }
  .tool-card { flex-basis: 100%; max-width: none; }
  .chat-msg { max-width: 90%; }
}

/* ===================== Announcement/discount popup (admin-controlled,
   see /admin/content -> "Announcement Popup") ===================== */
.site-popup-overlay {
  position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(15, 15, 20, 0.55); backdrop-filter: blur(2px);
}
.site-popup-overlay[hidden] { display: none; }
.site-popup {
  position: relative; width: 100%; max-width: 420px; background: var(--bg-elevated, #fff);
  color: var(--text, #16151a); border-radius: 16px; padding: 32px 28px 28px; text-align: center;
  box-shadow: 0 24px 60px rgba(0,0,0,0.35); animation: sitePopupIn .25s ease;
}
@keyframes sitePopupIn { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.site-popup h3 { margin: 0 0 10px; font-size: 21px; }
.site-popup p { margin: 0 0 20px; color: var(--text-muted, #666); font-size: 14.5px; line-height: 1.5; }
.site-popup .btn { width: 100%; }
.site-popup-close {
  position: absolute; top: 10px; right: 14px; border: none; background: none; cursor: pointer;
  font-size: 26px; line-height: 1; color: var(--text-muted, #888); padding: 4px 8px;
}
.site-popup-close:hover { color: var(--text, #16151a); }
.site-popup-image {
  display: block; width: 100%; max-height: 180px; object-fit: cover; border-radius: 10px; margin-bottom: 16px;
}
/* An announcement that IS the picture - no title, no message, just a
   banner or offer graphic with its words already in the artwork. Cropping
   that to a 180px letterbox would cut the message in half, so it gets
   shown whole (capped against the viewport so a tall graphic still fits
   on a phone) and the dialog's own padding gets out of its way. */
.site-popup-image-only {
  max-height: min(70vh, 620px); object-fit: contain; margin-bottom: 0;
}
.site-popup:has(> .site-popup-image-only) { padding: 14px; }
.site-popup:has(> .site-popup-image-only) .btn { margin-top: 14px; }
.site-popup-countdown {
  display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 700;
  color: var(--gold); background: var(--gold-tint); border: 1px solid var(--gold-tint-border);
  padding: 4px 12px; border-radius: 999px; margin: -10px 0 18px; letter-spacing: 0.01em;
}

/* ===================== In-house help-bot widget (admin-controlled, see
   /admin/content -> "Help Bot") - a floating button + slide-up panel,
   built entirely in-house rather than a third-party embed. ===================== */
.help-bot { position: fixed; right: 20px; bottom: 20px; z-index: 998; }
.help-bot-toggle {
  width: 54px; height: 54px; border-radius: 50%; border: 1.5px solid var(--primary);
  background: var(--accent); color: var(--primary-dark); box-shadow: var(--shadow-lg);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.help-bot-toggle:hover { transform: translateY(-2px); box-shadow: 0 20px 45px rgba(33, 22, 12, 0.2); }
.help-bot.open .help-bot-toggle { transform: scale(0.94); }
.help-bot-panel {
  position: absolute; right: 0; bottom: 68px; width: 320px; max-width: calc(100vw - 40px);
  max-height: min(70vh, 520px); display: flex; flex-direction: column;
  background: var(--card-solid); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 18px 18px 14px; animation: fadeInUp 0.2s var(--ease) both;
}
.help-bot-panel[hidden] { display: none; }
.help-bot-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.help-bot-header h4 { margin: 0; font-size: 16px; color: var(--ink); }
.help-bot-close {
  background: transparent; border: none; font-size: 22px; line-height: 1; cursor: pointer;
  color: var(--text-muted); padding: 0 2px;
}
.help-bot-close:hover { color: var(--text); }
.help-bot-greeting { margin: 8px 0 12px; font-size: 13px; color: var(--text-muted); line-height: 1.5; }
.help-bot-search {
  width: 100%; padding: 10px 12px; border-radius: 9px; border: 1px solid var(--border); font-size: 13.5px;
  background: var(--card-solid); color: var(--text); margin-bottom: 10px;
}
.help-bot-search:focus { outline: none; border-color: var(--primary-light); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.18); }
.help-bot-results { overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.help-bot-item {
  border: 1px solid var(--border); border-radius: 8px; padding: 2px 12px; background: var(--surface-soft);
}
.help-bot-item summary { cursor: pointer; list-style: none; padding: 9px 0; font-weight: 600; font-size: 13px; }
.help-bot-item summary::-webkit-details-marker { display: none; }
.help-bot-item p { margin: 0 0 10px; font-size: 12.5px; color: var(--text-muted); line-height: 1.5; }
.help-bot-empty { font-size: 12.5px; color: var(--text-muted); text-align: center; padding: 10px 0; }
.help-bot-footer { margin: 0; font-size: 11.5px; color: var(--text-muted); text-align: center; border-top: 1px solid var(--border); padding-top: 10px; }
@media (max-width: 480px) {
  .help-bot { right: 14px; bottom: 14px; }
  .help-bot-panel { right: -6px; }
}

/* === FAQ accordion (/help - see pages.py's FAQ_ITEMS) =====================
   Plain <details>/<summary> - a real click-to-expand accordion with no
   JS needed at all, natively keyboard/screen-reader accessible. */
.faq-list { display: flex; flex-direction: column; gap: 10px; margin: 20px 0; }
.faq-item {
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
  padding: 4px 18px; transition: border-color 0.2s ease;
}
.faq-item[open] { border-color: var(--border-strong); }
.faq-question {
  cursor: pointer; list-style: none; padding: 14px 28px 14px 0; font-weight: 700;
  font-size: 15px; position: relative; user-select: none;
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question::after {
  content: "+"; position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  font-size: 20px; font-weight: 400; color: var(--text-muted); transition: transform 0.2s ease;
}
.faq-item[open] .faq-question::after { content: "−"; }
.faq-answer { margin: 0 0 16px; color: var(--text-muted); font-size: 14px; line-height: 1.6; }
.faq-contact-cta {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px;
  margin-top: 24px; padding: 18px 20px; border-radius: 10px; background: var(--tint); border: 1px solid var(--tint-border);
}

/* ---------------------------------------------------------------------
   Ad slots (see ads.py). The container is styled, never the ad itself -
   an ad network's own script controls what goes inside, and touching it
   is usually against their terms.

   Two things this does deliberately:
     * `min-height: 0` and no fixed size. A slot with nothing in it takes
       up no space at all, so a page on a site with no ad code looks
       exactly as it did before ads existed.
     * `overflow: hidden` plus max-width. A misbehaving ad creative
       cannot push the page wider than the phone screen, which is the
       single most common way ads wreck a mobile layout.
   --------------------------------------------------------------------- */
.ad-slot {
  max-width: 100%; overflow: hidden; margin: 0 auto;
  display: flex; justify-content: center;
}
.ad-slot:empty { display: none; }
.ad-slot-top { margin-bottom: 18px; }
.ad-slot-bottom { margin-top: 26px; }
.ad-slot-article { margin: 28px 0; }
/* A quiet, honest label so a reader can tell paid content from ours -
   required by several ad networks and simply the right thing to do. */
.ad-slot::before {
  content: "Advertisement";
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
}

/* ---------------------------------------------------------------------
   Notification bell (see static/js/notifications.js and notifications.py)
   --------------------------------------------------------------------- */
.notif-wrap { position: relative; display: inline-flex; }
.notif-bell {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; border-radius: 10px;
  background: transparent; border: 1px solid transparent; color: inherit; cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.notif-bell:hover { background: var(--surface-soft); border-color: var(--border); }
.notif-bell.has-unread { color: var(--brand, currentColor); }
.notif-badge {
  position: absolute; top: 4px; right: 3px; min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 9px; background: var(--danger, #dc2626); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 17px; text-align: center;
}
.notif-panel {
  position: absolute; top: calc(100% + 8px); right: 0; width: min(360px, calc(100vw - 32px));
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.16); z-index: 60; overflow: hidden;
}
.notif-panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--border); font-size: 14px;
}
.notif-mark-read {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--text-muted); font-size: 12px; font-weight: 600;
}
.notif-mark-read:hover { text-decoration: underline; }
.notif-list { max-height: min(60vh, 420px); overflow-y: auto; }
.notif-item {
  display: flex; gap: 11px; align-items: flex-start; padding: 12px 14px;
  border-bottom: 1px solid var(--border); color: inherit; text-decoration: none;
}
a.notif-item:hover { background: var(--surface-soft); }
.notif-item.notif-unread { background: var(--tint, rgba(46, 83, 149, 0.06)); }
.notif-icon {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--surface-soft); color: var(--text-muted);
}
.notif-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.notif-title { font-size: 13.5px; font-weight: 650; line-height: 1.35; }
.notif-body { font-size: 12.5px; color: var(--text-muted); line-height: 1.45; }
.notif-when { font-size: 11px; color: var(--text-muted); opacity: 0.85; margin-top: 2px; }
.notif-empty { padding: 22px 16px; margin: 0; font-size: 13px; color: var(--text-muted); text-align: center; }
.notif-panel-foot {
  display: block; padding: 11px 14px; text-align: center;
  font-size: 12.5px; font-weight: 600; text-decoration: none;
}
.notif-panel-foot:hover { background: var(--surface-soft); }

/* On a phone the nav collapses into a stacked menu, where an absolutely
   positioned dropdown would be cut off by the header. Let it flow inline
   instead. */
@media (max-width: 860px) {
  .notif-wrap { width: 100%; }
  .notif-bell { width: auto; height: auto; padding: 8px 0; justify-content: flex-start; gap: 8px; }
  .notif-bell::after { content: "Notifications"; font-size: inherit; font-weight: inherit; }
  .notif-badge { position: static; margin-left: 6px; }
  .notif-panel { position: static; width: 100%; box-shadow: none; margin: 6px 0 10px; }
}

/* ---------------------------------------------------------------------
   Exam photo resizer - the interactive crop frame (photo_crop.js)
   --------------------------------------------------------------------- */
.ep-crop-wrap {
  position: relative; border: 1px solid var(--border); border-radius: 10px;
  padding: 8px; background: #fff; overflow: hidden;
}
.ep-crop-canvas {
  display: block; width: 100%; border-radius: 6px;
  cursor: grab; touch-action: none;            /* we handle pinch ourselves */
  background: #f2f2f2;
}
.ep-crop-canvas.cropping { cursor: grabbing; }
.ep-crop-controls { margin-top: 10px; }
.ep-zoom-label { display: block; font-size: 12px; font-weight: 600; margin-bottom: 4px; }
.ep-zoom-row { display: flex; align-items: center; gap: 8px; }
.ep-zoom-row input[type="range"] { flex: 1; margin: 0; }
.ep-zoom-btn {
  width: 34px; min-width: 34px; height: 34px; padding: 0;
  font-size: 18px; line-height: 1; display: inline-flex;
  align-items: center; justify-content: center;
}
.ep-crop-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.ep-crop-actions .btn { flex: 1; min-width: 120px; justify-content: center; }
.ep-crop-hint { margin: 8px 0 0; font-size: 12px; line-height: 1.5; }
/* A signature is fitted whole rather than cropped, so the frame controls
   are hidden for it rather than shown and doing nothing. */
.ep-crop-controls.hidden { display: none; }

/* ===================== Language picker =====================
   In the header of every page - see i18n.language_switcher. A <details>
   element, so it needs no JavaScript: the browser handles opening,
   closing and keyboard focus, and the entries inside are ordinary links
   a crawler can follow. */
/* Pushed to the right so it sits with the theme toggle rather than
   floating in the middle of the header - .topbar spreads its children
   with space-between, so a new child would otherwise land wherever the
   arithmetic put it. */
.lang-menu { position: relative; display: inline-flex; flex: none; margin-left: auto; }
[dir="rtl"] .lang-menu { margin-left: 0; margin-right: auto; }
.lang-menu > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 9px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--card); color: inherit;
  font-size: 13px; font-weight: 700;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
/* Both spellings - Safari still needs the -webkit- one to drop the
   default disclosure triangle. */
.lang-menu > summary::-webkit-details-marker { display: none; }
.lang-menu > summary::marker { content: ""; }
.lang-menu > summary:hover { border-color: var(--border-strong); background: var(--tint); }
.lang-menu > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lang-flag { font-size: 15px; line-height: 1; display: inline-flex; align-items: center; }
.lang-flag-img {
  display: block;
  width: 18px;
  height: 14px;
  object-fit: cover;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
}
.lang-menu-item .lang-flag-img { width: 20px; height: 15px; }
.lang-code { font-family: var(--font-mono); letter-spacing: 0.02em; }
.lang-caret { font-size: 10px; opacity: 0.6; }
.lang-menu[open] > summary .lang-caret { transform: rotate(180deg); }

.lang-menu-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 1200;
  min-width: 232px; max-height: 60vh; overflow-y: auto;
  padding: 8px; border-radius: 12px;
  background: var(--bg-elevated); border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  animation: langMenuIn .14s var(--ease);
}
/* On a right-to-left page the header is mirrored, so the panel hangs off
   the other edge. */
[dir="rtl"] .lang-menu-panel { right: auto; left: 0; }
@keyframes langMenuIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.lang-menu-title {
  margin: 2px 8px 6px; font-size: 10.5px; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-muted); font-family: var(--font-mono);
}
.lang-menu-item {
  display: grid; grid-template-columns: 22px 1fr auto; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 9px; text-decoration: none; color: var(--text);
  transition: background .12s var(--ease);
}
.lang-menu-item:hover { background: var(--tint); }
/* The language's OWN name is the label; the flag is decoration and the
   English name is a quiet gloss for anyone who does not recognise the
   script - see the note on LANGUAGES in i18n.py. */
.lang-menu-name { font-size: 13.5px; font-weight: 700; }
.lang-menu-en { font-size: 11px; color: var(--text-muted); font-weight: 600; }
.lang-menu-item.is-current { background: var(--gold-tint); }
.lang-menu-item.is-current .lang-menu-name { color: var(--ink); }
/* A language that's offered but whose translations aren't published yet:
   still a real, working link (the tools all work), just quieter, so the
   menu is honest about which languages are finished. */
.lang-menu-item.is-pending .lang-menu-name { font-weight: 600; opacity: 0.72; }
.lang-menu-item.is-pending .lang-menu-en { opacity: 0.8; }
/* The note at the top of a not-yet-translated language's tools page. */
.lang-pending-note {
  max-width: 640px; margin: 10px auto 0; padding: 9px 14px;
  border-radius: 10px; border: 1px solid var(--border);
  background: var(--tint); color: var(--text-muted);
  font-size: 12.5px; line-height: 1.55;
}
@media (max-width: 520px) {
  .lang-menu > summary { padding: 0 7px; }
  .lang-menu > summary .lang-code { display: none; }
  .lang-menu-panel { min-width: 208px; }
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Right-to-left languages (Arabic, Urdu). The page's own direction is set
   on <html>; these two put the nav and text alignment the right way round
   without needing a separate stylesheet. */
html[dir="rtl"] .topbar { direction: rtl; }
html[dir="rtl"] .blog-post-body { text-align: right; }
html[dir="rtl"] .blog-post-body ul,
html[dir="rtl"] .blog-post-body ol { padding-right: 20px; padding-left: 0; }

/* --------------------------------------------------------------------
   Size-target chips (Compress to Exact Size, and any other tool that
   offers a row of preset values).

   These used to borrow `.pe-tool` / `.pe-tool-group` from
   static/css/pdf_edit.css, which is only loaded on the PDF editor page -
   so on every other page the chips rendered as bare, unstyled <button>s
   and, critically, `.active` had no visual effect at all: you could not
   tell which target size was selected. Defined here in the global sheet
   instead, so the selected state is always visible.
   -------------------------------------------------------------------- */
.size-chip-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.size-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 64px; height: 38px; padding: 0 14px; margin: 0;
  border-radius: 10px; border: 1.5px solid var(--border);
  background: var(--card); color: var(--text);
  cursor: pointer; font-size: 13.5px; font-weight: 700; line-height: 1;
  transition: background 0.18s ease, border-color 0.18s ease,
              color 0.18s ease, box-shadow 0.18s ease;
}
.size-chip:hover { background: var(--tint); border-color: var(--tint-border); }
.size-chip:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--tint);
  border-color: var(--border-strong);
}
.size-chip.active,
.size-chip[aria-pressed="true"] {
  background: var(--accent); color: #fff; border-color: var(--accent);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.14);
}
.size-chip.active:hover,
.size-chip[aria-pressed="true"]:hover {
  background: var(--accent); border-color: var(--accent);
}
/* A checkmark on the chosen chip, so the selection reads correctly even
   for a visitor who can't distinguish the accent colour from the plain
   chip background. */
.size-chip[aria-pressed="true"]::before {
  content: "\2713"; font-size: 12px; margin-right: 6px; opacity: 0.95;
}

/* =====================================================================
   Shared UI primitives that were previously only in pdf_edit.css /
   sign_pdf.css.

   Those two stylesheets are loaded ONLY by their own pages (the PDF
   editor, and the e-sign signing page). Several other tools reuse the
   same class names for their toggles, page arrows and preview modals -
   Signature Cleanup's White/Transparent switch, E-Sign's signing-order
   switch, Aadhaar Mask's page navigation, Reorder's page-preview
   lightbox - and on those pages the rules simply did not exist. The
   result was a control that changed nothing visible when clicked: the
   selected option looked identical to the unselected one, a "previous
   page" arrow pointed the same way as "next", a disabled button looked
   live, and a modal rendered inline in the middle of the form instead of
   as an overlay.

   Defining them here, in the global sheet every page loads, fixes all of
   those at once. pdf_edit.css still loads after this on its own page and
   carries the same values, so the editor is unaffected.
   ===================================================================== */

.pe-tool-group {
  display: flex; align-items: center; gap: 4px;
  padding-right: 10px; border-right: 1px solid var(--border);
}
.pe-tool-group:last-of-type { border-right: none; }
.pe-tool, .pe-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  width: 36px; height: 36px; border-radius: 9px; border: 1px solid transparent;
  background: transparent; color: var(--text); cursor: pointer; font-size: 13px; font-weight: 700;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.pe-tool.pe-wide { width: auto; padding: 0 12px; }
.pe-tool:hover, .pe-icon-btn:hover { background: var(--tint); }
.pe-tool.active { background: var(--accent); color: #fff; border-color: var(--accent); }
.pe-icon-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pe-icon-btn:disabled:hover { background: transparent; }
/* Without this the "previous page" arrow is the same right-pointing
   glyph as "next page". */
.pe-flip { transform: rotate(180deg); }
.pe-zoom-group, .pe-page-group { font-size: 13px; font-weight: 700; color: var(--text-muted); }
.pe-zoom-group span, .pe-page-group span { min-width: 76px; text-align: center; }

.pe-modal-backdrop {
  position: fixed; inset: 0; top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(15, 23, 42, 0.55); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center; z-index: 100; padding: 20px;
}
.pe-modal-backdrop.hidden { display: none; }
.pe-modal {
  width: 100%; max-width: 520px; max-height: 86vh; overflow-y: auto;
  background: var(--card-solid); border: 1px solid var(--border); border-radius: 16px;
  padding: 22px 24px; box-shadow: var(--shadow-lg);
}
.pe-modal-wide { max-width: 640px; }
.pe-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.pe-modal-head h3 { margin: 0; font-family: var(--font-heading); font-size: 19px; }
.pe-modal-close {
  width: 32px; height: 32px; border-radius: 9px; border: none; background: var(--surface-soft);
  color: var(--text-muted); font-size: 18px; cursor: pointer; line-height: 1;
}
.pe-modal-close:hover { background: var(--tint); color: var(--text); }
.pe-modal-foot { display: flex; align-items: center; gap: 10px; margin-top: 16px; flex-wrap: wrap; }

/* The "this part is transparent" checkerboard behind Signature Cleanup's
   preview. Without it the cleaned signature - deliberately dark ink on a
   cleared background - was invisible against a dark-mode panel, which
   read as "the tool produced nothing". */
.sp-checker-bg {
  border: 1.5px dashed var(--border); border-radius: 10px; padding: 10px;
  background-image: repeating-conic-gradient(#c9c2d6 0% 25%, transparent 0% 50%);
  background-size: 16px 16px;
  background-color: #fff;
  display: flex; align-items: center; justify-content: center; min-height: 100px;
}
:root[data-theme="dark"] .sp-checker-bg,
:root:not([data-theme="light"]) .sp-checker-bg { background-color: #2a2438; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sp-checker-bg { background-color: #2a2438; }
}

/* A disabled primary button had NO styling at all, so the big "Unlock" /
   "Burn in the mask" button looked fully live while doing nothing until
   its preconditions were met, with no cue as to why. */
.btn:disabled,
.btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
.btn:disabled:hover,
.btn[disabled]:hover { transform: none; }

/* The click ripple (static/js/animations.js) is sized ~1.4x the button
   and was never clipped, so on a full-width .btn-large it washed a white
   circle outside the button's corners on every click. */
.btn { overflow: hidden; }

/* Placeholder tile for a page whose thumbnail couldn't be rendered - it
   still holds its place in the order (see static/js/reorder.js). */
.reorder-thumb-failed {
  display: flex; align-items: center; justify-content: center;
  min-height: 120px; color: var(--text-muted);
  font-size: 13px; font-weight: 700;
  background: var(--surface-soft); border-style: dashed;
}

/* Form Upload Check's pass/fail headline (an <h3>, so this colours the
   text rather than making it a badge). */
.fc-verdict-ok { color: var(--success); }
.fc-verdict-bad { color: var(--danger); }

/* ------------------------------------------------------------------
   Scanned-PDF confirmation dialog (dashboard)
   Shown before a scan/photo is converted so the user picks how the
   Word document should be built - see static/js/dashboard.js.
   ------------------------------------------------------------------ */
.scan-dialog {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(15, 23, 42, 0.55);
  backdrop-filter: blur(2px);
}
.scan-dialog.hidden { display: none; }
.scan-dialog-card {
  width: 100%; max-width: 520px;
  max-height: calc(100vh - 40px); overflow-y: auto;
  background: var(--surface, #fff);
  border-radius: 14px;
  padding: 24px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
  text-align: left;
}
.scan-dialog-card h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; }
.scan-dialog-card > .dash-sub { margin: 0 0 18px; }

.scan-dialog-options { border: 0; margin: 0 0 20px; padding: 0; display: grid; gap: 10px; }
.scan-option {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px; cursor: pointer;
  border: 1.5px solid var(--border, #e2e8f0); border-radius: 10px;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.scan-option:hover { border-color: var(--brand, #6366f1); }
.scan-option:has(input:checked) {
  border-color: var(--brand, #6366f1);
  background: rgba(99, 102, 241, 0.06);
}
.scan-option input { margin-top: 3px; flex: 0 0 auto; }
.scan-option-body { display: block; }
.scan-option-body strong { display: block; font-size: 14.5px; margin-bottom: 3px; }
.scan-option-body small { display: block; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); }

.scan-dialog-actions { display: flex; justify-content: flex-end; gap: 10px; }

@media (max-width: 520px) {
  .scan-dialog-card { padding: 18px; }
  .scan-dialog-actions { flex-direction: column-reverse; }
  .scan-dialog-actions .btn { width: 100%; }
}

/* ==================================================================
   Drop zone graphic
   ==================================================================
   Every drop zone on the site - PDF to Word, e-sign, sign PDF, the
   Aadhaar and form tools, and the tool-page shell - shares .dropzone
   and .dz-icon, so this one block upgrades all of them without a line
   of markup or script changing anywhere.

   What it draws: two sheets of paper behind the existing upload arrow,
   the front one ruled. At rest they sit almost square, breathing very
   slightly. On hover they part. While a file is actually over the zone
   they fan open, the arrow lifts into the gap, a verdigris scan line
   runs down the front sheet, and the dashed border marches - so the
   moment of "yes, let go here" is unmistakable rather than a two-pixel
   colour change.

   Drawn in CSS rather than as an image or an SVG file: it has to be
   themed by the same tokens as everything else (both light and dark),
   it has four states to animate between, and it must not add a request
   to a page on a phone connection.
   ================================================================== */
.dz-icon {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 116px; height: 96px;
  margin: 0 auto 16px;
  font-size: 0;               /* the wrapper's own inherited size is unused now */
}

/* The two sheets. ::before is the one behind, ::after the ruled one in
   front - both are pure decoration, which is why they live on
   pseudo-elements and never enter the accessibility tree. */
.dz-icon::before,
.dz-icon::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 58px; height: 74px;
  border-radius: 5px;
  background: var(--card-solid);
  border: 1.5px solid var(--border-strong);
  box-shadow: 0 4px 10px rgba(33, 22, 12, 0.10);
  transition: transform 0.45s var(--ease), box-shadow 0.45s var(--ease), border-color 0.3s ease;
}
.dz-icon::before {
  transform: translate(-50%, -50%) rotate(-8deg) translateX(-10px);
  opacity: 0.7;
}
.dz-icon::after {
  /* The ruled sheet: four hairlines, drawn with a repeating gradient so
     they scale with the box and need no extra element. The top band is
     left blank as a "heading" so it reads as a document rather than as
     lined notepaper. */
  transform: translate(-50%, -50%) rotate(5deg) translateX(7px);
  background:
    /* the heading band: a short, heavier rule near the top */
    linear-gradient(var(--border-strong), var(--border-strong)) 10px 14px / 24px 3px no-repeat,
    /* then the body rules */
    repeating-linear-gradient(
      to bottom,
      transparent 0 24px,
      var(--track) 24px 25.5px,
      transparent 25.5px 34px
    ),
    var(--card-solid);
  background-repeat: no-repeat, repeat, repeat;
}

/* The arrow that was already there sits on top of the sheets. */
.dz-icon > svg,
.dz-icon > .icon {
  position: relative; z-index: 2;
  width: 30px; height: 30px;
  color: var(--accent);
  /* A disc behind the arrow lifts it off the ruled sheet, which was
     busy enough underneath it to make the glyph hard to pick out. */
  background: var(--card-solid);
  border-radius: 50%;
  padding: 7px;
  box-shadow: 0 3px 10px rgba(33, 22, 12, 0.16);
  filter: drop-shadow(0 2px 4px rgba(33, 22, 12, 0.18));
  transition: transform 0.35s var(--ease);
}

/* A scan line down the front sheet. Only ever visible while a file is
   over the zone - at rest it would be restless for no reason. */
.dz-icon i.dz-scan { display: none; }

.dropzone:hover .dz-icon::before { transform: translate(-50%, -50%) rotate(-12deg) translateX(-15px); }
.dropzone:hover .dz-icon::after  { transform: translate(-50%, -50%) rotate(9deg) translateX(15px); }
.dropzone:hover .dz-icon > svg   { transform: translateY(-3px); }

.dropzone.dragover .dz-icon::before {
  transform: translate(-50%, -50%) rotate(-19deg) translateX(-25px) translateY(3px);
  border-color: var(--accent);
}
.dropzone.dragover .dz-icon::after {
  transform: translate(-50%, -50%) rotate(16deg) translateX(25px) translateY(3px);
  border-color: var(--accent);
  box-shadow: 0 8px 18px rgba(33, 22, 12, 0.16);
}
.dropzone.dragover .dz-icon > svg {
  transform: translateY(-8px) scale(1.08);
  color: var(--dropzone-border);
}

/* Marching ants while a file is over the zone. The dash pattern is
   animated by moving the border-image offset, which is the only way to
   animate a dashed border without swapping it for a background image
   and losing the border-radius. */
.dropzone.dragover {
  border-style: dashed;
  animation: dzAnts 0.7s linear infinite;
}
@keyframes dzAnts {
  from { border-color: var(--primary); }
  50%  { border-color: var(--dropzone-border); }
  to   { border-color: var(--primary); }
}

/* A very slight breath at rest, so the zone reads as live rather than
   as a static box - two pixels over three seconds, not a bounce. */
@media (prefers-reduced-motion: no-preference) {
  .dz-icon { animation: dzBreathe 3.6s ease-in-out infinite; }
}
@keyframes dzBreathe {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}

/* Motion off: the sheets still fan on hover and drag (those are
   feedback, not decoration - a transition, not a looping animation),
   but nothing loops on its own. */
@media (prefers-reduced-motion: reduce) {
  .dz-icon { animation: none; }
  .dropzone.dragover { animation: none; border-color: var(--primary); }
}

/* Dark theme: paper on a dark desk needs its own edge, or the sheets
   vanish into the panel behind them. */
:root[data-theme="dark"] .dz-icon::before,
:root[data-theme="dark"] .dz-icon::after,
:root:not([data-theme="light"]) .dz-icon::before,
:root:not([data-theme="light"]) .dz-icon::after {
  background: var(--bg-elevated);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
}
:root[data-theme="dark"] .dz-icon::after,
:root:not([data-theme="light"]) .dz-icon::after {
  background:
    linear-gradient(var(--border-strong), var(--border-strong)) 10px 14px / 24px 3px no-repeat,
    repeating-linear-gradient(
      to bottom,
      transparent 0 24px,
      var(--track) 24px 25.5px,
      transparent 25.5px 34px
    ),
    var(--bg-elevated);
  background-repeat: no-repeat, repeat, repeat;
}

/* ==================================================================
   Site graphics
   ==================================================================
   Additive decoration on top of the existing "Ink & Seal" identity -
   nothing here changes a colour, a size or a layout that was already
   set. The whole point of the identity is paper, ink and an official
   seal, and until now that lived entirely in the palette: every surface
   was a flat rectangle. These are the marks that make it read as
   paper - a ruled grid, an engraved rule with a diamond, a stamped
   seal, a corner fold - plus a small line drawing for each step of
   "How it works".

   Drawn in CSS and inline SVG rather than as image files: they have to
   be themed by the same tokens as everything else (both light and dark
   mode), and they must not add a single request to a page loading on a
   phone connection. Every one of them is decoration - aria-hidden or a
   pseudo-element - so none of it reaches a screen reader, and all of it
   sits behind the content it decorates.
   ================================================================== */

/* --- 1. The hero band, on paper ------------------------------------ */
/* A fine ruled grid, at the opacity of a watermark. `--paper-line` is
   defined per theme below so this is a warm graphite on parchment in
   light mode and a soft highlight on ink in dark mode. */
:root { --paper-line: rgba(33, 29, 44, 0.055); --paper-seal: rgba(168, 59, 44, 0.07); }
.hero-band::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    repeating-linear-gradient(to right, var(--paper-line) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(to bottom, var(--paper-line) 0 1px, transparent 1px 34px);
  /* Fades out downward so the grid never fights the content below it. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,0.35) 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,0.35) 55%, transparent 100%);
}
/* A stamped seal, off in the corner of the paper - the identity's own
   motif, drawn once, large and faint, the way a real document carries an
   embossed mark rather than a logo. */
.hero-band::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  right: -70px; bottom: -90px; width: 320px; height: 320px;
  background-repeat: no-repeat; background-size: contain; opacity: 0.9;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg fill='none' stroke='%23A83B2C' stroke-opacity='0.14' stroke-width='2.5'%3E%3Ccircle cx='100' cy='100' r='78'/%3E%3Ccircle cx='100' cy='100' r='64' stroke-dasharray='5 7'/%3E%3Ccircle cx='100' cy='100' r='44'/%3E%3Cpath d='M100 56v88M56 100h88'/%3E%3Cpath d='M100 40l7 12h-14zM100 160l7-12h-14zM40 100l12-7v14zM160 100l-12-7v14z' fill='%23A83B2C' fill-opacity='0.14' stroke='none'/%3E%3C/g%3E%3C/svg%3E");
}
.hero-band > .hero { position: relative; z-index: 1; }

/* --- 2. An engraved rule between sections -------------------------- */
/* <div class="section-rule" aria-hidden="true"></div> */
.section-rule {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin: 40px auto; max-width: 1040px; color: var(--border);
}
.section-rule::before, .section-rule::after {
  content: ""; height: 1px; flex: 1;
  background: linear-gradient(to right, transparent, var(--border-strong), transparent);
}
.section-rule > span {
  width: 7px; height: 7px; transform: rotate(45deg);
  background: var(--accent); opacity: 0.7; border-radius: 1px;
  box-shadow: 0 0 0 4px var(--tint);
}

/* --- 3. "How it works" line drawings ------------------------------- */
/* Each .step gets a small SVG above its number. Stroke is currentColor
   at the step's own accent, so both themes are handled with no second
   copy of the artwork. */
.step { position: relative; overflow: hidden; }
.step-art {
  display: block; width: 56px; height: 56px; margin-bottom: 4px;
  color: var(--accent);
}
.step-art path, .step-art circle, .step-art rect, .step-art line, .step-art polyline {
  vector-effect: non-scaling-stroke;
}
/* The step number now sits beside the drawing rather than above it. */
.step-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.step-head .step-num { margin-bottom: 0; flex: none; }
/* A faint tint bleeding in from the corner, so a step reads as a card
   rather than a box - and lifts on hover with the card itself. */
.step::after {
  content: ""; position: absolute; right: -40px; top: -40px; width: 120px; height: 120px;
  border-radius: 50%; background: var(--tint); opacity: 0.55;
  transition: transform 0.35s var(--ease), opacity 0.35s var(--ease);
  pointer-events: none; z-index: 0;
}
.step:hover::after { transform: scale(1.25); opacity: 0.8; }
.step > * { position: relative; z-index: 1; }

/* --- 4. Feature cards: a turned-down corner ------------------------ */
.feature { position: relative; overflow: hidden; }
.feature::after {
  content: ""; position: absolute; right: 0; bottom: 0; width: 26px; height: 26px;
  background: linear-gradient(135deg, transparent 49%, var(--tint-border) 50%, var(--tint) 52%);
  pointer-events: none;
}

/* --- 5. The wax seal beside "First one free" ----------------------- */
.seal-art { display: block; width: 84px; height: 84px; color: var(--violet); flex: none; }
@media (max-width: 640px) { .seal-art { display: none; } }

/* ===================== One tool, one language, one page
   (templates/tool_page_localised.html) - the page a local-language
   search lands on. Its own layout rather than the blog's: a heading with
   the tool's icon, the call to action repeated above and below the copy,
   and body text at reading width. ===================== */
.localised-tool { max-width: 760px; margin: 0 auto 28px; }
.localised-tool-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.localised-tool-icon {
  flex: none; width: 56px; height: 56px; border-radius: 14px; display: flex;
  align-items: center; justify-content: center; color: var(--accent);
  background: var(--tint); border: 1px solid var(--tint-border);
}
.localised-tool-head h1 { margin: 0 0 6px; font-size: 26px; line-height: 1.25; font-weight: 800; }
.localised-tool-cta { margin: 20px 0; }
.localised-tool-cta .btn { width: 100%; justify-content: center; }
.localised-tool-body h2 { font-size: 19px; margin: 26px 0 10px; font-weight: 800; }
.localised-tool-body h3 { font-size: 15.5px; margin: 20px 0 6px; font-weight: 700; }
.localised-tool-body p { margin: 0 0 12px; line-height: 1.7; color: var(--text); }
.localised-tool-body ol, .localised-tool-body ul { margin: 0 0 14px; padding-left: 22px; line-height: 1.7; }
.localised-tool-body li { margin-bottom: 6px; }
.localised-tool-foot {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  border-top: 1px solid var(--border); padding-top: 14px; margin: 26px 0 0; font-size: 12.5px;
}

/* ===================== "Buying from outside India"
   (templates/international_purchase.html) - see
   payments.international_purchase for why this page exists. Reading
   width, the price list as plain chips, and an ordinary two-column
   form. ===================== */
.intl-panel { max-width: 760px; margin: 0 auto 28px; }
.intl-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.intl-globe {
  flex: none; width: 52px; height: 52px; border-radius: 14px; display: flex;
  align-items: center; justify-content: center; color: var(--accent);
  background: var(--tint); border: 1px solid var(--tint-border);
}
.intl-head h1 { margin: 0; font-size: 25px; line-height: 1.25; font-weight: 800; }
.intl-body p { margin: 0 0 12px; line-height: 1.7; }
.intl-cta { margin: 20px 0 6px; }
.intl-cta .btn { width: 100%; justify-content: center; }
.intl-cta-note { margin: 0 0 8px; font-size: 12.5px; }
.intl-subhead {
  display: flex; align-items: center; gap: 8px;
  font-size: 17px; font-weight: 800; margin: 28px 0 12px;
  padding-top: 18px; border-top: 1px solid var(--border);
}
.intl-packs { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 4px; }
.intl-pack {
  display: flex; flex-direction: column; gap: 1px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface-soft);
}
.intl-pack-credits { font-size: 11.5px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.intl-pack-price { font-family: var(--font-heading); font-size: 19px; font-weight: 700; }
.intl-pack-local { font-size: 11.5px; color: var(--text-muted); font-weight: 600; }
.intl-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 620px) { .intl-form-row { grid-template-columns: 1fr; } }
.intl-form label { display: block; margin: 12px 0 4px; font-weight: 700; font-size: 13px; }
.intl-form .intl-hint { margin: 4px 0 0; font-size: 12px; }
.intl-form button { margin-top: 18px; }
/* The honeypot: off-screen rather than display:none, because some bots
   skip anything that is display:none and this one is meant to be
   filled in. */
.intl-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.intl-sent { margin-bottom: 6px; }
.intl-foot { border-top: 1px solid var(--border); padding-top: 14px; margin: 26px 0 0; font-size: 12.5px; }
