/* Project-specific styles for loopdf - PDF Tools */
/* Uses base design system variables from style.css */

/* =============================================================
   THEME OVERRIDE
   =============================================================
   Remaps every shared base theme token (--text-color, --card-bg,
   --primary-blue, --border-color, --info-item-bg, etc.) to the new
   pdf palette so every page (tools, blog, auth, user panel, reviews,
   content pages, editor, admin) picks up the redesign without
   editing markup. Also applies Geist (body) + Fraunces (h1–h5)
   globally, with editor + admin opt-outs that keep system fonts.
   Scoped to loopdf.com - no impact on sister startup-cms projects.
   ============================================================= */

/* ---------- Chrome cleanup ----------
   1) Suppress the project-wide contour SVG pattern that base_style.css paints
      via body.theme-dark::before / body.theme-light::before. It reads as noise
      under the new clean design on every loopdf page.
   2) Strip the legacy card chrome from .container (background, rounded bottom
      corners, shadow). The body palette + section-level spacing now own the
      visual, matching the landing's full-bleed feel. Max-width + inline
      padding stay so content still breathes on narrow viewports. */

body::before {
  display: none !important;
  background: none !important;
  content: none !important;
}

body main.container,
body main.container.container-default,
body main.container.container-90,
body main.container.container-70,
body main.container.container-1200 {
  background: transparent !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  border: 0 !important;
}

/* Mobile: something on these pages is wider than the screen, so the browser
   expands the layout viewport past the device width (innerWidth > device),
   which renders the page zoomed-out / as a narrow column with dead space.
   Clamp the document to the viewport and make the container + common
   fixed-size offenders fluid. Excludes the standalone PDF editor
   (#pdfEditorApp), which has its own correct full-screen layout. */
@media (max-width: 900px) {
  html:not(:has(#pdfEditorApp)),
  body:not(:has(#pdfEditorApp)) {
    max-width: 100vw !important;
    overflow-x: hidden !important;
  }

  body:not(:has(#pdfEditorApp)) main.container,
  body main.container.container-default,
  body main.container.container-90,
  body main.container.container-70,
  body main.container.container-1200,
  body main.landing-container {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
    box-sizing: border-box !important;
  }

  /* Media/wide content must never force the page wider than the screen. */
  body:not(:has(#pdfEditorApp)) img,
  body:not(:has(#pdfEditorApp)) svg,
  body:not(:has(#pdfEditorApp)) video,
  body:not(:has(#pdfEditorApp)) canvas,
  body:not(:has(#pdfEditorApp)) iframe,
  body:not(:has(#pdfEditorApp)) table,
  body:not(:has(#pdfEditorApp)) pre {
    max-width: 100% !important;
  }
}

/* ---------- Light theme palette remap ---------- */

body.theme-light {
  /* Foreground / text */
  --text-color: #1b1110; /* pdf-ink (warm near-black) */
  --heading-color: #1b1110; /* pdf-ink */
  --heading-sub: #1b1110;
  --muted-text: #80706b; /* pdf-muted (warm grey) */
  --text-primary: #1b1110;
  --text-secondary: #80706b;

  /* Surfaces */
  --container-bg: #ffffff;
  --card-bg: #ffffff; /* pdf-surface (solid, not rgba) */
  --card-header-bg: #fbf3f2; /* pdf-surface-2 (warm red tint) */
  --input-bg: #ffffff;
  --dropdown-bg: #ffffff;
  --item-bg: #fbf3f2;
  --item-hover-bg: #fbedec; /* pdf-tint */
  --table-header-bg: #fbedec; /* pdf-tint */
  --info-item-bg: #fbedec; /* pdf-tint */
  --info-bg: #fdecea;
  --info-border: #f6cfcd;
  --info-text: #a31621;

  /* Borders */
  --border-color: #efe0dd; /* pdf-line */

  /* Brand - loopdf red.
     --primary-blue / --primary-blue-hover are NOT declared here on purpose:
     brand_tokens.css (asset order 2, same body.theme-* selector) is the single
     source for them, and everything below derives from those two values so the
     mark, the buttons and the landing palette cannot drift apart. */
  --accent-blue: #f2706b;
  --light-blue-text: var(--primary-blue-hover);
  --primary-color: var(--primary-blue);
  --primary-hover: var(--primary-blue-hover);
  --primary-shadow: color-mix(in srgb, var(--primary-blue) 25%, transparent);
  /* Raw channels for rgba() call sites - keep in step with --primary-blue. */
  --link-rgb: 214, 40, 40;

  /* Links */
  --link: #c41f24;
  --link-hover: #a31621;
  --blockquote: #d62828;

  /* Footer */
  --footer-nav-bg: #fbf3f2;
  --footer-bottom-bg: #fbf3f2;
  --footer-border: #efe0dd;
  --footer-section-bg: #fbf3f2;

  /* Elevation / shadow */
  --shadow-elev:
    0 1px 0 rgba(163, 22, 33, 0.05), 0 12px 24px -8px rgba(163, 22, 33, 0.12);
  --shadow-color: rgba(163, 22, 33, 0.08);

  /* Page background */
  --bg-gradient: #fbf7f6; /* pdf-bg (warm paper) */
  --bg-dark: #f1e3e0;

  /* Disabled button */
  --button-disabled-bg: rgba(214, 40, 40, 0.07);
  --button-disabled-border: rgba(214, 40, 40, 0.15);
  --button-disabled-text: rgba(27, 17, 16, 0.4);
}

/* ---------- Dark theme palette remap ---------- */

body.theme-dark {
  /* Foreground / text */
  --text-color: #c2bcba; /* pdf-ink-2 (warm light grey) */
  --heading-color: #f5f4f2; /* pdf-ink */
  --heading-sub: #f5f4f2;
  --muted-text: #928c8a; /* pdf-muted */
  --text-primary: #c2bcba;
  --text-secondary: #928c8a;

  /* Surfaces - warm near-black. Each one is the neutral charcoal shifted a few
     points toward the brand red, so the dark theme is recognisably loopdf's
     without stopping being black. Kept in step with the --pdf-* dark block in
     landing.css. */
  --container-bg: #191315; /* pdf-bg */
  --card-bg: #261b1d; /* pdf-surface */
  --card-header-bg: #211819; /* pdf-surface-2 */
  --input-bg: #191315;
  --dropdown-bg: #211819;
  --item-bg: #261b1d;
  --item-hover-bg: #332427;
  --table-header-bg: #32211f; /* pdf-tint dark (red wash) */
  --info-item-bg: #32211f; /* pdf-tint dark */
  --info-bg: #2c1a1a;
  --info-border: #4a2a2a;
  --info-text: #ff9e97;

  /* Borders */
  --border-color: #3e2e30; /* pdf-line dark */

  /* Brand - loopdf red on charcoal. See the light block: the two source
     values come from brand_tokens.css, the rest are derived. */
  --accent-blue: var(--primary-blue);
  --light-blue-text: var(--primary-blue-hover);
  --primary-color: var(--primary-blue);
  --primary-hover: var(--primary-blue-hover);
  --primary-shadow: color-mix(in srgb, var(--primary-blue) 40%, transparent);
  /* Raw channels for rgba() call sites - keep in step with --primary-blue. */
  --link-rgb: 255, 107, 97;

  /* Links */
  --link: #ff8e86; /* pdf-primary-ink dark */
  --link-hover: #ffa59e;
  --blockquote: #ff6b61;

  /* Footer */
  --footer-bottom-bg: #150f11;
  --footer-border: #3e2e30;
  --footer-section-bg: #211819;

  /* Elevation / shadow - drops carry the same faint red as the surfaces. */
  --shadow-elev: 0 10px 40px rgba(26, 6, 9, 0.55);
  --shadow-color: rgba(26, 6, 9, 0.6);

  /* Page background */
  --bg-gradient: #191315; /* pdf-bg dark */
  --bg-dark: #191315;

  /* Disabled button */
  --button-disabled-bg: rgba(148, 163, 184, 0.2);
  --button-disabled-border: rgba(148, 163, 184, 0.32);
  --button-disabled-text: rgba(226, 232, 240, 0.72);
}

/* Navbar CTA (Sign in button) - white ink on the brand fill, matching the
   primary buttons. The base default is --brand-ink (dark ink in the dark theme),
   which reads as near-black on the red fill. Per base_navbar.css, --nb-cta-ink is
   declared directly on .nb-root/.nb-drawer, so a body-level override is ignored -
   it must be re-stated on the same selectors. */
body.theme-dark .nb-root,
body.theme-dark .nb-drawer {
  --nb-cta-ink: #ffffff;
}

/* Fredoka's 700 weight is chunky and closes up the letter counters at the
   mega-menu title size, so the bold labels read cramped. Nudging the size up ~1px,
   easing the weight to 600, and adding a little letter-spacing opens the glyphs
   up and makes them noticeably easier to read - still clearly a title against the
   lighter description below. Scoped to the navbar menu, where the labels live. */
.nb-rich__title {
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: 0.35px;
}

/* ---------- Typography ---------- */

body {
  font-family:
    'Fredoka',
    system-ui,
    -apple-system,
    'Segoe UI',
    Roboto,
    sans-serif;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5 {
  font-family: 'Fredoka', system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: -0.01em;
}

h6,
code,
kbd,
pre,
samp {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---------- Typography opt-outs ----------
   Editor is a functional app UI - labels, inspector, keyboard hints look
   wrong in a serif display font. Keep the new palette (tokens) but force
   every element back to the system-ui stack. Admin (dense DataTables +
   forms) follows the same rule. */

body:has(#pdfEditorApp),
body:has(.pdf-editor-page) {
  font-family:
    'Fredoka',
    system-ui,
    -apple-system,
    'Segoe UI',
    Roboto,
    sans-serif;
}
body:has(#pdfEditorApp) *,
body:has(.pdf-editor-page) * {
  font-family: inherit;
}
body:has(#pdfEditorApp) code,
body:has(#pdfEditorApp) kbd,
body:has(#pdfEditorApp) pre,
body:has(#pdfEditorApp) samp,
body:has(.pdf-editor-page) code,
body:has(.pdf-editor-page) kbd,
body:has(.pdf-editor-page) pre,
body:has(.pdf-editor-page) samp {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

body:has(.admin-container),
body:has(.admin-container) h1,
body:has(.admin-container) h2,
body:has(.admin-container) h3,
body:has(.admin-container) h4,
body:has(.admin-container) h5 {
  font-family:
    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: -0.01em;
}

/* =============================================================
   BUTTONS - project-wide primary + secondary styling.
   Deliberately uses `body .button` / `body.theme-* .button-primary`
   selectors so the specificity matches (or exceeds) every rule in
   base_elements.css. This is the ONLY source of truth for button
   appearance on loopdf.com - nothing leaks in from startup-cms base.
     • Primary:   solid dark-ink (light) / loopdf red (dark), 12px radius.
     • Secondary: surface background, subtle border, lavender hover tint.
   Applies to every page (editor, auth, tool pages, landing, etc.).
   ============================================================= */

/* Buttons - single source of truth. Every rule is theme-prefixed
   (body.theme-light / body.theme-dark) so specificity equals or exceeds
   every rule in base_elements.css (including `body.theme-light .button:hover`
   which was previously beating our plain `body .button:hover`). Reads
   directly from the remapped theme tokens defined above. */

/* ---- Base reset: secondary appearance + resets for the primary too ---- */
body.theme-light .button,
body.theme-light a.button,
body.theme-light button.button,
body.theme-light input[type='submit'].button,
body.theme-light input[type='button'].button,
body.theme-light input[type='reset'].button,
body.theme-light .btn,
body.theme-light a.btn,
body.theme-light button.btn,
body.theme-dark .button,
body.theme-dark a.button,
body.theme-dark button.button,
body.theme-dark input[type='submit'].button,
body.theme-dark input[type='button'].button,
body.theme-dark input[type='reset'].button,
body.theme-dark .btn,
body.theme-dark a.btn,
body.theme-dark button.btn {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 10px !important;
  padding: 12px 20px !important;
  margin: 0 6px 0 0 !important;
  border-radius: 12px !important;
  font-family: inherit !important;
  font-weight: 600 !important;
  font-size: 14.5px !important;
  line-height: 1.2 !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
  border: 1px solid var(--border-color) !important;
  background: var(--card-bg) !important;
  background-image: none !important;
  color: var(--heading-color) !important;
  text-decoration: none !important;
  cursor: pointer;
  white-space: nowrap;
  /* No box-shadow here on purpose: the secondary button lift now comes from
     base_elements.css so every project shares it. Forcing `none !important`
     is what made this project's secondary buttons read as flat next to a
     primary. */
  transform: none !important;
  transition:
    transform 0.15s,
    box-shadow 0.2s,
    background 0.2s,
    border-color 0.15s,
    color 0.15s !important;
}

/* ---- Secondary hover - subtle tint, same border. No jump to brand purple
   (that was reading as a frame). Matches the landing template's ghost CTA:
   background lifts to --info-item-bg, border stays at the soft --border-color. ---- */
body.theme-light .button:hover,
body.theme-light a.button:hover,
body.theme-light button.button:hover,
body.theme-light .btn:hover,
body.theme-light a.btn:hover,
body.theme-light button.btn:hover,
body.theme-dark .button:hover,
body.theme-dark a.button:hover,
body.theme-dark button.button:hover,
body.theme-dark .btn:hover,
body.theme-dark a.btn:hover,
body.theme-dark button.btn:hover {
  background: var(--info-item-bg) !important;
  background-image: none !important;
  border-color: var(--border-color) !important;
  color: var(--heading-color) !important;
  transform: translateY(-1px) !important;
  /* Hover shadow likewise inherited from base_elements.css. */
}

/* Secondary focus - purple outline only on surface-colored buttons. */
body.theme-light .button:focus-visible,
body.theme-light .btn:focus-visible,
body.theme-dark .button:focus-visible,
body.theme-dark .btn:focus-visible {
  outline: 2px solid var(--primary-blue) !important;
  outline-offset: 3px;
}

/* ---- Primary - solid fill, NO border, NO purple glow. Light theme uses
   deep-ink fill with white text. Dark theme uses brand purple with dark-ink
   text. Same look as the landing hero CTA, minus any frame/ring artifacts. ---- */
body.theme-light .button-primary,
body.theme-light a.button-primary,
body.theme-light button.button-primary,
body.theme-light input[type='submit'].button-primary,
body.theme-light .btn-primary,
body.theme-light a.btn-primary,
body.theme-light button.btn-primary {
  background: var(--primary-blue) !important;
  background-image: none !important;
  color: #ffffff !important;
  border: 0 !important;
  outline: none !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  box-shadow: 0 6px 16px -6px rgba(163, 22, 33, 0.42) !important;
}

body.theme-dark .button-primary,
body.theme-dark a.button-primary,
body.theme-dark button.button-primary,
body.theme-dark input[type='submit'].button-primary,
body.theme-dark .btn-primary,
body.theme-dark a.btn-primary,
body.theme-dark button.btn-primary {
  background: var(--primary-blue) !important;
  background-image: none !important;
  color: #ffffff !important;
  border: 0 !important;
  outline: none !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.5) !important;
}

/* ---- Primary hover - same fill, lift + deeper shadow. No tint, no ring. ---- */
body.theme-light .button-primary:hover,
body.theme-light a.button-primary:hover,
body.theme-light button.button-primary:hover,
body.theme-light .btn-primary:hover,
body.theme-light a.btn-primary:hover,
body.theme-light button.btn-primary:hover {
  background: var(--primary-blue-hover) !important;
  background-image: none !important;
  color: #ffffff !important;
  border: 0 !important;
  outline: none !important;
  transform: translateY(-2px) !important;
  box-shadow: 0 12px 24px -8px rgba(163, 22, 33, 0.5) !important;
}

body.theme-dark .button-primary:hover,
body.theme-dark a.button-primary:hover,
body.theme-dark button.button-primary:hover,
body.theme-dark .btn-primary:hover,
body.theme-dark a.btn-primary:hover,
body.theme-dark button.btn-primary:hover {
  background: var(--primary-blue) !important;
  background-image: none !important;
  color: #ffffff !important;
  border: 0 !important;
  outline: none !important;
  transform: translateY(-2px) !important;
  box-shadow: 0 12px 24px -8px rgba(0, 0, 0, 0.6) !important;
}

/* ---- Primary focus - a11y only. Use a dashed-style offset outline that
   doesn't read as a frame, shown only for keyboard-triggered focus. ---- */
body.theme-light .button-primary:focus,
body.theme-light .btn-primary:focus,
body.theme-dark .button-primary:focus,
body.theme-dark .btn-primary:focus {
  outline: none !important;
  border: 0 !important;
}
body.theme-light .button-primary:focus-visible,
body.theme-light .btn-primary:focus-visible,
body.theme-dark .button-primary:focus-visible,
body.theme-dark .btn-primary:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.7) !important;
  outline-offset: -4px;
  border: 0 !important;
}

/* ---- Primary active - snap back, no residual gradient from base ---- */
body.theme-light .button-primary:active,
body.theme-light .btn-primary:active,
body.theme-dark .button-primary:active,
body.theme-dark .btn-primary:active {
  background-image: none !important;
  border: 0 !important;
  outline: none !important;
  transform: translateY(0) !important;
}

/* FontAwesome / SVG glyph colour on primary - defeat base override
   (base has `.button-primary i { color: #fff !important }`). */
body .button-primary i,
body .button-primary .fas,
body .button-primary .fab,
body .button-primary .far,
body .btn-primary i,
body .btn-primary .fas,
body .btn-primary .fab,
body .btn-primary .far,
body .button-primary svg,
body .btn-primary svg {
  color: inherit !important;
  fill: currentColor;
  stroke: currentColor;
}

/* Button icons sized consistently across the whole project */
body .button .fas,
body .button .fab,
body .button .far,
body .button i,
body .button svg,
body .btn .fas,
body .btn .fab,
body .btn .far,
body .btn i,
body .btn svg {
  font-size: 0.95em;
  color: inherit !important;
}

/* Hero Section */
.hero-section {
  position: relative;
  margin: 2rem 0 4rem;
  padding: 4rem 0 5rem;
  overflow: hidden;
}

.hero-background-animation {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(
    135deg,
    #d62828 0%,
    #a31621 25%,
    #ff7a59 50%,
    #4facfe 75%,
    #00f2fe 100%
  );
  background-size: 400% 400%;
  animation: heroGradientShift 15s ease infinite;
  opacity: 0.05;
  z-index: 0;
  pointer-events: none;
}

@keyframes heroGradientShift {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.hero-container {
  max-width: 100%;
  width: 100%;
  margin: 0 auto;
  padding: 0;
  position: relative;
  z-index: 1;
}

.hero-content {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 3rem;
  align-items: center;
  align-content: center;
  overflow: visible;
}

.hero-text {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  width: 100%;
  align-items: center;
  overflow: visible;
}

.hero-title,
.hero-description {
  text-align: center;
  width: 100%;
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
}

.hero-description {
  font-size: 1.4rem;
  color: var(--text-color);
  margin: 0;
  line-height: 1.7;
  font-weight: 400;
}

.hero-features-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  padding: 1.5rem;
  overflow: visible;
}

.hero-feature-card {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-medium);
  padding: 1.5rem;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 1.5rem;
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease,
    transform 0.15s ease;
  opacity: 1;
}

.hero-feature-card:hover {
  border-color: #d62828;
  box-shadow: 0 6px 24px rgba(214, 40, 40, 0.2);
  transform: translateY(-4px) scale(1.02);
  animation: none;
}

.hero-feature-icon {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radius-small);
  background: linear-gradient(
    135deg,
    rgba(110, 231, 183, 0.95) 0%,
    rgba(52, 211, 153, 0.98) 50%,
    rgba(16, 185, 129, 0.95) 100%
  );
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 1.8rem;
  flex-shrink: 0;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 2px solid rgba(255, 255, 255, 0.35);
  box-shadow:
    0 6px 20px rgba(110, 231, 183, 0.35),
    0 2px 8px rgba(52, 211, 153, 0.2),
    inset 0 2px 4px rgba(255, 255, 255, 0.3),
    inset 0 -1px 2px rgba(0, 0, 0, 0.15);
  animation:
    iconPulse 2s ease-in-out infinite,
    iconGradientShift 4s ease infinite;
  background-size: 200% 200%;
}

@keyframes iconPulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.05);
  }
}

@keyframes iconGradientShift {
  0%,
  100% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
}

.hero-feature-card:hover .hero-feature-icon {
  transform: scale(1.1) rotate(5deg);
  background: linear-gradient(
    135deg,
    rgba(52, 211, 153, 0.98) 0%,
    rgba(110, 231, 183, 1) 50%,
    rgba(16, 185, 129, 0.98) 100%
  );
  background-size: 200% 200%;
  box-shadow:
    0 10px 28px rgba(110, 231, 183, 0.5),
    0 4px 12px rgba(52, 211, 153, 0.3),
    inset 0 2px 6px rgba(255, 255, 255, 0.4),
    inset 0 -1px 3px rgba(0, 0, 0, 0.2);
  border-color: rgba(255, 255, 255, 0.45);
  border-width: 2px;
  animation: iconGradientShift 2s ease infinite;
}

.hero-feature-text {
  color: var(--text-color);
  font-size: 1.6rem;
  line-height: 1.5;
  margin: 0;
  font-weight: 400;
  flex: 1;
}

.hero-upload {
  display: flex;
  justify-content: center;
  align-items: center;
  align-self: center;
  height: 100%;
}

.hero-upload-box {
  width: 100%;
  max-width: 560px;
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.95) 0%,
    rgba(255, 255, 255, 0.98) 100%
  );
  backdrop-filter: blur(10px);
  border: 2px solid rgba(0, 0, 0, 0.08);
  border-radius: 24px;
  padding: 3.5rem 2.5rem;
  text-align: center;
  position: relative;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  overflow: hidden;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
  animation: heroUploadFloat 6s ease-in-out infinite;
}

@keyframes heroUploadFloat {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

.hero-upload-box:hover {
  transform: translateY(-8px) scale(1.02);
  box-shadow: 0 20px 60px rgba(214, 40, 40, 0.15);
  border-color: rgba(214, 40, 40, 0.3);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.98) 0%,
    rgba(255, 255, 255, 1) 100%
  );
}

.hero-upload-box.drag-over {
  transform: translateY(-8px) scale(1.05);
  box-shadow: 0 25px 70px rgba(214, 40, 40, 0.2);
  animation: heroUploadPulse 1s ease-in-out infinite;
  border-color: rgba(214, 40, 40, 0.5);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 1) 0%,
    rgba(255, 255, 255, 1) 100%
  );
}

@keyframes heroUploadPulse {
  0%,
  100% {
    transform: translateY(-8px) scale(1.05);
  }
  50% {
    transform: translateY(-12px) scale(1.06);
  }
}

.hero-upload-process {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2rem;
  pointer-events: none;
  z-index: 1;
  width: calc(100% - 2.5rem);
  max-width: 100%;
}

.process-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  animation: heroProcessPulse 3s ease-in-out infinite;
}

.process-step:nth-child(1) {
  animation-delay: 0s;
}

.process-step:nth-child(3) {
  animation-delay: 1s;
}

.process-step:nth-child(5) {
  animation-delay: 2s;
}

.process-step i {
  font-size: 2.5rem;
  color: #d62828;
  animation: heroStepIcon 3s ease-in-out infinite;
}

.process-step:nth-child(1) i {
  animation-delay: 0s;
}

.process-step:nth-child(3) i {
  animation-delay: 1s;
}

.process-step:nth-child(5) i {
  animation-delay: 2s;
}

.process-step span {
  font-size: 1rem;
  font-weight: 700;
  color: #4a5568;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.process-arrow {
  color: rgba(214, 40, 40, 0.7);
  font-size: 1.5rem;
  animation: heroArrowPulse 3s ease-in-out infinite;
}

.process-arrow:nth-child(2) {
  animation-delay: 0.5s;
}

.process-arrow:nth-child(4) {
  animation-delay: 1.5s;
}

@keyframes heroProcessPulse {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.6;
  }
  50% {
    transform: translateY(-5px);
    opacity: 1;
  }
}

@keyframes heroStepIcon {
  0%,
  100% {
    transform: scale(1);
    color: #d62828;
  }
  50% {
    transform: scale(1.15);
    color: #a31621;
  }
}

@keyframes heroArrowPulse {
  0%,
  100% {
    opacity: 0.5;
    transform: translateX(0);
  }
  50% {
    opacity: 0.9;
    transform: translateX(4px);
  }
}

.hero-upload-content {
  position: relative;
  z-index: 2;
  padding-top: 6rem;
}

.hero-upload-icon-wrapper {
  display: none;
}

.hero-upload-icon {
  font-size: 5rem;
  background: linear-gradient(135deg, #d62828 0%, #a31621 50%, #ff7a59 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  position: relative;
  z-index: 2;
  animation: heroIconFloat 3s ease-in-out infinite;
  display: inline-block;
}

@keyframes heroIconFloat {
  0%,
  100% {
    transform: translateY(0) rotate(0deg);
  }
  25% {
    transform: translateY(-15px) rotate(5deg);
  }
  75% {
    transform: translateY(-5px) rotate(-5deg);
  }
}

.hero-upload-icon-bg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 120px;
  height: 120px;
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.15) 0%,
    rgba(163, 22, 33, 0.15) 100%
  );
  border-radius: 50%;
  z-index: 1;
  animation: heroIconBgPulse 3s ease-in-out infinite;
}

@keyframes heroIconBgPulse {
  0%,
  100% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0.6;
  }
  50% {
    transform: translate(-50%, -50%) scale(1.3);
    opacity: 0.3;
  }
}

.hero-upload-box.drag-over .hero-upload-icon {
  animation: heroIconSpin 0.6s ease-in-out infinite;
}

@keyframes heroIconSpin {
  0%,
  100% {
    transform: translateY(0) rotate(0deg) scale(1);
  }
  50% {
    transform: translateY(-10px) rotate(180deg) scale(1.1);
  }
}

.hero-upload-title {
  font-size: 1.6rem;
  font-weight: 700;
  margin: 0 0 0.75rem;
  background: linear-gradient(
    135deg,
    var(--text-color) 0%,
    var(--link) 60%,
    rgba(214, 40, 40, 0.9) 100%
  );
  background-size: 200% 200%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation: heroTitleGradientShift 8s ease infinite;
}

.hero-upload-hint {
  color: var(--muted-text);
  font-size: 1.4rem;
  margin: 0 0 2rem;
  font-weight: 400;
}

.hero-upload-separator {
  display: flex;
  align-items: center;
  margin: 1.5rem 0;
  position: relative;
}

.hero-upload-separator::before,
.hero-upload-separator::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-color);
}

.hero-upload-separator span {
  padding: 0 1rem;
  color: var(--muted-text);
  font-size: 1.25rem;
  font-weight: 600;
}

.hero-upload-button {
  font-size: 1.2rem;
  padding: 1rem 2.5rem;
  background: linear-gradient(135deg, #d62828 0%, #a31621 100%);
  border: none;
  color: white;
  font-weight: 700;
  border-radius: 12px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 15px rgba(214, 40, 40, 0.4);
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
}

.hero-upload-button::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.3),
    transparent
  );
  transition: left 0.5s ease;
}

.hero-upload-button:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 25px rgba(214, 40, 40, 0.5);
  background: linear-gradient(135deg, #a31621 0%, #d62828 100%);
}

.hero-upload-button:hover::before {
  left: 100%;
}

.hero-upload-button:active {
  transform: translateY(-1px);
  box-shadow: 0 4px 15px rgba(214, 40, 40, 0.4);
}

.hero-upload-button i {
  font-size: 1.1rem;
}

.hero-upload-limit {
  margin-top: 1.5rem;
  color: var(--muted-text);
  font-size: 1.4rem;
  font-weight: 400;
}

.hero-upload-formats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* Hero upload PDF/convert choice modal - uses base_modal.css .modal, .modal-content, .modal-header, .modal-body */
.hero-choice-modal-backdrop {
  position: absolute;
  inset: 0;
}

.hero-choice-modal-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  color: var(--muted-text, #94a3b8);
  margin: 0 0 0.25rem;
  font-weight: 700;
}

#heroPdfChoiceModal .modal-header h3 {
  margin: 0;
  font-size: 1.35rem;
}

.hero-choice-modal-subtitle {
  margin: 0.35rem 0 0;
  color: var(--muted-text, #94a3b8);
}

.hero-choice-modal-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
}

.hero-choice-card {
  padding: 0.75rem;
  border-radius: 10px;
  border: 1px solid var(--border-muted, rgba(255, 255, 255, 0.08));
  background: rgba(255, 255, 255, 0.02);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: center;
  text-align: center;
}

.hero-choice-card-content {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  flex: 1 1 auto;
  min-height: 0;
}

.hero-choice-card-label {
  display: block;
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--link, #6366f1);
  margin: 0;
}

.hero-choice-filename-block,
.hero-choice-select {
  width: 100%;
  min-height: 3.75rem;
  padding: 0.75rem 0.85rem;
  border-radius: 8px;
  border: 1px solid var(--border-muted, rgba(255, 255, 255, 0.12));
  background: var(--input-bg, var(--card-bg, #0f172a));
  color: var(--text-color, #e5e7eb);
  font-size: 0.95rem;
  box-sizing: border-box;
  line-height: 1.35;
}

.hero-choice-filename-block {
  font-weight: 600;
  word-break: break-word;
  display: flex;
  align-items: center;
  height: 3.75rem;
  margin-bottom: 1.5rem;
}

.hero-choice-select {
  cursor: pointer;
  height: 3.75rem;
}

.hero-choice-card-hint {
  margin: 0;
  color: var(--muted-text, #94a3b8);
  font-size: 0.875rem;
  line-height: 1.4;
}

.hero-choice-action {
  align-self: center;
  flex-shrink: 0;
  margin-top: 0.5rem;
}

.format-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem 1rem;
  border-radius: 12px;
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: #ffffff;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.3),
    0 0 8px rgba(0, 0, 0, 0.2);
  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease;
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
  z-index: 1;
}

.format-badge > * {
  position: relative;
  z-index: 2;
}

.format-badge::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(
    circle at center,
    rgba(255, 255, 255, 0.25) 0%,
    transparent 70%
  );
  opacity: 0.5;
  transition: opacity 0.2s ease;
  z-index: 1;
}

.format-badge:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.format-badge:hover::before {
  opacity: 0.8;
}

.format-pdf {
  background: linear-gradient(
    135deg,
    rgba(229, 62, 62, 0.9) 0%,
    rgba(197, 48, 48, 0.95) 50%,
    rgba(229, 62, 62, 0.85) 100%
  );
}

.format-word {
  background: linear-gradient(
    135deg,
    rgba(41, 128, 185, 0.9) 0%,
    rgba(52, 152, 219, 0.95) 50%,
    rgba(41, 128, 185, 0.85) 100%
  );
}

.format-excel {
  background: linear-gradient(
    135deg,
    rgba(39, 174, 96, 0.9) 0%,
    rgba(46, 213, 115, 0.95) 50%,
    rgba(39, 174, 96, 0.85) 100%
  );
}

.format-ppt {
  background: linear-gradient(
    135deg,
    rgba(231, 76, 60, 0.9) 0%,
    rgba(235, 77, 75, 0.95) 50%,
    rgba(231, 76, 60, 0.85) 100%
  );
}

.format-jpg {
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.9) 0%,
    rgba(163, 22, 33, 0.95) 50%,
    rgba(214, 40, 40, 0.85) 100%
  );
}

.format-png {
  background: linear-gradient(
    135deg,
    rgba(72, 187, 120, 0.9) 0%,
    rgba(56, 161, 105, 0.95) 50%,
    rgba(72, 187, 120, 0.85) 100%
  );
}

.format-gif {
  background: linear-gradient(
    135deg,
    rgba(237, 137, 54, 0.9) 0%,
    rgba(221, 107, 32, 0.95) 50%,
    rgba(237, 137, 54, 0.85) 100%
  );
}

.format-webp {
  background: linear-gradient(
    135deg,
    rgba(66, 153, 225, 0.9) 0%,
    rgba(49, 130, 206, 0.95) 50%,
    rgba(66, 153, 225, 0.85) 100%
  );
}

/* Dark theme upload section */
body.theme-dark .hero-upload-box {
  background: var(--card-bg);
  border-color: rgba(255, 255, 255, 0.15);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}

body.theme-dark .hero-upload-box:hover {
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  border-color: rgba(255, 255, 255, 0.25);
  background: var(--card-bg);
}

body.theme-dark .hero-upload-box.drag-over {
  box-shadow: 0 25px 70px rgba(0, 0, 0, 0.35);
  border-color: rgba(255, 255, 255, 0.3);
  background: var(--card-bg);
}

body.theme-dark .hero-upload-icon-bg {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.08) 0%,
    rgba(255, 255, 255, 0.12) 100%
  );
}

body.theme-dark .hero-upload-process {
  opacity: 0.7;
}

body.theme-dark .process-step i {
  color: #ff6b61;
}

body.theme-dark .process-step span {
  color: #e2e8f0;
}

body.theme-dark .process-arrow {
  color: rgba(255, 107, 97, 0.8);
}

body.theme-dark .process-step i {
  animation: heroStepIconDark 3s ease-in-out infinite;
}

@keyframes heroStepIconDark {
  0%,
  100% {
    transform: scale(1);
    color: #ff6b61;
  }
  50% {
    transform: scale(1.15);
    color: #ffa59e;
  }
}

body.theme-dark .hero-upload-separator::before,
body.theme-dark .hero-upload-separator::after {
  background: rgba(255, 255, 255, 0.15);
}

body.theme-dark .hero-upload-separator span {
  color: rgba(255, 255, 255, 0.7);
}

body.theme-dark .format-badge {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.5),
    0 0 10px rgba(0, 0, 0, 0.3);
  color: #ffffff;
  font-weight: 700;
}

body.theme-dark .format-badge:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

/* Responsive Hero Section */
@media (max-width: 968px) {
  .hero-content {
    grid-template-columns: 1fr;
    gap: 4rem;
  }

  .hero-text {
    width: 100%;
    align-items: center;
  }

  .hero-title,
  .hero-description {
    text-align: center;
  }

  .hero-title {
    font-size: clamp(31px, 4.9vw, 46px);
  }

  .hero-description {
    font-size: 1.2rem;
  }

  .hero-upload-box {
    max-width: 100%;
  }

  .hero-features-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.25rem;
  }

  .hero-feature-text {
    font-size: 1.4rem;
  }
}

@media (max-width: 768px) {
  .hero-section {
    margin: 1rem 0 3rem;
    padding: 3rem 0 4rem;
  }

  .hero-title {
    font-size: clamp(28px, 6vw, 34px);
    line-height: 1.2;
  }

  .hero-description {
    font-size: 1.1rem;
  }

  .hero-features-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }

  .hero-feature-card {
    padding: 1.25rem;
    gap: 1.25rem;
  }

  .hero-feature-icon {
    width: 3rem;
    height: 3rem;
    font-size: 1.5rem;
  }

  .hero-feature-text {
    font-size: 1.3rem;
  }

  .hero-upload-box {
    padding: 2.5rem 2rem;
  }

  .hero-upload-content {
    padding-top: 5rem;
  }

  .hero-upload-process {
    gap: 1.25rem;
    top: 15px;
    width: calc(100% - 2rem);
  }

  .process-step i {
    font-size: 2rem;
  }

  .process-step span {
    font-size: 0.85rem;
  }

  .process-arrow {
    font-size: 1.25rem;
  }

  .hero-upload-icon {
    font-size: 4rem;
  }

  .hero-upload-title {
    font-size: 1.4rem;
  }

  .hero-upload-button {
    font-size: 1.1rem;
    padding: 0.875rem 2rem;
  }

  .hero-upload-formats {
    gap: 0.5rem;
    margin-top: 1.25rem;
  }

  .format-badge {
    padding: 0.4rem 0.75rem;
    font-size: 0.75rem;
  }
}

/* Tool Grid */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1.25rem;
  margin-bottom: 2rem;
  max-width: 100%;
  justify-content: start;
}

.tool-card {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  padding: 1.75rem 1.5rem;
  text-align: center;
  cursor: pointer;
  transition:
    transform 0.28s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1),
    border-color 0.2s ease;
  text-decoration: none;
  display: block;
  color: inherit;
  position: relative;
  width: 100%;
  margin: 0 auto;
}

.tool-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
  text-decoration: none;
  color: inherit;
}

.tool-card.last-used {
  border-color: var(--primary-blue);
  border-width: 2px;
  background: color-mix(in srgb, var(--primary-blue) 8%, transparent);
}

.tool-card.last-used::after {
  content: '✓';
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  background: var(--primary-blue);
  color: white;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  font-weight: bold;
}

.tool-icon {
  font-size: 3rem;
  margin-bottom: 0.75rem;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  display: block;
}

.tool-icon img {
  width: 56px;
  height: 56px;
  display: block;
  margin: 0 auto;
}

.tool-icon.tool-icon-conversion {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-size: 2.4rem;
  line-height: 1;
}

.tool-icon.tool-icon-conversion .tool-icon-conversion-arrow {
  font-size: 1.5rem;
  opacity: 0.72;
}

.tool-card:hover .tool-icon {
  transform: scale(1.05);
  opacity: 0.9;
}

.tool-card h3 {
  color: var(--heading-color);
  font-weight: 600;
  margin-bottom: 0.5rem;
  font-size: 20px;
  line-height: 1.4;
  letter-spacing: 0.02em;
}

.tool-card p {
  color: var(--muted-text);
  font-size: 1.35rem;
  margin: 0;
  line-height: 1.6;
  letter-spacing: 0.01em;
}

/* Tool cards are <a> elements; the base anchor styles repurpose border-bottom
   as a link-underline and zero it out, leaving the card with only three
   borders. Restore the full box border so every card reads as closed. */
a.tool-card {
  border-bottom-width: 1px !important;
  border-bottom-style: solid !important;
  border-bottom-color: var(--border-color) !important;
}

/* Tools Section */
.tools-section {
  text-align: center;
  margin-bottom: 3rem;
}

.tools-section-title {
  text-align: center;
  margin-bottom: 1rem;
}

.tools-section-description {
  text-align: center;
  font-size: 1.35rem;
  color: var(--muted-text);
  margin-bottom: 0;
  max-width: 600px;
  margin-left: auto;
  margin-right: auto;
  line-height: 1.6;
}

.tool-privacy-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin: 10px auto 0;
  padding: 6px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--primary-blue) 25%, transparent);
  background: color-mix(in srgb, var(--primary-blue) 6%, transparent);
  color: var(--primary-blue);
  cursor: pointer;
  transition:
    background 0.2s,
    border-color 0.2s;
  width: fit-content;
}

.tool-privacy-icon svg {
  display: block;
}

.tool-privacy-icon:hover {
  background: color-mix(in srgb, var(--primary-blue) 12%, transparent);
  border-color: color-mix(in srgb, var(--primary-blue) 45%, transparent);
}

/* ── Convert PDF page ──────────────────────────────────────────── */
.convert-page {
  padding-top: 2.5rem;
}

.convert-page-head {
  margin-bottom: 2.5rem;
}

.convert-page h1 {
  font-family: 'Fredoka', system-ui, sans-serif;
  font-weight: 600;
  font-size: 40px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
  text-wrap: balance;
}

.convert-page-dek {
  font-size: 17px;
  line-height: 1.55;
  color: var(--muted-text);
  margin: 0;
  max-width: 52ch;
}

.convert-page .tool-grid {
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

/* Prevent pdf-landing from overriding the page background/color */
.convert-page.pdf-landing {
  background: transparent;
  color: inherit;
}

/* Tool Interface */
.tool-interface {
  margin-top: 2rem;
}

.tool-interface h2 {
  color: var(--heading-color);
  font-size: clamp(20px, 2.7vw, 27px);
  margin-bottom: 1.5rem;
  line-height: 1.25;
}

.tool-interface h2 i {
  color: var(--link);
  margin-right: 0.5rem;
}

.tool-interface h3 {
  font-size: clamp(18px, 2.4vw, 24px);
  line-height: 1.3;
}

.tool-interface h4 {
  font-size: clamp(15px, 1.9vw, 20px);
  line-height: 1.35;
}

/* File Lists */
.file-list {
  margin-top: 1rem;
  margin-bottom: 1rem;
}

/* Images-to-PDF: grid of image cards */
.file-list-images-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 0.75rem;
}

.file-list-images-grid .file-item-with-thumb {
  flex-direction: column;
  align-items: stretch;
  text-align: center;
  padding: 0.5rem;
  margin-bottom: 0;
  position: relative;
}

.file-list-images-grid .file-item-thumb-img {
  width: 100%;
  height: 80px;
  min-width: 0;
  min-height: 80px;
  margin-right: 0;
  margin-bottom: 0.4rem;
}

.file-list-images-grid .file-item-name {
  font-size: 0.75rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-right: 0;
  margin-bottom: 0.15rem;
}

.file-list-images-grid .file-item-size {
  font-size: 0.7rem;
  margin-left: 0;
  margin-right: 0;
  margin-bottom: 0.35rem;
}

.file-list-images-grid .file-item-remove {
  align-self: center;
  margin: 5px 0 0 0;
}

/* Images grid: drag handle */
.file-list-images-grid .file-item-drag-handle-grid {
  position: absolute;
  top: 0.25rem;
  left: 0.25rem;
  z-index: 2;
  opacity: 0;
  transition: opacity 0.2s ease;
  background: rgba(var(--card-bg-rgb, 255, 255, 255), 0.85);
  border-radius: var(--radius-small);
  padding: 0.15rem 0.3rem;
  font-size: 0.75rem;
}

.file-list-images-grid .file-item-with-thumb:hover .file-item-drag-handle-grid {
  opacity: 1;
}

/* Images grid: horizontal drag-over indicators (left/right) */
.file-list-images-grid .file-item-drag-over-left::before {
  content: '';
  position: absolute;
  top: 0;
  left: -2px;
  bottom: 0;
  width: 3px;
  height: auto;
  background: var(--link);
  border-radius: 2px;
}

.file-list-images-grid .file-item-drag-over-right::after {
  content: '';
  position: absolute;
  top: 0;
  right: -2px;
  bottom: 0;
  width: 3px;
  height: auto;
  background: var(--link);
  border-radius: 2px;
}

.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem;
  background: var(--input-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  margin-bottom: 0.5rem;
}

.file-item-thumb-img {
  width: 48px;
  height: 48px;
  min-width: 48px;
  min-height: 48px;
  object-fit: cover;
  border-radius: var(--radius-small);
  border: 1px solid var(--border-color);
  margin-right: 0.75rem;
  flex-shrink: 0;
  background: var(--card-bg);
}

.file-item-with-thumb .file-item-name {
  margin-right: 0.5rem;
}

.file-item-name {
  flex: 1;
  color: var(--text-color);
  font-size: 0.9em;
  word-break: break-all;
}

.file-item-size {
  color: var(--muted-text);
  font-size: 0.85em;
  margin-left: 1rem;
  margin-right: 0.5rem;
}

.file-item-remove {
  background: var(--input-bg);
  border: 1px solid var(--border-color);
  color: var(--muted-text);
  cursor: pointer;
  padding: 0;
  border-radius: 50%;
  transition: all 0.2s ease;
  width: 32px;
  height: 32px;
  min-width: 32px;
  min-height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  line-height: 0;
  box-sizing: border-box;
  position: relative;
}

.file-item-remove i {
  margin: 0 !important;
  padding: 0 !important;
  line-height: 1;
  display: block;
  width: 1em;
  height: 1em;
  text-align: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.file-item-remove:hover {
  background: rgba(220, 53, 69, 0.15);
  border-color: #dc3545;
  color: #dc3545;
  transform: scale(1.05);
}

.file-item-remove:active {
  transform: scale(0.95);
}

/* Draggable File Items for Merge Tool */
.file-item-draggable {
  cursor: move;
  transition: all 0.2s ease;
}

.file-item-draggable:hover {
  border-color: var(--link);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.file-item-dragging {
  opacity: 0.5;
  border-color: var(--link);
  box-shadow: 0 4px 12px rgba(var(--link-rgb, 0, 123, 255), 0.3);
}

.file-item-drag-over {
  border-color: var(--link);
  background: rgba(var(--link-rgb, 0, 123, 255), 0.05);
  position: relative;
}

.file-item-drag-over-top::before {
  content: '';
  position: absolute;
  top: -2px;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--link);
  border-radius: 2px;
}

.file-item-drag-over-bottom::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--link);
  border-radius: 2px;
}

.file-item-drag-handle {
  color: var(--muted-text);
  cursor: grab;
  padding: 0.25rem;
  display: flex;
  align-items: center;
  transition: color 0.2s ease;
}

.file-item-drag-handle:active {
  cursor: grabbing;
}

.file-item-draggable:hover .file-item-drag-handle {
  color: var(--link);
}

/* File Info */
.file-info {
  margin-top: 1rem;
  padding: 1rem;
  background: var(--input-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  font-size: 1.4rem;
}

.file-info-item {
  display: flex;
  justify-content: space-between;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--border-color);
  font-size: 1.4rem;
}

.file-info-item:last-child {
  border-bottom: none;
}

.file-info-item strong {
  color: var(--heading-color);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.file-info-icon {
  color: var(--link);
  font-size: 1.8rem;
}

.file-info-item span {
  color: var(--text-color);
}

/* Watermark PDF: document info (left) + settings (right) */
.watermark-preview-in-info {
  margin-top: 8px;
}

.watermark-type-toggle {
  display: flex;
  gap: 12px;
  margin-bottom: 10px;
}

.watermark-type-toggle label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.watermark-text-section,
.watermark-image-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.watermark-text-row {
  display: flex;
  gap: 10px;
}

.watermark-text-col {
  flex: 1 1 0;
}

.watermark-color-input {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 32px;
  padding: 0;
  border-radius: 6px;
  border: 1px solid var(--border-color);
  background: var(--card-bg);
  cursor: pointer;
}

.watermark-color-input::-webkit-color-swatch-wrapper {
  padding: 0;
}

.watermark-color-input::-webkit-color-swatch {
  border: none;
  border-radius: 4px;
}

.watermark-color-input::-moz-color-swatch {
  border: none;
  border-radius: 4px;
}

.watermark-opacity-label,
.watermark-position-label,
.watermark-pages-label {
  margin-top: 4px;
}

#watermarkOptions input[type='text'],
#watermarkOptions input[type='number'],
#watermarkOptions select {
  width: 100%;
}

#watermarkOptions .button {
  width: 100%;
  margin-top: 12px;
}

/* Page Buttons */
.page-checkboxes {
  margin-top: 0.5rem;
}

.page-checkboxes .base-multi-select-button-group {
  flex-wrap: wrap;
}

.page-checkboxes .base-multi-select-button-group__btn {
  flex: 0 0 auto !important;
}

/* Result Area */
.result-area {
  margin-top: 1.5rem;
  padding: 1.5rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
}

.result-area.success {
  border-color: #66bb6a;
  background: rgba(102, 187, 106, 0.05);
}

.result-area.error {
  border-color: #dc3545;
  background: rgba(220, 53, 69, 0.05);
}

.result-message {
  margin-bottom: 1rem;
  color: var(--text-color);
}

.result-message.success {
  color: #66bb6a;
}

.result-message.error {
  color: #dc3545;
}

.result-download {
  margin-top: 1rem;
}

.result-edit-pdf {
  margin-top: 1rem;
}

.result-continue {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
}

.result-continue-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.result-continue-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--heading-color);
}

.result-continue-more {
  font-size: 13px;
  color: var(--muted-text);
  text-decoration: none;
}

.result-continue-more:hover {
  color: var(--heading-color);
  text-decoration: underline;
}

.result-continue-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

.continue-tool-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-medium);
  background: var(--card-bg);
  text-decoration: none;
  color: inherit;
  transition: all 0.2s ease;
}

.continue-tool-card:hover {
  border-color: #d62828;
  box-shadow: 0 4px 12px rgba(214, 40, 40, 0.15);
  transform: translateY(-1px);
}

.continue-tool-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.04);
  color: var(--continue-tool-color, #d62828);
  flex-shrink: 0;
  font-size: 16px;
}

.continue-tool-card i {
  margin-right: 0 !important;
}

.continue-tool-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--heading-color);
  flex: 1;
}

.continue-tool-arrow {
  color: var(--muted-text);
  font-size: 12px;
}

/* Related-tool icons unified to the brand red (were a Tailwind rainbow that
   clashed with the red theme). */
.continue-tool-card[data-tool] {
  --continue-tool-color: var(--primary-blue);
}

body.theme-dark .continue-tool-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

body.theme-dark .continue-tool-icon {
  background: rgba(255, 255, 255, 0.08);
}

.result-edit-pdf-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  background: rgba(0, 0, 0, 0.02);
}

.result-edit-pdf-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-medium);
  border: 1px solid var(--border-color);
  background: rgba(0, 0, 0, 0.04);
  color: var(--muted-text);
  font-size: 1.25rem;
  flex-shrink: 0;
  padding: 16px;
  margin-left: 10px;
}

.result-edit-pdf-icon i {
  opacity: 0.9;
  margin-right: 0 !important;
}

.result-edit-pdf-text {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--text-color);
  flex: 1;
  min-width: 0;
}

.result-edit-pdf-inner .button {
  flex-shrink: 0;
  margin-left: auto;
}

@media (max-width: 768px) {
  .result-edit-pdf-inner {
    flex-direction: column;
    align-items: stretch;
  }
  .result-edit-pdf-inner .button {
    margin-left: 0;
  }
}

.result-stats {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border-color);
  font-size: 0.9rem;
  color: var(--muted-text);
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.5rem;
}

.result-stats-item {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-bottom: 0;
}

.result-stats-item strong {
  font-weight: 600;
  font-size: 0.9rem;
}

.result-stats-item:last-child {
  margin-bottom: 0;
}

/* Loading State */
.loading {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 3px solid rgba(0, 0, 0, 0.1);
  border-radius: 50%;
  border-top-color: var(--link);
  animation: spin 0.8s linear infinite;
  margin-right: 0.5rem;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Image Preview Grid */
.image-preview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
  margin-top: 1rem;
}

.image-preview-item {
  position: relative;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  overflow: hidden;
  background: transparent;
  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease,
    border-color 0.2s ease;
  padding: 0.6rem;
  text-align: center;
}

.image-preview-item img,
.image-preview-image {
  width: 100%;
  height: auto;
  display: block;
  cursor: pointer;
  transition:
    transform 0.2s ease,
    opacity 0.2s ease;
  margin-bottom: 0.5rem;
}

.image-preview-page {
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--text-color);
  margin-bottom: 0.4rem;
}

.image-preview-item:hover {
  border-color: var(--link);
  box-shadow: 0 8px 18px rgba(15, 23, 42, 0.15);
  transform: translateY(-2px);
}

.image-preview-item:hover img {
  transform: scale(1.02);
}

.image-preview-download {
  margin-top: 0.6rem;
  padding: 0;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 64px;
  height: 40px;
}

.image-preview-download i {
  display: block;
  line-height: 1;
  font-size: 1.05rem;
  width: 1em;
  height: 1em;
}

.image-preview-label {
  padding: 0.5rem;
  text-align: center;
  font-size: 0.85em;
  color: var(--muted-text);
  background: var(--card-bg);
}

.image-preview-meta {
  margin-top: 0.25rem;
  font-size: 0.75em;
  color: var(--muted-text);
}

.image-preview-actions {
  display: flex;
  justify-content: center;
  padding: 0 0.5rem 0.5rem;
  background: transparent;
}

.image-preview-button,
.image-preview-download {
  padding: 0.45rem 0.9rem;
  font-size: 0.9em;
  background: transparent;
  border: 1px solid var(--border-color);
  color: var(--text-color);
}

.image-preview-download {
  padding: 0.4rem 0.55rem;
  border-radius: 8px;
  line-height: 1;
}

.image-preview-download i {
  font-size: 0.95rem;
}

.extract-images-actions {
  margin-top: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.extract-images-toolbar {
  margin-top: 1rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.extract-images-toolbar label {
  margin: 0;
  color: var(--heading-color);
  font-size: 1.1rem;
  font-weight: 600;
}

.extract-images-toolbar select {
  max-width: 220px;
  min-height: 44px;
}

.extract-file-boxes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1rem;
}

.extract-file-box {
  padding: 1.5rem;
  border-radius: var(--radius-large);
  border: 1px solid var(--border-color);
  background: transparent;
  text-align: center;
  transition: all 0.3s ease;
}

.extract-file-box:hover {
  border-color: #d62828;
  transform: translateY(-2px);
}

.extract-file-box-icon {
  width: 64px;
  height: 64px;
  margin: 0 auto 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.12) 0%,
    rgba(163, 22, 33, 0.12) 100%
  );
  color: #d62828;
  font-size: 1.8rem;
}

.extract-file-box-value {
  font-size: 1.55rem;
  color: var(--heading-color);
  word-break: break-word;
  font-weight: 600;
}

.extract-file-box-label {
  font-size: 1.05rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--heading-color);
  margin-bottom: 0.5rem;
  font-weight: 600;
}

.extract-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--border-color);
  color: var(--text-color);
  font-size: 1.25rem;
  font-weight: 600;
}

.extract-badge i {
  font-size: 1.2rem;
}

.extract-result-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.extract-result-header {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}

.extract-result-title {
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--heading-color);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.extract-result-subtitle {
  font-size: 1.2rem;
  color: var(--text-color);
  font-weight: 500;
}

.extract-result-actions {
  margin: 0;
}

.extract-result-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.extract-stat-card {
  padding: 0.75rem;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  background: var(--input-bg);
  text-align: center;
}

.extract-stat-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-text);
}

.extract-stat-value {
  margin-top: 0.35rem;
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--heading-color);
}

.extract-result-message {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-small);
  font-weight: 500;
}

.extract-result-message.success {
  background: rgba(102, 187, 106, 0.12);
  color: #4caf50;
}

.extract-result-message.error {
  background: rgba(220, 53, 69, 0.12);
  color: #dc3545;
}

/* OCR Tool Styles */
.ocr-progress {
  margin-top: 1.5rem;
  padding: 1rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: var(--input-bg);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 0.75rem;
}

.progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #d62828, #a31621);
  border-radius: 999px;
  transition: width 0.3s ease;
  width: 0%;
}

.progress-text {
  text-align: center;
  color: var(--text-color);
  font-size: 0.95rem;
  margin: 0;
}

.ocr-result-container {
  padding: 1rem 0;
}

.ocr-result-container h3 {
  margin-bottom: 1rem;
  color: var(--heading-color);
  font-size: 1.3rem;
}

.ocr-text-preview {
  max-height: 400px;
  overflow-y: auto;
  padding: 1rem;
  background: var(--input-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  font-family: 'Courier New', monospace;
  font-size: 1.25rem;
  line-height: 1.6;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: var(--text-color);
}

.ocr-result-message {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-small);
  font-weight: 500;
}

.ocr-result-message.success {
  background: rgba(102, 187, 106, 0.12);
  color: #4caf50;
}

.ocr-result-message.error {
  background: rgba(220, 53, 69, 0.12);
  color: #dc3545;
}

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

/* Drag & Drop Zone */
.dropzone {
  border: 2px dashed var(--border-color);
  border-radius: var(--radius-large);
  padding: 3rem 2rem;
  text-align: center;
  background: var(--card-bg);
  transition: all 0.3s ease;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.dropzone::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(var(--link-rgb, 0, 123, 255), 0.1),
    transparent
  );
  transition: left 0.5s ease;
}

.dropzone:hover {
  border-color: var(--link);
  background: rgba(var(--link-rgb, 0, 123, 255), 0.02);
}

.dropzone:hover::before {
  left: 100%;
}

.dropzone.drag-over {
  border-color: var(--link);
  background: rgba(var(--link-rgb, 0, 123, 255), 0.1);
  transform: scale(1.02);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}

.dropzone.drag-over::before {
  left: 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0% {
    left: -100%;
  }
  100% {
    left: 100%;
  }
}

.dropzone-icon {
  font-size: 4rem;
  color: var(--link);
  margin-bottom: 1rem;
  animation: bounce 2s infinite;
}

@keyframes bounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

.dropzone.drag-over .dropzone-icon {
  animation: pulse 0.5s infinite;
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
}

.dropzone-text {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--heading-color);
  margin-bottom: 0.5rem;
}

.dropzone-hint {
  color: var(--muted-text);
  font-size: 0.9em;
}

.dropzone-file-input {
  display: none;
}

/* Hidden file input */
.hidden-file-input {
  display: none;
}

/* Merge tool header - vertical stack: X button on top, then label */
.merge-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
}

/* Merge tool delete button - red border circle with red X */
.merge-page-delete-btn {
  background: transparent !important;
  color: #e53e3e !important;
  border: 2px solid #e53e3e !important;
  border-radius: 50% !important;
  width: 26px !important;
  height: 26px !important;
  min-width: 26px !important;
  min-height: 26px !important;
  max-width: 26px !important;
  max-height: 26px !important;
  padding: 0 !important;
  margin: 0 !important;
  cursor: pointer !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
  transition:
    transform 0.15s,
    border-color 0.15s,
    box-shadow 0.15s !important;
}

.merge-page-delete-btn:hover {
  background: transparent !important;
  border-color: #c53030 !important;
  transform: scale(1.15) !important;
  box-shadow: 0 0 8px rgba(229, 62, 62, 0.5) !important;
}

.merge-page-delete-btn i,
.merge-page-delete-btn .fas,
.merge-page-delete-btn .fa-times {
  color: #e53e3e !important;
  font-size: 1.4rem !important;
  margin-left: 7px !important;
}

.merge-page-delete-btn:hover i,
.merge-page-delete-btn:hover .fas,
.merge-page-delete-btn:hover .fa-times {
  color: #c53030 !important;
}

/* Page label below the X button */
.merge-page-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
  width: 100%;
}

/* Undo delete button */
.merge-page-undo-btn {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--link);
  color: white;
  border: none;
  border-radius: 4px;
  padding: 6px 12px;
  font-size: 0.75rem;
  cursor: pointer;
  z-index: 15;
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  transition:
    background 0.15s,
    transform 0.15s;
}

.merge-page-undo-btn:hover {
  background: var(--link-hover);
  transform: translate(-50%, -50%) scale(1.05);
}

/* Merge pages container for proper gap handling */
.merge-pages-container {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.5rem 0;
}

/* Merge tool - all pages container (flat view) */
.merge-all-pages-container {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  padding: 1rem;
}

.merge-pages-header,
.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--border-color);
}

.preview-header-title {
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--text-color);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.preview-header-title i {
  color: var(--link);
}

.preview-header-title .merge-pages-title-count {
  margin-left: 5px;
  padding: 6px 9px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  color: var(--heading-color);
  background: rgba(var(--link-rgb, 51, 102, 255), 0.16);
  border: 1px solid rgba(var(--link-rgb, 51, 102, 255), 0.24);
  line-height: 1.1;
}

.merge-header-controls {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  min-width: 0;
  max-width: 100%;
}

.merge-preview-size {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 1.5rem;
  background: var(--input-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  font-size: 1.1rem;
  color: var(--text-color);
  flex-wrap: wrap;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}

.merge-preview-size i {
  font-size: 1.25rem;
  color: var(--link);
}

.merge-preview-label {
  font-weight: 600;
  white-space: nowrap;
  font-size: 1.35rem;
}

.merge-preview-slider {
  flex: 1 1 120px;
  width: 160px;
  max-width: 100%;
  min-width: 90px;
  height: 8px;
  border-radius: 4px;
  background: var(--border-color);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  margin: 0 0.5rem;
}

@media (max-width: 600px) {
  .merge-header-controls,
  .merge-preview-size {
    width: 100%;
  }
  .merge-preview-size {
    gap: 0.6rem;
    padding: 0.6rem 0.8rem;
  }
  .merge-preview-label {
    font-size: 1rem;
  }
  .merge-preview-slider {
    margin: 0;
  }
}

.merge-preview-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--link);
  cursor: pointer;
  border: 3px solid var(--card-bg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: transform 0.15s ease;
}

.merge-preview-slider::-webkit-slider-thumb:hover {
  transform: scale(1.15);
}

.merge-preview-slider::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--link);
  cursor: pointer;
  border: 3px solid var(--card-bg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

.merge-preview-value {
  min-width: 60px;
  text-align: center;
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--link);
  background: var(--card-bg);
  padding: 0.35rem 0.75rem;
  border-radius: var(--radius-small);
}

.merge-pages-title {
  font-weight: 600;
  color: var(--heading-color);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.merge-pages-title i {
  color: var(--link);
}

.merge-pages-count {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--muted-text);
  background: var(--input-bg);
  padding: 0.5rem 1.25rem;
  border-radius: 1.5rem;
}

/* Merge tool drag info - uses standard alert alert-info, just add margin */
.merge-drag-info {
  margin-bottom: 1rem;
}

.merge-drag-info strong {
  color: #60a5fa;
}

.merge-pages-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  min-height: 100px;
}

/* Merge page thumbnails in flat view - 50% BIGGER */
.merge-pages-grid .merge-page-thumbnail {
  position: relative;
  cursor: grab;
  width: calc(165px * var(--preview-scale, 1));
  min-height: calc(220px * var(--preview-scale, 1));
  padding: 0.5rem;
  gap: 0.5rem;
}

.merge-pages-grid .merge-page-thumbnail:active {
  cursor: grabbing;
}

/* Merge tool - BIG page number label */
.merge-pages-grid .merge-page-thumbnail .preview-card-header {
  padding: 0.5rem;
  background: var(--card-bg);
}

.merge-pages-grid .merge-page-thumbnail .page-number {
  font-size: 1rem;
  font-weight: 700;
  color: var(--heading-color);
  line-height: 1.1;
}

.merge-pages-grid .merge-page-thumbnail .preview-card-footer {
  align-items: center;
  justify-content: center;
  min-height: 34px;
}

.merge-page-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  cursor: pointer;
  user-select: none;
  margin-bottom: 0 !important;
}

.merge-page-toggle-input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.merge-page-toggle-slider {
  width: 40px;
  height: 22px;
  border-radius: 999px;
  background: var(--border-color);
  position: relative;
  transition: background 0.2s ease;
}

.merge-page-toggle-slider::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 0.2s ease;
}

.merge-page-toggle-input:checked + .merge-page-toggle-slider {
  background: var(--link);
}

.merge-page-toggle-input:checked + .merge-page-toggle-slider::after {
  transform: translateX(18px);
}

.merge-file-summary {
  margin-top: 1rem;
}

.merge-file-summary-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-color);
}

.merge-file-summary-row:last-child {
  border-bottom: none;
}

.merge-file-summary-left {
  min-width: 56px;
  font-weight: 700;
  color: var(--heading-color);
}

.merge-file-summary-right {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.65rem;
  flex: 1;
  min-width: 0;
}

.merge-file-summary-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.merge-file-summary-size {
  color: var(--muted-text);
  font-size: 0.82em;
  white-space: nowrap;
}

.merge-file-summary-remove {
  margin: 0 !important;
}

/* Thumbnail loading state */
.thumbnail-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 80px;
  color: var(--muted-text);
}

.preview-disabled-message {
  color: var(--muted-text);
  font-size: 0.85em;
  padding: 0.5rem;
  text-align: center;
  font-style: italic;
}

/* File Info with Preview */
.file-info-with-preview {
  margin-top: 1rem;
}

.file-info-with-preview .file-info {
  margin-bottom: 0.5rem;
}

/* Custom file upload button */
.file-upload-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  border-radius: 10px;
  border: 1px solid var(--border-color);
  background: var(--input-bg);
  color: var(--text-color);
  cursor: pointer;
  font-weight: 600;
  transition: all 0.2s ease;
}

.file-upload-button:hover {
  border-color: var(--link);
  color: var(--link);
}

.file-upload-button i {
  font-size: 0.95rem;
}

input[type='file']#htmlToPdfCssFile {
  display: none;
}

@media (max-width: 1024px) {
  .convert-page .tool-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Responsive Design */
@media (max-width: 768px) {
  .tool-grid {
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1rem;
  }

  .tool-card {
    padding: 1.25rem 1rem;
  }

  .tool-icon {
    font-size: 2.75rem;
    margin-bottom: 0.625rem;
  }

  .tool-icon.tool-icon-conversion {
    font-size: 2.1rem;
    gap: 0.5rem;
  }

  .tool-icon.tool-icon-conversion .tool-icon-conversion-arrow {
    font-size: 1.25rem;
  }

  .tool-card h3 {
    font-size: 17px;
  }

  .tool-card p {
    font-size: 1.2rem;
  }

  .convert-page .tool-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .convert-page h1 {
    font-size: 28px;
  }

  .image-preview-grid {
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  }

  .dropzone {
    padding: 2rem 1rem;
  }

  .dropzone-icon {
    font-size: 3rem;
  }
}

/* Tool Navigation Buttons */
.tool-nav {
  margin-bottom: 2rem;
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}

.advanced-toggle {
  margin-top: 1rem;
}

.tool-option-field .toggle-switch {
  width: 100%;
  justify-content: flex-start;
  flex-wrap: nowrap;
  display: flex;
  align-items: center;
  gap: 12px;
}

.tool-option-field .toggle-switch span {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 1.1rem;
  font-weight: 600;
}

.tool-option-field .toggle-switch input[type='checkbox'] {
  margin-top: 0;
  margin-bottom: 0;
}

.optimize-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(145px, 1fr));
  gap: 0.75rem;
  margin-top: 0.85rem;
}

.optimize-stat-card {
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-small);
  background: var(--input-bg);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.optimize-stat-icon {
  width: 48px;
  height: 48px;
  margin: 0 0 0.5rem 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: rgba(214, 40, 40, 0.15);
  color: #d62828;
  font-size: 20px;
  flex-shrink: 0;
}

.optimize-stat-icon i,
.optimize-stat-icon .icon,
.optimize-stat-icon span {
  margin-right: 0 !important;
  font-size: 28px;
}

.optimize-stat-label {
  font-size: 0.9rem;
  color: var(--muted-text);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.25rem;
  font-weight: bold;
}

.optimize-stat-value {
  font-size: 1rem;
  color: var(--heading-color);
  font-weight: 600;
}

.optimize-download-top {
  margin-bottom: 1rem;
}

.optimize-success-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1rem 1.25rem;
  border-radius: var(--radius-large);
  background: linear-gradient(
    135deg,
    rgba(102, 187, 106, 0.18),
    rgba(214, 40, 40, 0.12)
  );
  border: 1px solid rgba(102, 187, 106, 0.35);
  color: #d6f6dc;
  font-weight: 700;
  margin-bottom: 1.25rem;
  animation: optimizeSuccessIn 0.35s ease-out;
}

.optimize-success-banner .result-download {
  margin-top: 0;
}

.optimize-success-banner .button {
  border-radius: 12px;
  padding: 0.7rem 1.25rem;
}

@media (max-width: 768px) {
  .optimize-success-banner {
    flex-direction: column;
    align-items: stretch;
  }

  .optimize-success-banner .button {
    width: 100%;
  }

  .optimize-success-banner .result-action-icon {
    width: auto;
  }
}

.optimize-success-info {
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
}

.optimize-success-icon {
  width: 48px;
  height: 48px;
  border-radius: 16px;
  background: linear-gradient(
    135deg,
    rgba(102, 187, 106, 0.35),
    rgba(214, 40, 40, 0.2)
  );
  border: 1px solid rgba(102, 187, 106, 0.45);
  display: grid;
  place-items: center;
  color: #66bb6a;
  font-size: 0;
}

.optimize-success-icon i {
  color: #66bb6a;
  line-height: 1;
  font-size: 1.25rem;
  display: block;
  transform: translateX(3px);
}

.optimize-success-text {
  font-size: 1.6rem;
  color: #d6f6dc;
}

/* Light theme adjustments for optimize-style result */
body:not(.theme-dark) .optimize-success-banner {
  background: linear-gradient(
    135deg,
    rgba(34, 197, 94, 0.12),
    rgba(59, 130, 246, 0.1)
  );
  border-color: rgba(34, 197, 94, 0.35);
  color: #14532d;
}

body:not(.theme-dark) .optimize-success-text {
  color: #14532d;
}

body:not(.theme-dark) .optimize-success-icon {
  background: linear-gradient(
    135deg,
    rgba(34, 197, 94, 0.25),
    rgba(59, 130, 246, 0.18)
  );
  border-color: rgba(34, 197, 94, 0.35);
  color: #16a34a;
}

body:not(.theme-dark) .optimize-success-icon i {
  color: #16a34a;
}

body:not(.theme-dark) .optimize-stat-label {
  color: #0f172a;
}

@keyframes optimizeSuccessIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.advanced-options {
  margin-top: 0.75rem;
  padding: 1rem;
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-small);
  background: var(--input-bg);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.advanced-options[hidden] {
  display: none;
}

.permissions-grid {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.preview-size-value {
  min-width: 40px;
  text-align: center;
  font-size: 0.85em;
  color: var(--muted-text);
  font-weight: 500;
}

/* File Item Styles */
.file-item-content {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
}

.file-item-info {
  flex: 1;
}

.overlay-file-item {
  flex-direction: column;
  align-items: stretch;
}

.overlay-file-item .file-item-content {
  width: 100%;
}

.overlay-file-header {
  width: 100%;
  margin-top: 0.75rem;
  margin-bottom: 0.5rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border-color);
}

.overlay-file-name {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--heading-color);
  word-break: break-word;
}

.overlay-preview-controls {
  margin-bottom: 0.75rem;
}

/* Result Download Buttons & After-action buttons */
.result-download {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.result-after-actions {
  flex-wrap: wrap;
  gap: 0.35rem 0.5rem;
}

.result-after-actions .button.share-menu-open {
  background: var(--border-color, #e2e8f0);
  color: var(--text-color, #333);
}
body.theme-dark .result-after-actions .button.share-menu-open {
  background: #334155;
  color: #e2e8f0;
}

.result-after-actions .button {
  white-space: nowrap;
}

/* Remove button (red / danger) - base_style inspired */
body.theme-dark .result-action-remove,
body.theme-light .result-action-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
body.theme-dark .result-action-remove {
  background: rgba(239, 68, 68, 0.12) !important;
  border-color: rgba(239, 68, 68, 0.4) !important;
  color: #ef4444 !important;
}
body.theme-dark .result-action-remove:hover {
  background: rgba(239, 68, 68, 0.22) !important;
  border-color: #ef4444 !important;
  color: #f87171 !important;
}

.result-action-remove i {
  margin-right: 0;
}
body.theme-light .result-action-remove {
  background: rgba(220, 53, 69, 0.1) !important;
  border-color: rgba(220, 53, 69, 0.35) !important;
  color: #dc3545 !important;
}
body.theme-light .result-action-remove:hover {
  background: rgba(220, 53, 69, 0.18) !important;
  border-color: #dc3545 !important;
  color: #c82333 !important;
}

.button-preview {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
}

/* Icon-only preview (eye): secondary to Download */
.button-preview-icon {
  padding: 1.7rem !important;
  min-width: auto;
  margin: 0 !important;
}
.button-preview-icon .fas {
  margin: 0;
}

/* File Info and Options - Note: display:none is set via JS, not CSS class */

.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.75rem 1rem;
  align-items: end;
}

.options-field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.options-field > label {
  margin: 0;
}

.options-field > select,
.options-field > input,
.options-field > textarea {
  width: 100%;
}

.options-grid > button {
  grid-column: 1 / -1;
}

#deleteOptions .delete-pages-help {
  display: block;
  grid-column: 1 / -1;
}

#deleteOptions .delete-pages-btn {
  grid-column: 1 / -1;
  justify-self: start;
  margin-top: 0.75rem;
}

/* Tool options - side by side layout */
.tool-options-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1rem;
}

.tool-option-field {
  flex: 1;
  min-width: 150px;
}

.tool-option-field label:not(.toggle-switch) {
  display: block;
  margin-bottom: 0.5rem;
}

.tool-option-field select,
.tool-option-field input {
  width: 100%;
  margin-bottom: 0;
  height: 44px;
  padding: 0.5rem 0.75rem;
}

@media (max-width: 500px) {
  .tool-options-row {
    flex-direction: column;
  }

  .tool-option-field {
    min-width: 100%;
  }
}

/* Input Groups with Margin */
.input-group-margin {
  margin-top: 1rem;
}

/* Page Preview Container */
.page-preview-container {
  margin-top: 1rem;
  padding: 1rem;
  background: var(--input-bg);
  border-radius: var(--radius-small);
}

/* PDF Info Section */
.pdf-info-section {
  margin: 4rem 0;
  padding: 0;
}

.pdf-info-content {
  margin-bottom: 4rem;
}

.pdf-info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2rem;
}

.pdf-info-item {
  padding: 2rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  text-align: center;
}

.pdf-info-item:hover {
  border-color: #d62828;
  transform: translateY(-3px);
  box-shadow: 0 6px 16px rgba(214, 40, 40, 0.15);
}

.pdf-info-item-icon {
  width: 64px;
  height: 64px;
  margin: 0 auto 1.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.1) 0%,
    rgba(163, 22, 33, 0.1) 100%
  );
  border-radius: 16px;
  font-size: 2rem;
  color: #d62828;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.pdf-info-item:hover .pdf-info-item-icon {
  transform: scale(1.05);
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.15) 0%,
    rgba(163, 22, 33, 0.15) 100%
  );
}

.pdf-info-item h3 {
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--heading-color);
  margin: 0 0 0.5rem 0;
  line-height: 1.4;
  letter-spacing: 0.02em;
}

.pdf-info-item p {
  font-size: 1.35rem;
  line-height: 1.6;
  color: var(--text-color);
  margin: 0;
  font-weight: 400;
  letter-spacing: 0.01em;
}

.pdf-resources {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.pdf-resources-title {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--heading-color);
  margin: 0 0 1.5rem 0;
  text-align: center;
}

.resource-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
  margin-top: 2rem;
}

.resource-link {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 2rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  text-decoration: none;
  color: inherit;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  width: 100%;
  cursor: pointer;
}

/* Animated gradient border that follows rounded corners */
.resource-link::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, #d62828 0%, #a31621 50%, #d62828 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 2;
  pointer-events: none;
}

.resource-link:hover {
  border-color: transparent;
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.15);
}

.resource-link:hover::before {
  opacity: 1;
}

/* Hide the span border elements - using pseudo-element instead */
.resource-link-border-left,
.resource-link-border-right {
  display: none;
}

.resource-icon {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 16px;
  font-size: 2rem;
  position: relative;
  z-index: 1;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

/* Wikipedia - Clean glass style */
.resource-wikipedia .resource-icon {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.9) 0%,
    rgba(245, 245, 245, 0.8) 100%
  );
  color: #1a1a2e;
  border: 1px solid rgba(0, 0, 0, 0.1);
  box-shadow:
    0 4px 16px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

/* Adobe - Modern red/coral gradient with transparency */
.resource-adobe .resource-icon {
  background: linear-gradient(
    135deg,
    rgba(239, 68, 68, 0.85) 0%,
    rgba(220, 38, 38, 0.9) 50%,
    rgba(185, 28, 28, 0.85) 100%
  );
  color: #ffffff;
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow:
    0 4px 16px rgba(239, 68, 68, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

/* ISO - Modern blue/indigo gradient with transparency */
.resource-iso .resource-icon {
  background: linear-gradient(
    135deg,
    rgba(59, 130, 246, 0.85) 0%,
    rgba(79, 70, 229, 0.9) 50%,
    rgba(67, 56, 202, 0.85) 100%
  );
  color: #ffffff;
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow:
    0 4px 16px rgba(79, 70, 229, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.resource-link:hover .resource-icon {
  transform: scale(1.08) rotate(-3deg);
}

.resource-wikipedia:hover .resource-icon {
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

.resource-adobe:hover .resource-icon {
  box-shadow:
    0 8px 24px rgba(239, 68, 68, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.resource-iso:hover .resource-icon {
  box-shadow:
    0 8px 24px rgba(79, 70, 229, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

/* Dark theme adjustments for resource icons */
body.theme-dark .resource-wikipedia .resource-icon {
  background: linear-gradient(
    135deg,
    rgba(30, 41, 59, 0.9) 0%,
    rgba(51, 65, 85, 0.8) 100%
  );
  color: #f1f5f9;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

body.theme-dark .resource-adobe .resource-icon {
  background: linear-gradient(
    135deg,
    rgba(239, 68, 68, 0.75) 0%,
    rgba(220, 38, 38, 0.8) 50%,
    rgba(185, 28, 28, 0.75) 100%
  );
  border: 1px solid rgba(255, 255, 255, 0.1);
}

body.theme-dark .resource-iso .resource-icon {
  background: linear-gradient(
    135deg,
    rgba(99, 102, 241, 0.75) 0%,
    rgba(79, 70, 229, 0.8) 50%,
    rgba(67, 56, 202, 0.75) 100%
  );
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.resource-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  position: relative;
  z-index: 1;
}

.resource-title {
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--heading-color);
  display: block;
  line-height: 1.4;
  letter-spacing: 0.02em;
  transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.resource-link:hover .resource-title {
  color: #d62828;
}

.resource-desc {
  font-size: 1.35rem;
  color: var(--text-color);
  display: block;
  line-height: 1.6;
  letter-spacing: 0.01em;
  opacity: 0.85;
  transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.resource-link:hover .resource-desc {
  opacity: 1;
}

.resource-arrow {
  flex-shrink: 0;
  color: var(--muted-text);
  font-size: 1.1rem;
  opacity: 0.6;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  z-index: 1;
}

.resource-link:hover .resource-arrow {
  opacity: 1;
  color: #d62828;
  transform: translateX(4px);
}

/* Dark theme adjustments for resource links */
body.theme-dark .resource-link:hover {
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.2);
  border-color: transparent;
}

body.theme-dark .resource-link:hover .resource-title {
  color: #ff8e86;
}

body.theme-dark .resource-link:hover .resource-arrow {
  color: #ff8e86;
}

body.theme-dark .resource-link::before {
  background: linear-gradient(135deg, #ff8e86 0%, #ffa59e 50%, #ff8e86 100%);
}

/* Why loopdf Section */
.why-loopdf-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
  margin-bottom: 4rem;
}

.why-card {
  padding: 2rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  display: flex;
  gap: 1.5rem;
  align-items: center;
  text-align: left;
}

/* Animated gradient border for why cards */
.why-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, #d62828 0%, #a31621 50%, #d62828 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1;
  pointer-events: none;
}

.why-card:hover {
  border-color: transparent;
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.15);
}

.why-card:hover::before {
  opacity: 1;
}

.why-card-icon {
  width: 56px;
  height: 56px;
  min-width: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.1) 0%,
    rgba(163, 22, 33, 0.1) 100%
  );
  border-radius: 14px;
  font-size: 1.5rem;
  color: #d62828;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  z-index: 2;
}

.why-card:hover .why-card-icon {
  transform: scale(1.08);
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.15) 0%,
    rgba(163, 22, 33, 0.15) 100%
  );
}

.why-card-content {
  flex: 1;
  position: relative;
  z-index: 2;
}

.why-card h3 {
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--heading-color);
  margin: 0 0 0.75rem 0;
  line-height: 1.4;
  letter-spacing: 0.02em;
  transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  z-index: 2;
}

.why-card:hover h3 {
  color: #d62828;
}

.why-card p {
  font-size: 1.35rem;
  line-height: 1.6;
  color: var(--text-color);
  margin: 0;
  font-weight: 400;
  letter-spacing: 0.01em;
  position: relative;
  z-index: 2;
}

.why-card p strong {
  color: var(--heading-color);
}

/* Contact link in why card */
.why-card-cta {
  color: #d62828;
  font-weight: 600;
  text-decoration: none;
  transition: all 0.3s ease;
}

.why-card-cta:hover {
  color: #a31621;
  text-decoration: underline;
}

body.theme-dark .why-card-cta {
  color: #ff8e86;
}

body.theme-dark .why-card-cta:hover {
  color: #ffa59e;
}

/* Dark theme for why cards */
body.theme-dark .why-card:hover {
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.2);
}

body.theme-dark .why-card:hover h3 {
  color: #ff8e86;
}

body.theme-dark .why-card-icon {
  background: linear-gradient(
    135deg,
    rgba(255, 107, 97, 0.15) 0%,
    rgba(255, 142, 134, 0.15) 100%
  );
  color: #ff6b61;
}

body.theme-dark .why-card:hover .why-card-icon {
  background: linear-gradient(
    135deg,
    rgba(255, 107, 97, 0.2) 0%,
    rgba(255, 142, 134, 0.2) 100%
  );
}

body.theme-dark .why-card::before {
  background: linear-gradient(135deg, #ff8e86 0%, #ffa59e 50%, #ff8e86 100%);
}

/* Testimonials Section */
.testimonials-container {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 4rem;
  padding: 1px 0.5rem;
}

.testimonials-slider {
  flex: 1;
  overflow: hidden;
  border-radius: var(--radius-large);
  padding: 5px;
}

.testimonials-track {
  display: flex;
  gap: 1.5rem;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}

.testimonial-card {
  flex: 0 0 auto;
  width: calc((100% - 3rem) / 3);
  min-width: calc((100% - 3rem) / 3);
  max-width: calc((100% - 3rem) / 3);
  padding: 2rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  box-sizing: border-box;
}

/* Gradient border using the working technique from why-card */
.testimonial-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, #d62828 0%, #a31621 50%, #d62828 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1;
  pointer-events: none;
  will-change: opacity;
}

.testimonial-card:hover {
  border-color: var(--card-bg);
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.15);
}

.testimonial-card:hover::before {
  opacity: 1;
}

.testimonial-stars {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1rem;
  position: relative;
  z-index: 2;
}

.testimonial-stars i {
  color: #fbbf24;
  font-size: 1.1rem;
}

.testimonial-text {
  font-size: 1.35rem;
  line-height: 1.7;
  color: var(--text-color);
  margin: 0 0 1.5rem 0;
  font-style: italic;
  position: relative;
  z-index: 2;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 6.885rem; /* line-height (1.7) * font-size (1.35rem) * 3 lines = 6.885rem */
  max-height: 6.885rem; /* Ensure all cards have same text height */
}

.testimonial-author {
  display: flex;
  align-items: center;
  gap: 1rem;
  position: relative;
  z-index: 2;
}

.testimonial-avatar {
  width: 48px;
  height: 48px;
  min-width: 48px;
  border-radius: 50%;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  position: relative;
}

.testimonial-avatar .fi {
  width: 100%;
  height: 100%;
  display: block;
  background-size: 85%;
  background-position: center;
  background-repeat: no-repeat;
}

.testimonial-info {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.testimonial-name {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--heading-color);
}

.testimonial-meta {
  font-size: 1.1rem;
  color: var(--muted-text);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.flag-icon {
  font-size: 1.4rem;
  line-height: 1;
  display: inline-block;
  vertical-align: middle;
  font-style: normal;
}

.testimonial-meta .flag-icon {
  display: none; /* Hide flag from meta, it's now in the avatar */
}

.testimonial-nav {
  width: 48px;
  height: 48px;
  min-width: 48px;
  border-radius: 50%;
  border: 1px solid var(--border-color);
  background: var(--card-bg);
  color: var(--text-color);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
  z-index: 10;
}

.testimonial-nav:hover {
  border-color: #d62828;
  color: #d62828;
  background: rgba(214, 40, 40, 0.1);
}

.testimonial-nav:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

/* Dark theme testimonials */
body.theme-dark .testimonial-card:hover {
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.2);
}

body.theme-dark .testimonial-nav:hover {
  color: #ff8e86;
  border-color: #ff8e86;
  background: rgba(255, 142, 134, 0.1);
}

body.theme-dark .testimonial-card::before {
  background: linear-gradient(135deg, #ff8e86 0%, #ffa59e 50%, #ff8e86 100%);
}

/* Responsive testimonials */
@media (max-width: 1024px) {
  .testimonial-card {
    width: calc((100% - 1.5rem) / 2);
    min-width: calc((100% - 1.5rem) / 2);
    max-width: calc((100% - 1.5rem) / 2);
  }
}

@media (max-width: 768px) {
  .testimonials-container {
    padding: 1px 0.25rem;
  }

  .testimonials-slider {
    padding: 5px 0;
  }

  .testimonial-card {
    width: 100%;
    min-width: 100%;
    max-width: 100%;
    padding: 1.5rem;
  }

  .testimonial-nav {
    width: 40px;
    height: 40px;
    min-width: 40px;
  }

  .testimonial-text {
    font-size: 1.2rem;
    min-height: 6.12rem; /* line-height (1.7) * font-size (1.2rem) * 3 lines = 6.12rem */
    max-height: 6.12rem;
  }

  .testimonial-name {
    font-size: 1.15rem;
  }

  .testimonial-meta {
    font-size: 1rem;
  }
}

/* PDF Usage Statistics Section */
.pdf-usage-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  margin-bottom: 4rem;
}

.usage-card {
  padding: 1.75rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
}

/* Animated gradient border for usage cards */
.usage-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, #d62828 0%, #a31621 50%, #d62828 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1;
  pointer-events: none;
}

.usage-card:hover {
  border-color: transparent;
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.15);
}

.usage-card:hover::before {
  opacity: 1;
}

.usage-card-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
}

.usage-card-icon {
  width: 48px;
  height: 48px;
  min-width: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.1) 0%,
    rgba(163, 22, 33, 0.1) 100%
  );
  border-radius: 12px;
  font-size: 1.25rem;
  color: #d62828;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.usage-card:hover .usage-card-icon {
  transform: scale(1.08);
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.15) 0%,
    rgba(163, 22, 33, 0.15) 100%
  );
}

.usage-card-stat {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  flex: 1;
}

.stat-number {
  font-size: 2rem;
  font-weight: 700;
  color: #d62828;
  line-height: 1;
}

.stat-bar {
  width: 100%;
  height: 6px;
  background: rgba(214, 40, 40, 0.15);
  border-radius: 3px;
  overflow: hidden;
}

.stat-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #d62828 0%, #a31621 100%);
  border-radius: 3px;
  transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.usage-source {
  text-align: center;
  font-size: 1.1rem;
  color: var(--muted-text);
  margin-top: 1rem;
  margin-bottom: 4rem;
  font-style: italic;
}

.usage-source a {
  color: #d62828;
  text-decoration: none;
  transition: all 0.3s ease;
}

.usage-source a:hover {
  color: #a31621;
  text-decoration: underline;
}

/* ---- The card ---- */
/* Frame-color-only accent: card look, hover/open border tint, no leading
   icon, and no glow/shadow/tint chrome - all come from base_collapse.css. */
.collapse-container.collapse-faq {
  --collapse-accent: var(--primary-blue);
  --collapse-accent-rgb: 214, 40, 40;
}
body.theme-dark .collapse-container.collapse-faq {
  --collapse-accent-rgb: 255, 107, 97;
}

/* ---- Shared FAQ header: title row + "Still stuck?" link ---- */
.faq-head-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.faq-still-stuck {
  font-size: 15.5px;
  color: var(--muted-text);
  margin: 0 0 6px;
}
.faq-still-stuck a {
  color: var(--primary-blue);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1.5px solid
    color-mix(in srgb, var(--primary-blue) 35%, transparent);
}
.faq-still-stuck a:hover {
  border-bottom-color: var(--primary-blue);
}

@media (max-width: 768px) {
}

body.theme-dark .usage-source a {
  color: #ff8e86;
}

body.theme-dark .usage-source a:hover {
  color: #ffa59e;
}

.usage-card h3 {
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--heading-color);
  margin: 0 0 0.75rem 0;
  line-height: 1.4;
  letter-spacing: 0.02em;
  transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  z-index: 2;
}

.usage-card:hover h3 {
  color: #d62828;
}

.usage-card p {
  font-size: 1.35rem;
  line-height: 1.6;
  color: var(--text-color);
  margin: 0;
  font-weight: 400;
  letter-spacing: 0.01em;
  position: relative;
  z-index: 2;
}

.usage-card p strong {
  color: var(--heading-color);
}

/* Dark theme for usage cards */
body.theme-dark .usage-card:hover {
  box-shadow: 0 8px 24px rgba(214, 40, 40, 0.2);
}

body.theme-dark .usage-card:hover h3 {
  color: #ff8e86;
}

body.theme-dark .stat-number {
  color: #ff8e86;
}

body.theme-dark .stat-bar {
  background: rgba(255, 107, 97, 0.15);
}

body.theme-dark .stat-bar-fill {
  background: linear-gradient(90deg, #ff8e86 0%, #ffa59e 100%);
}

body.theme-dark .usage-card-icon {
  background: linear-gradient(
    135deg,
    rgba(255, 107, 97, 0.15) 0%,
    rgba(255, 142, 134, 0.15) 100%
  );
  color: #ff6b61;
}

body.theme-dark .usage-card:hover .usage-card-icon {
  background: linear-gradient(
    135deg,
    rgba(255, 107, 97, 0.2) 0%,
    rgba(255, 142, 134, 0.2) 100%
  );
}

body.theme-dark .usage-card::before {
  background: linear-gradient(135deg, #ff8e86 0%, #ffa59e 50%, #ff8e86 100%);
}

/* Responsive usage cards */
@media (max-width: 1024px) {
  .pdf-usage-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .pdf-usage-grid {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  .usage-card {
    padding: 1.5rem;
  }

  .usage-card h3 {
    font-size: 1.4rem;
  }

  .usage-card p {
    font-size: 1.2rem;
  }

  .stat-number {
    font-size: 1.5rem;
  }
}

/* Responsive why cards */
@media (max-width: 768px) {
  .why-loopdf-grid {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  .why-card {
    padding: 1.5rem;
    gap: 1.25rem;
  }

  .why-card h3 {
    font-size: 1.4rem;
  }

  .why-card p {
    font-size: 1.2rem;
  }

  .why-card-icon {
    width: 48px;
    height: 48px;
    min-width: 48px;
    font-size: 1.25rem;
    border-radius: 12px;
  }
}

/* Responsive PDF Info Section */
@media (max-width: 968px) {
  .pdf-info-section {
    margin: 4rem 0;
  }

  .pdf-info-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }

  .pdf-info-item {
    padding: 2rem;
  }

  .resource-links {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }

  .resource-icon {
    width: 56px;
    height: 56px;
    font-size: 1.75rem;
  }

  .resource-title {
    font-size: 1.4rem;
  }

  .resource-desc {
    font-size: 1.2rem;
  }
}

@media (max-width: 768px) {
  .pdf-info-section {
    margin: 3rem 0;
  }

  .pdf-info-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }

  .pdf-info-item {
    padding: 1.75rem;
  }

  .pdf-info-item h3 {
    font-size: 1.4rem;
  }

  .pdf-info-item p {
    font-size: 1.2rem;
  }

  .pdf-info-item-icon {
    width: 56px;
    height: 56px;
    font-size: 1.75rem;
  }

  .pdf-resources {
    margin-top: 0;
    padding-top: 0;
  }

  .pdf-resources-title {
    font-size: 1.35rem;
    margin-bottom: 1rem;
  }

  .resource-link {
    padding: 1.5rem;
    gap: 1.25rem;
  }

  .resource-link:hover {
    transform: translateY(-2px);
  }

  .resource-link:hover .resource-icon {
    transform: scale(1.05) rotate(-2deg);
  }

  .resource-icon {
    width: 56px;
    height: 56px;
    font-size: 1.75rem;
  }

  .resource-title {
    font-size: 1.4rem;
  }

  .resource-desc {
    font-size: 1.2rem;
  }
}

/* CTA Section */
.cta {
  padding: 4rem 2rem;
  position: relative;
  overflow: hidden;
  margin-top: 4rem;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
}

.cta::before {
  content: '';
  position: absolute;
  top: -50%;
  right: -20%;
  width: 400px;
  height: 400px;
  background: radial-gradient(
    circle,
    rgba(214, 40, 40, 0.15) 0%,
    transparent 70%
  );
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
  animation: ctaFloat 20s ease-in-out infinite;
}

@keyframes ctaFloat {
  0%,
  100% {
    transform: translate(0, 0);
  }
  50% {
    transform: translate(-30px, 30px);
  }
}

.cta-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 3rem;
  flex-wrap: wrap;
  position: relative;
  z-index: 1;
  max-width: 1200px;
  margin: 0 auto;
}

.cta-text {
  flex: 1;
  min-width: 300px;
  max-width: 550px;
}

.cta h3 {
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  font-weight: 700;
  margin-bottom: 1rem;
  letter-spacing: -0.02em;
  background: linear-gradient(
    135deg,
    var(--text-color) 0%,
    var(--link) 60%,
    rgba(214, 40, 40, 0.9) 100%
  );
  background-size: 200% 200%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation: gradient-shift 8s ease infinite;
}

.cta .muted {
  font-size: 1.35rem;
  line-height: 1.7;
  color: var(--text-color);
}

.cta-actions {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: center;
  position: relative;
  min-width: 300px;
  flex-shrink: 0;
}

.cta-button-wrapper {
  position: relative;
  display: inline-block;
  margin-right: 1rem;
}

.cta-pointer {
  position: absolute;
  right: calc(100% + 2rem);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
  z-index: 10;
  animation: pointerBounce 2s ease-in-out infinite;
  white-space: nowrap;
  pointer-events: none;
  min-width: 100px;
}

.pointer-svg {
  width: 80px;
  height: 60px;
  color: #d62828;
  filter: drop-shadow(0 4px 8px rgba(214, 40, 40, 0.4));
  flex-shrink: 0;
}

.pointer-path {
  stroke-dasharray: 150;
  stroke-dashoffset: 150;
  animation: drawPath 3s ease-in-out infinite;
}

.pointer-arrow {
  opacity: 0;
  animation: arrowPulse 2s ease-in-out infinite;
  animation-delay: 0.5s;
}

.pointer-text {
  font-size: 0.85rem;
  font-weight: 600;
  color: #d62828;
  white-space: nowrap;
  background: rgba(214, 40, 40, 0.1);
  padding: 0.25rem 0.75rem;
  border-radius: var(--radius-small);
  border: 1px solid rgba(214, 40, 40, 0.3);
  animation: textPulse 2s ease-in-out infinite;
}

.cta-pulse {
  animation: buttonPulse 2s ease-in-out infinite;
  position: relative;
}

.cta-pulse::before {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  background: linear-gradient(135deg, #d62828, rgba(214, 40, 40, 0.8));
  opacity: 0;
  z-index: -1;
  filter: blur(8px);
  animation: glowPulse 2s ease-in-out infinite;
}

@keyframes pointerBounce {
  0%,
  100% {
    transform: translateY(-50%) translateX(0);
  }
  50% {
    transform: translateY(-50%) translateX(-8px);
  }
}

@keyframes drawPath {
  0% {
    stroke-dashoffset: 150;
    opacity: 0;
  }
  30% {
    opacity: 1;
  }
  70% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    opacity: 0.8;
  }
}

@keyframes arrowPulse {
  0%,
  100% {
    opacity: 0;
    transform: translateX(0);
  }
  50% {
    opacity: 1;
    transform: translateX(4px);
  }
}

@keyframes textPulse {
  0%,
  100% {
    opacity: 0.8;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.05);
  }
}

@keyframes buttonPulse {
  0%,
  100% {
    transform: scale(1);
    box-shadow: 0 4px 16px rgba(214, 40, 40, 0.3);
  }
  50% {
    transform: scale(1.02);
    box-shadow: 0 8px 24px rgba(214, 40, 40, 0.5);
  }
}

@keyframes glowPulse {
  0%,
  100% {
    opacity: 0;
    transform: scale(1);
  }
  50% {
    opacity: 0.6;
    transform: scale(1.1);
  }
}

.cta-actions .button {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  transform-style: preserve-3d;
  will-change: transform;
}

.cta-actions .button::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), transparent);
  opacity: 0;
  transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1;
}

.cta-actions .button::after {
  content: '';
  position: absolute;
  inset: -2px;
  background: linear-gradient(
    135deg,
    rgba(214, 40, 40, 0.3),
    rgba(214, 40, 40, 0.3)
  );
  border-radius: inherit;
  opacity: 0;
  filter: blur(12px);
  transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: -1;
}

.cta-actions .button:hover {
  transform: translateY(-3px) scale(1.02);
  box-shadow:
    0 12px 32px rgba(214, 40, 40, 0.35),
    0 0 0 1px rgba(255, 255, 255, 0.1) inset;
}

.cta-actions .button:hover::before {
  opacity: 1;
}

.cta-actions .button:hover::after {
  opacity: 1;
}

.cta-actions .button:active {
  transform: translateY(-1px) scale(0.98);
}

.cta-actions .button-primary {
  background: linear-gradient(135deg, #d62828 0%, #a31621 100%);
  box-shadow: 0 4px 16px rgba(214, 40, 40, 0.3);
}

/* CTA Responsive */
@media (max-width: 1100px) {
  .cta-pointer {
    right: calc(100% + 1rem);
    min-width: 80px;
  }

  .pointer-svg {
    width: 60px;
    height: 45px;
  }
}

@media (max-width: 992px) {
  .cta-pointer {
    display: none;
  }

  .cta-text {
    min-width: auto;
    max-width: none;
  }

  .cta-body {
    flex-direction: column;
    text-align: center;
    gap: 2rem;
  }

  .cta-actions {
    min-width: auto;
    justify-content: center;
  }
}

@media (max-width: 768px) {
  .cta {
    padding: 3rem 1.5rem;
    margin-top: 3rem;
  }

  .cta h3 {
    font-size: 1.5rem;
  }

  .cta .muted {
    font-size: 1.2rem;
  }

  .cta-button-wrapper {
    margin-right: 0;
  }

  .cta-actions {
    flex-direction: column;
    width: 100%;
  }

  .cta-actions .button {
    width: 100%;
    text-align: center;
  }
}

/* Dark theme CTA */
body.theme-dark .cta {
  background: var(--card-bg);
  border-color: var(--border-color);
}

body.theme-dark .cta::before {
  background: radial-gradient(
    circle,
    rgba(255, 107, 97, 0.15) 0%,
    transparent 70%
  );
}

body.theme-dark .pointer-svg {
  color: #ff8e86;
  filter: drop-shadow(0 4px 8px rgba(255, 142, 134, 0.4));
}

body.theme-dark .pointer-text {
  color: #ff8e86;
  background: rgba(255, 142, 134, 0.1);
  border-color: rgba(255, 142, 134, 0.3);
}

body.theme-dark .cta-pulse::before {
  background: linear-gradient(135deg, #ff8e86, rgba(255, 142, 134, 0.8));
}

body.theme-dark .cta-actions .button-primary {
  background: linear-gradient(135deg, #ff8e86 0%, #ffa59e 100%);
}

/* Password-protected PDF inline error alert */
.pdf-guard-error-alert {
  margin-top: 1rem;
}

.pdf-guard-error-alert a {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  border-bottom: none;
}

/* ==================== PDF FORMS LIBRARY ==================== */

.forms-grid {
  align-items: stretch;
}

.form-tool-card {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 10px;
  cursor: pointer;
}

.form-tool-card-thumb {
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-medium);
  overflow: hidden;
  border: 1px solid var(--border-color);
  background: rgba(214, 40, 40, 0.06);
  position: relative;
}

.form-tool-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.form-tool-card h3 {
  font-size: 17px;
  margin-bottom: 0;
  line-height: 1.3;
  min-height: calc(1.3em * 2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.form-tool-card-thumb-actions {
  position: absolute;
  inset: 0;
  display: flex;
  /* Anchored to the bottom of the thumb rather than centred: the top of a form
     is the part that identifies it, so the row sits where it covers least. */
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 10px;
  /* Three small buttons (preview / edit / download) instead of two large ones,
     so they still fit a narrow card at 4-column width. */
  gap: 8px;
  /* Scrim only where the buttons are - the thumbnail stays readable on hover. */
  background: linear-gradient(
    180deg,
    rgba(26, 8, 8, 0) 45%,
    rgba(26, 8, 8, 0.5) 100%
  );
  opacity: 0;
  transition: opacity 0.22s ease;
  pointer-events: none;
}

.form-tool-card.is-card-hovered .form-tool-card-thumb-actions {
  opacity: 1;
  pointer-events: auto;
}

.form-tool-card-action-btn {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid rgba(255, 226, 224, 0.26);
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  color: #ffffff;
  /* Glass, not paint: the fill is a thin tint and the blur does the work, so
     the form stays visible through the row. Opacity climbs on hover so the
     button the pointer is on reads as solid. */
  background: rgba(122, 24, 24, 0.16);
  backdrop-filter: blur(11px) saturate(1.35);
  -webkit-backdrop-filter: blur(11px) saturate(1.35);
  box-shadow:
    0 6px 16px rgba(0, 0, 0, 0.2),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transition:
    transform 0.15s ease,
    background-color 0.15s ease,
    box-shadow 0.15s ease,
    filter 0.15s ease;
}

.form-tool-card-action-btn:link,
.form-tool-card-action-btn:visited,
.form-tool-card-action-btn:hover,
.form-tool-card-action-btn:active,
.form-tool-card-action-btn:focus-visible {
  color: #ffffff;
  -webkit-text-fill-color: #ffffff;
}

/* One red family, three steps of weight: preview is the lightest wash, edit is
   the brand red (the primary action on a forms card), download is the deepest. */
.form-tool-card-action-btn[data-form-action='preview'] {
  background: linear-gradient(
    180deg,
    rgba(255, 150, 142, 0.14) 0%,
    rgba(196, 60, 55, 0.24) 100%
  );
}

.form-tool-card-action-btn[data-form-action='view'] {
  background: linear-gradient(
    180deg,
    rgba(255, 107, 97, 0.3) 0%,
    rgba(214, 40, 40, 0.4) 100%
  );
  border-color: rgba(255, 236, 234, 0.42);
}

.form-tool-card-action-btn[data-form-action='download'] {
  background: linear-gradient(
    180deg,
    rgba(196, 51, 46, 0.2) 0%,
    rgba(120, 21, 21, 0.32) 100%
  );
}

.form-tool-card-action-btn:hover,
.form-tool-card-action-btn:focus-visible {
  transform: translateY(-1px);
  border-color: rgba(255, 236, 234, 0.8);
  box-shadow:
    0 10px 22px rgba(0, 0, 0, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.form-tool-card-action-btn[data-form-action='preview']:hover,
.form-tool-card-action-btn[data-form-action='preview']:focus-visible {
  background: linear-gradient(
    180deg,
    rgba(255, 150, 142, 0.5) 0%,
    rgba(196, 60, 55, 0.68) 100%
  );
}

.form-tool-card-action-btn[data-form-action='view']:hover,
.form-tool-card-action-btn[data-form-action='view']:focus-visible {
  background: linear-gradient(
    180deg,
    rgba(255, 107, 97, 0.76) 0%,
    rgba(214, 40, 40, 0.86) 100%
  );
}

.form-tool-card-action-btn[data-form-action='download']:hover,
.form-tool-card-action-btn[data-form-action='download']:focus-visible {
  background: linear-gradient(
    180deg,
    rgba(196, 51, 46, 0.66) 0%,
    rgba(120, 21, 21, 0.8) 100%
  );
}

.form-tool-card-action-btn i {
  font-size: 15px;
  /* The fill is nearly clear, so the glyph carries its own contrast. */
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.55),
    0 0 8px rgba(0, 0, 0, 0.35);
}

.form-tool-card-action-btn--small {
  width: 38px;
  height: 38px;
  border-radius: 10px;
}

.form-tool-card-action-btn--small i {
  font-size: 15px;
}

/* Narrow cards (3+ columns on a tablet) - keep all three on one row. */
@media (max-width: 900px) {
  .form-tool-card-thumb-actions {
    gap: 6px;
    padding-bottom: 8px;
  }

  .form-tool-card-action-btn {
    width: 34px;
    height: 34px;
    border-radius: 9px;
  }

  .form-tool-card-action-btn i {
    font-size: 13px;
  }
}

.form-tool-card-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  background: rgba(7, 12, 24, 0.58);
  transition: opacity 0.2s ease;
}

.form-tool-card.is-downloading .form-tool-card-loading {
  opacity: 1;
}

.form-tool-card.is-downloading .form-tool-card-thumb-actions {
  opacity: 0;
}

.form-tool-card-loading-spinner {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  border: 4px solid rgba(255, 255, 255, 0.28);
  border-top-color: rgba(255, 255, 255, 0.95);
  animation: formCardSpin 0.9s linear infinite;
}

@keyframes formCardSpin {
  to {
    transform: rotate(360deg);
  }
}

/* ---------- Batch result file list ----------
   Shown under a batch summary only (2+ files). The zip is the primary download
   in the drawer foot; these rows exist so the user can see what came out and
   pull a single file without unzipping - and so a partial batch names the files
   that failed instead of just reporting a smaller count. */
.batch-file-list {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.batch-file-row {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  background: var(--card-bg);
  font-size: 13px;
}

.batch-file-icon {
  color: var(--muted-text);
  font-size: 13px;
}

.batch-file-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-color);
}

.batch-file-note {
  color: var(--muted-text);
  font-variant-numeric: tabular-nums;
}

/* A failed row has no download button, so its note takes that track too -
   otherwise the reason gets squeezed into the width of a button. */
.batch-file-row--failed {
  grid-template-columns: 16px minmax(0, 1fr) auto;
}

.batch-file-row--failed .batch-file-icon {
  color: var(--danger-color, #d62828);
}

.batch-file-row--failed .batch-file-note {
  white-space: normal;
}

.batch-file-download {
  width: 30px;
  height: 30px;
  padding: 0;
  gap: 0 !important;
}

/* While a file swap is in flight the panel keeps its previous height, so only
   the pages change rather than the whole column collapsing and rebounding. The
   fade covers the moment the old pages are gone and the new ones are not in
   yet. */
.pdf-preview-result.is-swapping .pdf-preview-pages-wrap,
.pdf-preview-container.is-swapping .pdf-preview-pages-wrap {
  opacity: 0.35;
}

.pdf-preview-result .pdf-preview-pages-wrap,
.pdf-preview-container .pdf-preview-pages-wrap {
  transition: opacity 160ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .pdf-preview-result .pdf-preview-pages-wrap,
  .pdf-preview-container .pdf-preview-pages-wrap {
    transition: none;
  }
}

/* The cloud keeps floating on the full drop zone - that is the invitation to
   upload, and the motion is the point. Once files are staged the same zone
   shrinks to the rail's "Add more PDFs" button, where a drifting icon next to a
   label is just fidget. Static there only.
   !important because base_dropzone.css is a component asset and lands after the
   project stylesheet, so an equal-weight rule here would lose. */
.dropzone.is-compact .dropzone-icon {
  animation: none !important;
}

/* The "All tools" grid ships every card, and the script then hides the handful
   that are already shown as featured cards above it - marked data-hide-in-all.
   Doing that only after load meant the grid rendered ~400px too tall and then
   collapsed, taking the category tabs and everything under them with it.
   Hidden from the start instead; picking a category still reveals them, because
   the script writes an inline display which outranks this. */
.pdf-landing:not(.pdf-tools-filtered)
  .pdf-tools-grid
  .tool-card[data-hide-in-all='1'] {
  display: none;
}

/* ---------- Batch preview file stepper ----------
   Sits in the preview header beside its title, so stepping between the files in
   a batch uses the same arrows-and-counter shape as the page pager directly
   below it. Only rendered for two or more files. */
.preview-file-nav {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 12px;
  min-width: 0;
}

.preview-file-nav__label {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font-size: 13px;
}

.preview-file-nav__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
  color: var(--text-color);
  font-weight: 600;
}

.preview-file-nav__count {
  color: var(--muted-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Round, like every other icon-only control on a tool page. The selector and
   the !important match .button-reset-tool's: base_elements.css paints button
   width, padding and radius with !important, so a plain class rule loses. */
body:not(:has(.admin-container)) button.button.preview-file-nav__step {
  width: 30px !important;
  min-width: 30px !important;
  height: 30px !important;
  padding: 0 !important;
  margin: 0 !important;
  border-radius: 999px !important;
  /* The hidden label is still a flex item, so a gap would centre
     "icon + gap + nothing" and push the glyph off-centre. */
  gap: 0 !important;
  flex: 0 0 auto;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* Buttons that pair an icon with a label give the icon a right margin. Centring
   "icon + 8px margin" in a 30px circle put the glyph 4px left of the middle -
   there is no label here for that margin to separate it from. */
body:not(:has(.admin-container)) button.button.preview-file-nav__step > i {
  margin: 0 !important;
}

/* Optical centring. The chevron mask is centred to the pixel inside its box,
   but a chevron does not read from its bounding box - the eye lands on the
   vertex, so a "<" looks pushed right and a ">" looks pushed left. Nudging each
   toward its own point is the same correction a play triangle needs, and em
   keeps it proportional if the icon size ever changes. */
body:not(:has(.admin-container))
  button.button.preview-file-nav__step
  > i.fa-chevron-left {
  transform: translateX(-0.07em);
}

body:not(:has(.admin-container))
  button.button.preview-file-nav__step
  > i.fa-chevron-right {
  transform: translateX(0.07em);
}

@media (max-width: 640px) {
  .preview-file-nav {
    margin-left: 0;
    width: 100%;
  }

  .preview-file-nav__label {
    flex: 1;
  }

  .preview-file-nav__name {
    max-width: none;
  }
}

/* The forms grid dims while a page/search request is in flight - the class was
   set by the pagination script but had no styling, so paging looked frozen. */
.base-tool-selector .tab-panels.is-loading {
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

/* Forms page spacing tune: reduce gap before pagination */
.pdf-forms-page ~ .tab-panels {
  padding-bottom: 8px;
}

.pdf-forms-page ~ #forms-overview-pagination.blog-pagination {
  margin-top: 12px;
  margin-bottom: 4px;
}

/* The SEO prose under every tool. It had no styling at all, so it ran the full
   width of the page - lines of ~200 characters that nobody reads. Capped to a
   normal measure and centred under the tool it belongs to. */
.seo-content {
  /* 70% of the viewport, with a ceiling: on a 1280px screen that is ~900px and
     ~118 characters a line, which is the width asked for. Without the cap an
     ultrawide monitor would put it straight back to the 200-character lines
     this replaced, since 70vw keeps growing while the text does not. */
  max-width: min(70vw, 1100px);
  margin-inline: auto;
}

/* Its headings are centred; the paragraphs and lists stay ranged left, which is
   what makes a long line readable. */
.seo-content > h1,
.seo-content > h2,
.seo-content > h3 {
  text-wrap: balance;
}

@media (max-width: 900px) {
  .seo-content {
    max-width: 100%;
  }
}

.forms-seo-block {
  margin-top: 32px;
  padding: 24px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-large);
  background: var(--card-bg);
}

.forms-seo-block h2 {
  font-size: 21px;
  margin-bottom: 11px;
}

.forms-seo-block ul {
  margin-bottom: 0;
}

/* ── Mega menu: full-width layout, no vertical scroll ── */
.mega-menu-content {
  max-width: min(1240px, calc(100vw - 24px)) !important;
  max-height: none !important;
  overflow-y: visible !important;
}

/* Navbar: on mobile (hamburger, <=750px) hide the quick links
   (Merge/Split/Compress) and the Convert dropdown; "All PDF Tools" stays so the
   full tool list is still reachable from the hamburger. */
@media (max-width: 750px) {
  .navbar-section--center li:has(> a.nav-quicklink) {
    display: none !important;
  }
}

/* Website-to-PDF: browser "Print to PDF" fallback guide (shown in a modal) */
.wpg-intro {
  margin: 0 0 1rem;
  color: var(--text-color);
  line-height: 1.5;
}

.wpg-tabs {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

@media (max-width: 640px) {
  .wpg-tabs {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.wpg-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding: 0.7rem 0.4rem;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  background: var(--card-bg);
  color: var(--muted-text, #6c757d);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease,
    color 0.15s ease,
    transform 0.1s ease;
}

.wpg-tab:hover {
  color: var(--text-color);
  border-color: var(--link);
}

.wpg-tab.active {
  color: var(--text-color);
  border-color: var(--link);
  box-shadow:
    0 0 0 2px var(--link) inset,
    0 2px 6px rgba(0, 0, 0, 0.06);
}

.wpg-tab .wpg-ic {
  width: 26px;
  height: 26px;
  display: block;
  filter: grayscale(0.55) opacity(0.75);
  transition: filter 0.15s ease;
}

.wpg-tab:hover .wpg-ic,
.wpg-tab.active .wpg-ic {
  filter: none;
}

.wpg-tab-label {
  line-height: 1;
}

.wpg-panel {
  display: none;
}

.wpg-panel.active {
  display: block;
}

.wpg-steps {
  margin: 0;
  padding-left: 1.25rem;
  line-height: 1.6;
  color: var(--text-color);
}

.wpg-steps li {
  margin-bottom: 0.4rem;
}

/* ============================================================
   NAVBAR + DROPDOWNS - re-skin the shared base chrome
   The base navbar ships a multi-colour rainbow gradient background
   (+ a rainbow ::after overlay) and faintly rainbow-tinted dropdown
   panels. That base CSS is shared across sister projects, so we
   override it here at the project level: a clean red-brand surface
   navbar with a hairline border, and solid dropdown panels.
   ============================================================ */
nav.navbar,
.navbar {
  background: var(--container-bg) !important;
  background-image: none !important;
  border-bottom: 1px solid var(--border-color) !important;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03) !important;
}
nav.navbar::before,
nav.navbar::after,
.navbar::before,
.navbar::after {
  background: none !important;
  background-image: none !important;
}
body.theme-dark nav.navbar,
body.theme-dark .navbar {
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4) !important;
}

/* The base navbar paints its text/links white (they sat on a coloured
   band). On the new white surface that text is invisible in light mode,
   so force readable dark ink there; dark theme keeps white. */
body.theme-light nav.navbar,
body.theme-light .navbar a,
body.theme-light .navbar button,
body.theme-light .navbar span,
body.theme-light .navbar li,
body.theme-light .navbar .nav-link,
body.theme-light .navbar .nav-quicklink,
body.theme-light .navbar [class*='nav-'] {
  color: var(--text-color) !important;
}
body.theme-light .navbar svg,
body.theme-light .navbar i {
  color: currentColor !important;
}
body.theme-light .navbar a:hover,
body.theme-light .navbar .nav-link:hover,
body.theme-light .navbar .nav-quicklink:hover {
  color: var(--primary-blue) !important;
}

.dropdown-content,
.mega-menu-content {
  background: var(--dropdown-bg) !important;
  background-image: none !important;
  border: 1px solid var(--border-color) !important;
}

/* No decorative side-stripes / washes on nav + menu items in ANY hover or
   active state. The base draws a 3px left bar (::before) plus a gradient wash
   (::after) on menu items - strip them everywhere. Using background:none
   (not display:none) so any caret glyph rendered via ::after survives; the
   empty absolute pseudo boxes are harmless. Items still get a clean flat
   hover (row tint + red text) below. */
.navbar a:not(.navbar-logo)::before,
.navbar a:not(.navbar-logo)::after,
.dropdown-content a::before,
.dropdown-content a::after,
.mega-menu-content a::before,
.mega-menu-content a::after,
.mega-menu-category-item::before,
.mega-menu-category-item::after {
  background: none !important;
  background-image: none !important;
  box-shadow: none !important;
}
.dropdown-content a:hover,
.mega-menu-content a:hover,
.mega-menu-category-item:hover {
  background: var(--item-hover-bg) !important;
  color: var(--primary-blue) !important;
}

/* ---- Brand lockup ----
   The framework navbar was unified to a shared .nb-brand markup (icon badge
   + optional wordmark span), replacing the old per-project .navbar-logo
   class this block used to target - which is why the "loopdf" wordmark
   disappeared after that refactor, this was still styling a class that no
   longer exists. The icon badge itself is now natively rendered by
   .nb-brand__badge/.nb-brand__img (same favicon.svg, bordered tile), so
   that part of the old hand-painted ::before badge is dropped as redundant.
   Only the wordmark half is ported: un-hide the sr-only span inside
   .nb-brand and paint "loopdf" onto it in the project's Fredoka font,
   exactly as before. */
body .navbar a.nb-brand .sr-only {
  position: static !important;
  width: auto !important;
  height: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  clip: auto !important;
  clip-path: none !important;
  overflow: visible !important;
  white-space: nowrap !important;
  border: 0 !important;
  font-size: 0 !important;
  line-height: 1 !important;
  color: transparent !important;
}
body .navbar a.nb-brand .sr-only::before {
  content: 'loopdf' !important;
  font-family: 'Fredoka', system-ui, sans-serif !important;
  font-weight: 600 !important;
  font-size: 15px !important;
  letter-spacing: -0.01em !important;
  color: var(--heading-color) !important;
}
.brand-tld {
  color: var(--primary-blue);
}
.footer-brand-name {
  font-family: 'Fredoka', system-ui, sans-serif !important;
  color: var(--heading-color) !important;
}

/* ============================================================
   MOBILE NAVBAR (hamburger) - re-skin the base mobile chrome
   ============================================================ */
/* Hamburger bars: the base paints them white (for the old coloured bar) -
   make them readable on the clean surface in both themes. */
body.theme-light .nav-toggle span {
  background: var(--text-color) !important;
}
body.theme-dark .nav-toggle span {
  background: #f5f4f2 !important;
}
/* Mobile menu dropdown: kill the base rainbow gradient; clean themed panel. */
.navbar-nav.is-open {
  background: var(--container-bg) !important;
  background-image: none !important;
  border-top: 1px solid var(--border-color) !important;
  box-shadow: 0 16px 32px -16px rgba(0, 0, 0, 0.35) !important;
}
/* Show the brand on mobile - the base hides the whole left section, leaving
   only a bare hamburger. The logo + wordmark fit comfortably beside it. */
@media (max-width: 640px) {
  .navbar-section--left {
    display: flex !important;
    align-items: center !important;
  }
}

/* ---- Theme toggle (light / dark) ----
   Base renders #theme-toggle as a bare sun/moon icon-swap with WHITE glyphs
   (made for the old coloured band) - invisible on the new white surface in
   light mode. Rework it into a clean bordered icon button with a brand-red
   glyph that reads in BOTH themes, in the navbar and the mobile menu. The
   base JS still owns the sun<->moon swap + theme switch. */
/* ONE theme toggle everywhere: the icon-only switcher (desktop navbar AND the
   mobile menu). The base also renders a separate labelled "Toggle theme" row
   (.mobile-theme-switcher) in the menu - hide it so the toggle isn't doubled. */
body .navbar .navbar-theme-switcher,
body .navbar .navbar-theme-switcher .theme-switcher {
  display: inline-flex !important;
  align-items: center !important;
}
body .navbar .navbar-theme-switcher {
  position: relative;
  margin-left: 6px !important;
  padding-left: 16px !important;
}
body .navbar .navbar-theme-switcher::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 22px;
  background: color-mix(in srgb, currentColor 22%, transparent);
}
.mobile-theme-switcher {
  display: none !important;
}
body .navbar #theme-toggle,
body .navbar .theme-toggle-button {
  width: 30px !important;
  height: 30px !important;
  min-width: 30px !important;
  min-height: 30px !important;
  padding: 0 !important;
  margin: 0 !important;
  align-self: center !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 8px !important;
  border: 1px solid var(--border-color) !important;
  background: var(--card-bg) !important;
  color: var(--primary-blue) !important;
  box-shadow: none !important;
  cursor: pointer !important;
  transition:
    background 0.18s ease,
    border-color 0.18s ease,
    color 0.18s ease,
    transform 0.15s ease !important;
}
body .navbar #theme-toggle:hover,
body .navbar .theme-toggle-button:hover {
  background: var(--info-item-bg) !important;
  border-color: var(--primary-blue) !important;
  transform: translateY(-1px) !important;
}
body .navbar #theme-toggle:focus-visible,
body .navbar .theme-toggle-button:focus-visible {
  outline: 2px solid var(--primary-blue) !important;
  outline-offset: 2px !important;
}
body .navbar #theme-toggle .theme-icon,
body .navbar .theme-toggle-button .theme-icon {
  color: var(--primary-blue) !important;
  font-size: 16px !important;
}
/* Mobile menu theme toggle: this button carries the "Toggle theme" TEXT (plus
   absolutely-positioned sun/moon icons), so style it as a labelled pill - not
   the icon-only desktop box, which made the text overflow and the icon escape.
   The icon sits absolutely on the left; the text clears it with left padding. */
body .navbar .theme-switcher-mobile {
  justify-content: center !important;
}
body .navbar #theme-toggle-mobile,
body .navbar .theme-toggle-button-mobile {
  position: relative !important;
  display: inline-flex !important;
  align-items: center !important;
  width: auto !important;
  height: 42px !important;
  padding: 0 18px 0 42px !important;
  margin: 0 auto !important;
  border: 1px solid var(--border-color) !important;
  border-radius: 11px !important;
  background: var(--card-bg) !important;
  color: var(--heading-color) !important;
  font-weight: 600 !important;
  font-size: 14px !important;
  cursor: pointer !important;
}
body .navbar #theme-toggle-mobile .theme-icon,
body .navbar .theme-toggle-button-mobile .theme-icon {
  position: absolute !important;
  left: 15px !important;
  top: 50% !important;
  transform: translateY(-50%) !important;
  color: var(--primary-blue) !important;
  font-size: 16px !important;
}

body.theme-light .navbar .navbar-action--ghost,
body.theme-dark .navbar .navbar-action--ghost {
  background: var(--primary-blue) !important;
  background-image: none !important;
  border: 1.5px solid var(--primary-blue) !important;
  border-radius: 999px !important;
  will-change: transform !important;
  transition:
    background-color 0.45s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.45s cubic-bezier(0.22, 1, 0.36, 1),
    color 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.5s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.5s cubic-bezier(0.22, 1, 0.36, 1) !important;
}
body.theme-light .navbar .navbar-action--ghost {
  background: #ff6b61 !important;
  border-color: #ff6b61 !important;
  color: #2a0d0b !important;
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.5) !important;
}
body.theme-dark .navbar .navbar-action--ghost {
  color: #2a0d0b !important;
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.5) !important;
}
body .navbar .navbar-action--ghost i,
body .navbar .navbar-action--ghost svg,
body .navbar .navbar-action--ghost .icon {
  color: currentColor !important;
}
body.theme-light .navbar .navbar-action--ghost:hover {
  background: #ff6b61 !important;
  border-color: #ff6b61 !important;
  color: #2a0d0b !important;
  transform: translateY(-2px) !important;
  box-shadow: 0 14px 28px -10px rgba(0, 0, 0, 0.62) !important;
  transition:
    background-color 0.22s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.22s cubic-bezier(0.22, 1, 0.36, 1),
    color 0.2s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.3s cubic-bezier(0.22, 1, 0.36, 1) !important;
}
body.theme-dark .navbar .navbar-action--ghost:hover {
  background: var(--primary-blue) !important;
  border-color: var(--primary-blue) !important;
  color: #2a0d0b !important;
  transform: translateY(-2px) !important;
  box-shadow: 0 14px 28px -10px rgba(0, 0, 0, 0.62) !important;
  transition:
    background-color 0.22s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.22s cubic-bezier(0.22, 1, 0.36, 1),
    color 0.2s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.3s cubic-bezier(0.22, 1, 0.36, 1) !important;
}
body.theme-light .navbar .navbar-action--ghost:active,
body.theme-dark .navbar .navbar-action--ghost:active {
  transform: translateY(0) !important;
  transition-duration: 0.09s !important;
}

/* ============================================================
   TOOL PAGES - landing-design alignment
   The 44 tool pages share this chrome (.tool-nav, .tools-section
   header, .card panel, .dropzone, .result-area, related tools).
   Align it to the landing "Red Technical Minimal" language:
   tight Fraunces headers + red accent, clean red-tinted notes,
   red dropzone, bordered surfaces.
   ============================================================ */
/* The reset control. data-tooltip-no-icon is required on the markup: without
   it base_tooltip.js promotes the button to .tooltip-wrapper and injects its
   own "?" glyph inside, which lands on top of the redo icon. The square sizing
   here beats this project's generic .button padding, which would otherwise
   render the icon button as a stubby pill. The selector carries `button.button`
   because the generic rule above is written as `body.theme-* button.button`
   (0,2,2) - a plain `.button-reset-tool` guard ties on specificity and loses. */
body:not(:has(.admin-container)) button.button.button-reset-tool {
  width: 38px !important;
  min-width: 38px !important;
  height: 38px !important;
  padding: 0 !important;
  margin: 0 !important;
  border-radius: 999px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

.tools-section-title {
  font-family: 'Fredoka', system-ui, sans-serif;
  font-weight: 600;
  font-size: clamp(30px, 4.4vw, 46px);
  line-height: 1.05;
  letter-spacing: -0.025em;
  margin: 0 0 14px;
  text-wrap: balance;
  color: var(--heading-color);
}
.tools-section-description {
  font-size: 18px;
  line-height: 1.6;
  color: var(--muted-text);
  max-width: 60ch;
  margin: 0 auto;
  text-wrap: pretty;
}

/* Alerts - conventional semantic colours (info=blue, success=green,
   warning=amber, danger=red) like Bootstrap, but tuned to sit naturally on
   both the light paper and the dark charcoal surfaces. Variant tokens drive
   one shared rule; the brand red stays reserved for actions/branding. */
.alert {
  border-radius: var(--radius-medium) !important;
}
body .alert-info,
body .alert-success,
body .alert-warning,
body .alert-danger,
body .alert-error {
  background: var(--a-bg) !important;
  border: 1px solid var(--a-bd) !important;
  color: var(--a-tx) !important;
}
body .alert-info i,
body .alert-info .fas,
body .alert-info svg,
body .alert-success i,
body .alert-success .fas,
body .alert-success svg,
body .alert-warning i,
body .alert-warning .fas,
body .alert-warning svg,
body .alert-danger i,
body .alert-danger .fas,
body .alert-danger svg,
body .alert-error i,
body .alert-error .fas,
body .alert-error svg {
  color: var(--a-ic) !important;
}
body.theme-light .alert-info {
  --a-bg: #eff6ff;
  --a-bd: #bfdbfe;
  --a-tx: #1e40af;
  --a-ic: #2563eb;
}
body.theme-light .alert-success {
  --a-bg: #f0fdf4;
  --a-bd: #bbf7d0;
  --a-tx: #166534;
  --a-ic: #16a34a;
}
body.theme-light .alert-warning {
  --a-bg: #fffbeb;
  --a-bd: #fde68a;
  --a-tx: #92400e;
  --a-ic: #d97706;
}
body.theme-light .alert-danger,
body.theme-light .alert-error {
  --a-bg: #fef2f2;
  --a-bd: #fecaca;
  --a-tx: #991b1b;
  --a-ic: #dc2626;
}
body.theme-dark .alert-info {
  --a-bg: rgba(59, 130, 246, 0.13);
  --a-bd: rgba(59, 130, 246, 0.34);
  --a-tx: #bfdbfe;
  --a-ic: #60a5fa;
}
body.theme-dark .alert-success {
  --a-bg: rgba(34, 197, 94, 0.13);
  --a-bd: rgba(34, 197, 94, 0.34);
  --a-tx: #bbf7d0;
  --a-ic: #4ade80;
}
body.theme-dark .alert-warning {
  --a-bg: rgba(245, 158, 11, 0.14);
  --a-bd: rgba(245, 158, 11, 0.34);
  --a-tx: #fde68a;
  --a-ic: #fbbf24;
}
body.theme-dark .alert-danger,
body.theme-dark .alert-error {
  --a-bg: rgba(248, 113, 113, 0.13);
  --a-bd: rgba(248, 113, 113, 0.34);
  --a-tx: #fecaca;
  --a-ic: #f87171;
}

/* Dropzone - clean red-accented upload surface. */
.dropzone {
  border: 1.5px dashed
    color-mix(in srgb, var(--primary-blue) 30%, var(--border-color)) !important;
  border-radius: var(--radius-large);
  background: color-mix(in srgb, var(--primary-blue) 3%, var(--card-bg));
}
.dropzone:hover {
  border-color: var(--primary-blue) !important;
  background: rgba(var(--link-rgb), 0.05) !important;
}
.dropzone.drag-over {
  border-color: var(--primary-blue) !important;
  background: rgba(var(--link-rgb), 0.1) !important;
}
.dropzone-icon {
  color: var(--primary-blue);
  font-size: 3.2rem;
}

/* Result card - keep green for the semantic "file ready" success, refined;
   the primary action button is the dominant red. */
.result-area {
  border-radius: var(--radius-large);
}
.result-area.success {
  border-color: color-mix(in srgb, #16a34a 55%, var(--border-color));
  background: rgba(22, 163, 74, 0.06);
}
.result-message.success {
  color: #16a34a;
}
body.theme-dark .result-message.success {
  color: #22c55e;
}

.tool-nav {
  margin-bottom: 24px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TOOL PAGES — canvas + rail

   One layout for every tool except the standalone editor at #pdfEditorApp.
   Work on the left, controls on the right, action pinned to the rail's bottom.

   The rail is a FIXED width and the canvas takes what is left, so nothing
   stretches and there is no proportion to tune. Values below are the agreed
   build spec, not derived at runtime.

   initToolShell() in script.js supplies the two things the markup lacks - a
   rail title and a file card - and marks the card .tool-shell. No template
   carries shell classes.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --tool-shell-max: 1240px;
  --tool-rail: 340px;
  --tool-canvas-pad: 28px;
}

/* --tool-canvas has to be declared on `body`, NOT on :root.
   This project defines its palette on body.theme-light / body.theme-dark, so
   --card-bg and --text-color simply do not exist at :root - a color-mix() of
   them there is invalid, resolves to nothing, and every surface painted with
   it comes out transparent. That is exactly what happened: the canvas tint
   that was supposed to separate the work area from the rail was never
   rendering at all. */
body:not(:has(.admin-container)) {
  --tool-canvas: color-mix(in srgb, var(--card-bg) 93%, var(--text-color) 7%);
}

/* ── page furniture ─────────────────────────────────────────────────────── */
.tools-section {
  text-align: center;
  max-width: 680px;
  margin: 0 auto 18px;
  padding-top: 8px;
}

/* Alerts belong above the shell, never inside the canvas: between the file and
   its pages they open a gap on both sides, which is most of the empty space
   this layout was rebuilt to remove. */
/* Alerts keep the framework's own info styling - that part was right. What was
   wrong was where they sat: inside the canvas, between the file and its pages.
   They live above the shell now and share its exact measure, so both edges line
   up with the tool instead of each note centring itself to its own text. */
body:not(:has(.admin-container)) .alert.tool-shell-note {
  width: auto;
  max-width: var(--tool-shell-max);
  margin: 0 auto 8px;
}

/* The reset control rides on the shell's top-right corner. */
.tool-nav {
  display: flex;
  justify-content: flex-end;
  max-width: var(--tool-shell-max);
  margin: 0 auto -46px;
  padding-right: 12px;
  position: relative;
  z-index: 2;
}

/* ── shell ──────────────────────────────────────────────────────────────── */
/* `.tools-section ~ .card` is the very selector initToolShell uses to find the
   card, so matching it here means the shell is painted before the script has
   run. Without it the card rendered as a plain block and then gained a border,
   a max-width and a grid on DOMContentLoaded - a visible pop on every reload. */
body:not(:has(.admin-container)) .tools-section ~ .card,
body:not(:has(.admin-container)) .card.tool-shell {
  display: grid;
  /* One column until a file is loaded - the rail is hidden before then, and a
     hidden grid item still reserves its track. */
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  max-width: var(--tool-shell-max);
  margin: 0 auto;
  padding: 0;
  background: var(--tool-canvas);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  overflow: hidden;
}

/* The reset button is moved into the rail head by the same script, and that
   rail stays hidden until a file is loaded - so before JS runs this row shows a
   control that is about to vanish. Hidden from the start it never flashes; the
   script still finds the button inside and relocates it. */
body:not(:has(.admin-container)) .tools-section ~ .tool-nav {
  display: none;
}

body:not(:has(.admin-container)) .card.tool-shell.has-file {
  grid-template-columns: minmax(0, 1fr) var(--tool-rail);
  /* stretch, so the rail spans the full shell height and its bottom-pinned
     action sits on the shell's bottom edge rather than mid-air. */
  align-items: stretch;
}

/* ── canvas ─────────────────────────────────────────────────────────────── */
body:not(:has(.admin-container)) .card.tool-shell > *:not(.tool-rail) {
  grid-column: 1;
  width: 100%;
  max-width: 560px;
  margin-left: auto;
  margin-right: auto;
}

body:not(:has(.admin-container)) .card.tool-shell > .dropzone {
  max-width: 480px;
  margin: var(--tool-canvas-pad) auto;
  padding: 44px 24px;
}

/* Pre-JS the card has no .tool-shell yet, so the drop zone was sitting flush
   against the card edges and the card came out 56px shorter than it would be a
   moment later. Only the margin is mirrored here - the width and padding come
   from the :not(.has-file) rule further down, which is what the finished
   no-file state uses. */
body:not(:has(.admin-container)) .tools-section ~ .card > .dropzone {
  margin: var(--tool-canvas-pad) auto;
  /* Explicit, because as a grid item it otherwise shrink-to-fits its content
     here and jumped from ~255px to the capped 620px once the script ran. */
  width: 100%;
}

body:not(:has(.admin-container)) .card.tool-shell > .dropzone.is-loaded {
  display: none;
}

/* file card */
body:not(:has(.admin-container)) .card.tool-shell > .tool-filecard {
  width: 200px !important;
  max-width: 200px !important;
  margin: var(--tool-canvas-pad) auto 0;
  padding: 12px;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.05),
    0 10px 28px -20px rgba(0, 0, 0, 0.45);
  text-align: center;
}

body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .file-info-item {
  display: block;
  width: auto;
  padding: 0;
  border-bottom: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted-text);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The "File:" / "Size:" labels go. They are different widths, so centring the
   rows left every value starting at a different x - and the card says what it
   is by being a file card. Name on top, facts under it, as designed. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .file-info-item
  strong {
  display: none;
}

/* The filename is the card's first row. It used to sit behind a cloned page
   thumbnail, which is gone: the canvas already shows every page, so repeating
   one of them at 400px only made the rail long enough to need scrolling. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .file-info-item:first-child {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text-color);
  margin-bottom: 1px;
}

/* page strip */
body:not(:has(.admin-container)) .card.tool-shell > .pdf-preview-panel {
  max-width: none;
  padding: 18px var(--tool-canvas-pad) var(--tool-canvas-pad);
}

body:not(:has(.admin-container)) .card.tool-shell .preview-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .card.tool-shell .preview-header-title {
  font-family: 'Fredoka', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
}

/* A zoom control is not a panel: boxed and padded it measured taller than the
   thumbnails it scales. */
body:not(:has(.admin-container)) .card.tool-shell .merge-preview-size {
  gap: 8px;
  padding: 0;
  background: transparent;
  border: 0;
  flex-wrap: nowrap;
}

body:not(:has(.admin-container)) .card.tool-shell .merge-preview-label,
body:not(:has(.admin-container)) .card.tool-shell .merge-preview-value {
  font-size: 12px;
  min-width: 0;
  padding: 0;
  background: none;
}

body:not(:has(.admin-container)) .card.tool-shell .merge-preview-slider {
  flex: 0 0 116px;
  width: 116px;
  min-width: 0;
}

body:not(:has(.admin-container)) .card.tool-shell .pdf-preview-pages-wrap {
  width: 100%;
  /* Room for the hover lift: the strip is overflow-y:hidden, so a card that
     rises 2px with a 1px border is clipped without it. */
  padding-top: 8px;
  padding-bottom: 14px;
}

/* The framework sizes a thumbnail as `calc(110px * var(--preview-scale))`, so a
   flat 96px would have silently killed the zoom slider. Move the BASE instead:
   96px at 100%, and the slider still scales from there. */
body:not(:has(.admin-container)) .card.tool-shell .pdf-preview-thumbnail {
  width: calc(96px * var(--preview-scale, 1));
  min-height: calc(148px * var(--preview-scale, 1));
}

/* result */
body:not(:has(.admin-container)) .card.tool-shell > .result-area {
  max-width: 480px;
  margin: var(--tool-canvas-pad) auto;
}

/* ── rail ───────────────────────────────────────────────────────────────── */
body:not(:has(.admin-container)) .card.tool-shell > .tool-rail {
  grid-column: 2;
  /* span, not `1 / -1`: -1 addresses the last line of the EXPLICIT grid, and
     these rows are all implicit (only columns are declared), so `1 / -1`
     silently resolved to a single row - the rail covered the file card's row
     only and its bottom-pinned action floated mid-shell. */
  grid-row: 1 / span 50;
  align-self: stretch;
  width: auto;
  max-width: none;
  margin: 0 !important;
  /* !important: the tools reveal their options block by writing
     style="display: block" INLINE, which beats any plain rule here. A block
     rail is not just cosmetic - `margin-top: auto` on the action only pushes
     inside a flex container, so without this the CTA never reaches the floor. */
  display: flex !important;
  flex-direction: column;
  gap: 12px;
  padding: 0 18px 18px;
  background: var(--card-bg);
  border-left: 1px solid var(--border-color);
  min-width: 0;
}

body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-rail
  > .tool-rail__head {
  margin: 0 -18px 4px;
  padding: 17px 18px;
  border-bottom: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .card.tool-shell .tool-rail__head h2 {
  margin: 0;
  font-family: 'Fredoka', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading-color);
}

/* The generators inline margin-top on every control; the rail owns its own
   rhythm through gap. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-rail
  > *:not(.tool-rail__head) {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}

body:not(:has(.admin-container)) .card.tool-shell > .tool-rail > label {
  font-size: 13px;
  font-weight: 600;
  color: var(--heading-color);
}

/* The action follows the controls it belongs to rather than being pinned to the
   rail's floor: with short options that left a long empty gap and a stranded
   button, and on a tall canvas it sat a screen away from the settings it
   applies. :last-child, and never a .tool-opt: the option cards are buttons
   too, so a blanket rule would catch the first of them instead. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-rail
  > button:last-child:not(.tool-opt) {
  margin-top: 18px !important;
  width: 100%;
  padding: 14px 16px;
  border-radius: 10px;
  font-size: 16px;
}

/* ── narrow: rail becomes a footer ──────────────────────────────────────── */
@media (max-width: 900px) {
  body:not(:has(.admin-container)) .card.tool-shell.has-file {
    grid-template-columns: minmax(0, 1fr);
  }

  body:not(:has(.admin-container)) .card.tool-shell > .tool-rail {
    grid-column: 1;
    grid-row: auto;
    border-left: 0;
    border-top: 1px solid var(--border-color);
  }

  .tool-nav {
    margin-bottom: -40px;
  }
}

/* ── rail options as selectable cards ───────────────────────────────────────
   The design picks between a handful of named choices, which reads far better
   as cards than as a dropdown in a 340px rail. buildRailOptions() in script.js
   renders these from the tool's own <select> and writes the choice straight
   back to it, so every existing change handler keeps working untouched. */
body:not(:has(.admin-container)) .card.tool-shell .tool-opt {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 0;
  text-align: left;
  font: inherit;
  color: var(--text-color);
  background: transparent !important;
  border: 1px solid var(--border-color) !important;
  border-radius: 10px;
  padding: 11px 13px;
  cursor: pointer;
}

body:not(:has(.admin-container)) .card.tool-shell .tool-opt:hover {
  border-color: var(--muted-text) !important;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-opt[aria-checked='true'] {
  border-color: var(--primary-blue) !important;
  background: color-mix(
    in srgb,
    var(--primary-blue) 10%,
    transparent
  ) !important;
}

/* A grid item's default `min-width: auto` means a long label refuses to shrink
   below its longest line, so the 1fr track grows past the card and the text
   spills out of both edges. min-width:0 lets it wrap instead - which matters
   here because these labels are tool copy ("Low (Minimal size reduction, best
   quality)"), not short words we control. */
body:not(:has(.admin-container)) .card.tool-shell .tool-opt > span:first-child {
  min-width: 0;
}

body:not(:has(.admin-container)) .card.tool-shell .tool-opt__name {
  display: block;
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.35;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Align the dot to the first line rather than the middle of a wrapped block,
   so a two-line option still reads as one control. */
body:not(:has(.admin-container)) .card.tool-shell .tool-opt {
  align-items: start;
}

body:not(:has(.admin-container)) .card.tool-shell .tool-opt__tick {
  margin-top: 1px;
}

body:not(:has(.admin-container)) .card.tool-shell .tool-opt__tick {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1.5px solid var(--border-color);
  flex: 0 0 auto;
  font-size: 0;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-opt[aria-checked='true']
  .tool-opt__tick {
  /* A filled brand dot, no glyph: the checkmark was a second success signal
     next to the card's own selected border, and green read as a status the
     choice does not have. */
  background: var(--primary-blue);
  border-color: var(--primary-blue);
  box-shadow: inset 0 0 0 3px var(--card-bg);
}

/* the source control stays in the DOM (handlers, validation) but out of sight */
body:not(:has(.admin-container)) .card.tool-shell .tool-opt-source {
  display: none !important;
}

/* The rail header carries the tool's title and its reset control. */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail__head
  .button-reset-tool {
  flex: 0 0 auto;
  margin: 0 !important;
}

/* Breathing room between the tool and the tool grid that follows it. Mirrored
   onto the pre-script selector as well: without it the card had no bottom
   margin until the script ran, so the tool grid below - tabs and all - sat 44px
   too high and then dropped into place on load. */
body:not(:has(.admin-container)) .tools-section ~ .card,
body:not(:has(.admin-container)) .card.tool-shell {
  margin-bottom: 44px;
}

/* ---- empty state: no rail, a drop zone that fills the canvas -------------
   Before a file exists the rail has nothing to act on, so showing it just
   offers controls that do nothing and squeezes the drop target into two
   thirds of the shell. Hiding it gives the upload the whole width, which is
   what the empty state in the design shows. ---- */
body:not(:has(.admin-container)) .card.tool-shell:not(.has-file) > .tool-rail {
  display: none !important;
}

body:not(:has(.admin-container))
  .tools-section
  ~ .card:not(.has-file)
  > .dropzone,
body:not(:has(.admin-container)) .card.tool-shell:not(.has-file) > .dropzone {
  max-width: 620px;
  padding: 56px 28px;
}

/* ---- the checkbox row --------------------------------------------------
   A bare <label> in a flex column re-seats itself by a couple of pixels when
   the native box is ticked - the checked control reports a slightly different
   baseline, and the row visibly jumps. Giving the row its own box and centring
   its contents pins it. ---- */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail .checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 26px;
  margin: 0;
  font-size: 13.5px;
  line-height: 1.3;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail
  .checkbox-label
  input[type='checkbox'] {
  flex: 0 0 auto;
  margin: 0;
}

/* The "?" that base_tooltip.js injects sits with the label, not after a gap. */
body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail
  .checkbox-label
  .tooltip-wrapper {
  flex: 0 0 auto;
  margin-left: 2px;
}

/* base_elements gives `.button .fas` a right margin so an icon clears the
   label beside it. An icon-only button has no label, so that margin simply
   shifts the glyph off centre - 8px of it, which reads as a 4px lean. */
body:not(:has(.admin-container)) .button-reset-tool .fas,
body:not(:has(.admin-container)) .button-reset-tool .far,
body:not(:has(.admin-container)) .button-reset-tool .fab,
body:not(:has(.admin-container)) .button-reset-tool svg {
  margin: 0 !important;
}

/* ---- rail fields ---------------------------------------------------------
   Several tools wrap their controls in their own scaffolding
   (.tool-options-row holding .tool-option-field), built for a wide panel. In a
   340px rail that row must stack, and its nested labels need the same
   treatment as a label sitting directly in the rail - otherwise one field
   looks like a rail control and the next looks like leftover form markup. ---- */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail .tool-options-row {
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* padding too, not just margin: the row carries its own inset for the wide
     two-column layout it was written for, which indented every field inside it
     15px further than a field sitting directly in the rail. */
  margin: 0;
  padding: 0;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail
  .tool-option-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  min-width: 0;
}

/* Every top-level group in the rail occupies the same box, so a field sitting
   directly in the rail lines up with one nested inside the tool's own row
   wrapper. Without this the two start at different x and the panel reads as
   two different forms stacked. */
body:not(:has(.admin-container)) .card.tool-shell > .tool-rail > * {
  align-self: stretch;
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}

body:not(:has(.admin-container)) .card.tool-shell .tool-rail label {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--heading-color);
  text-align: left;
}

/* A group of option cards, wherever it lands - directly in the rail or inside
   one of the tool's own fields. */
body:not(:has(.admin-container)) .card.tool-shell .tool-opt-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

/* Text and number inputs in the rail share the option cards' shape. */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail input[type='text'],
body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail
  input[type='number'] {
  width: 100%;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  font-size: 14px;
}

/* ---- multi-file tools (merge, overlay, compare) -------------------------
   These keep their drop zone after the first file, because it is how the next
   one gets added - but it steps back to a slim strip so the staged files, not
   the empty target, are the subject of the canvas. ---- */
/* Once files are staged the drop zone lives in the rail, under the list it
   adds to. It reads as a control there, not a landing area: full rail width,
   dashed to keep it recognisable as a drop target. */
body:not(:has(.admin-container)) .card.tool-shell .dropzone.is-in-rail {
  width: 100%;
  max-width: none;
  min-height: 0;
  margin: 0;
  padding: 13px 14px;
}

body:not(:has(.admin-container)) .card.tool-shell .dropzone.is-compact {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .dropzone.is-compact
  .dropzone-icon {
  font-size: 18px;
  margin: 0;
  line-height: 1;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .dropzone.is-compact
  .dropzone-text {
  font-size: 14px;
  font-weight: 600;
  margin: 0;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .dropzone.is-compact
  .dropzone-hint {
  display: none;
}

/* The staged-file list is the canvas for a multi-file tool, so it gets the
   column rather than the 560px single-file measure. */
body:not(:has(.admin-container)) .card.tool-shell > .file-list,
body:not(:has(.admin-container))
  .card.tool-shell
  > .file-info.merge-file-summary {
  max-width: none;
  width: 100%;
  padding-left: var(--tool-canvas-pad);
  padding-right: var(--tool-canvas-pad);
}

/* ---- staged files, in the rail (multi-file tools) ------------------------
   The summary was built as a full-width table row: label, name, size, remove,
   spread across a wide panel. At 340px that has to become a compact stack -
   name on its own line so it can truncate, size and remove beneath it. ---- */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail-files {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* The tools reveal this block by writing style="display: block" INLINE, which
     beats the rule above - and `gap` does nothing in block layout, so the file
     rows sat flush against each other. Spaced with margins below, which hold in
     either layout rather than depending on which one wins. */
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  font-size: 13px;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail-files
  .merge-file-summary-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2px 8px;
  padding: 9px 11px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
}

/* The real markup is `.merge-file-summary-left` (the "File 1" index) plus a
   `-right` wrapper holding name and size, then the remove button - not the
   .file-item-* classes the other tools use. Targeting the wrong ones left this
   list unstyled and merely lucky to fit. */
body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail-files
  .merge-file-summary-left {
  display: none;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail-files
  .merge-file-summary-right {
  grid-column: 1;
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail-files
  .merge-file-summary-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail-files
  .merge-file-summary-size {
  color: var(--muted-text);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail-files
  .merge-file-summary-remove {
  grid-column: 2;
  margin: 0 !important;
  flex: 0 0 auto;
}

/* The reset control inside an editor's toolbar: same square icon button, but
   it sits in the flow of the toolbar's right group rather than being pulled
   up over it by the old layout's negative margin. */
body:not(:has(.admin-container)) .sign-toolbar .button-reset-tool.is-in-toolbar,
body:not(:has(.admin-container))
  .sign-rail__actions
  button.button.button-reset-tool {
  margin: 0 !important;
  flex: 0 0 auto;
  /* Same height as Download/Share beside it, and still a circle.
     Sized explicitly rather than stretched: as a flex item its width resolves
     from its content on the main axis, so neither aspect-ratio nor align-self
     can derive a square from the row height - stretching gave a 15.8x43.4 pill.
     43.4px is what the text buttons compute to: 12px padding top and bottom,
     1px border top and bottom, around a 17.4px line box. */
  width: 43.4px !important;
  min-width: 43.4px !important;
  height: 43.4px !important;
  border-radius: 999px !important;
}

/* ═══ Sign PDF: workspace + permanent signature rail ═══════════════════════
   The signature builder used to be a centred fixed panel you opened, used and
   closed for every signature - a modal covering the document you were signing.
   It is a rail now: always open, always beside the page.
   ═══════════════════════════════════════════════════════════════════════════ */
body:not(:has(.admin-container)) .sign-pdf-container.is-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--tool-rail);
  grid-template-areas:
    'toolbar toolbar'
    'main    rail'
    'result  rail';
  align-items: start;
}

body:not(:has(.admin-container)) .sign-pdf-container.is-shell .sign-toolbar {
  grid-area: toolbar;
}

body:not(:has(.admin-container))
  .sign-pdf-container.is-shell
  .sign-main-content {
  grid-area: main;
  min-width: 0;
}

body:not(:has(.admin-container)) .sign-pdf-container.is-shell > .result-area {
  grid-area: result;
  min-width: 0;
}

body:not(:has(.admin-container)) .sign-pdf-container.is-shell .sign-rail {
  grid-area: rail;
  align-self: stretch;
  display: flex !important;
  flex-direction: column;
  gap: 12px;
  padding: 0 18px 18px;
  background: var(--card-bg);
  border-left: 1px solid var(--border-color);
  min-width: 0;
}

/* The panel drops its modal identity: no fixed position, no transform, no
   shadow, no fixed 520px width - it is a column in the rail now. */
body:not(:has(.admin-container)) .signature-panel.is-in-rail {
  position: static;
  transform: none;
  width: 100%;
  max-width: none;
  display: flex !important;
  flex-direction: column;
  gap: 10px;
  background: none;
  box-shadow: none;
  border-radius: 0;
  z-index: auto;
  margin: 0;
  padding: 0;
}

/* Its header and close control are redundant once it cannot be closed - the
   rail's own head names it. */
body:not(:has(.admin-container)) .signature-panel.is-in-rail .signature-header {
  display: none;
}

/* Comment PDF's panel was the same floating dialog the signature builder used
   to be - fixed, centred, 400px, opened over the document you were annotating.
   Same treatment: it becomes the rail's column. */
body:not(:has(.admin-container)) .comment-panel.is-in-rail {
  position: static;
  transform: none;
  width: 100%;
  max-width: none;
  display: flex !important;
  flex-direction: column;
  gap: 10px;
  background: none;
  box-shadow: none;
  border-radius: 0;
  z-index: auto;
  margin: 0;
  padding: 0;
}

body:not(:has(.admin-container)) .comment-panel.is-in-rail .comment-header {
  display: none;
}

body:not(:has(.admin-container)) .comment-panel.is-in-rail .comment-content {
  padding: 0;
  gap: 10px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* The textarea takes the rail's width rather than the dialog's 400px. */
body:not(:has(.admin-container)) .comment-panel.is-in-rail .comment-text-input {
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}

/* Save is the commit action and gets the full width; Cancel and Delete share
   the row under it, matching the sign rail's action block. */
body:not(:has(.admin-container)) .comment-panel.is-in-rail .comment-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
}

body:not(:has(.admin-container))
  .comment-panel.is-in-rail
  .comment-controls-right {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  flex: 1 1 100%;
}

body:not(:has(.admin-container))
  .comment-panel.is-in-rail
  .save-button-wrapper {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
}

body:not(:has(.admin-container))
  .comment-panel.is-in-rail
  .comment-controls
  .button {
  margin: 0 !important;
  justify-content: center;
}

body:not(:has(.admin-container)) .comment-panel.is-in-rail #saveComment {
  flex: 1;
}

body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-content {
  padding: 0;
  gap: 10px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* The draw canvas takes the rail's width rather than its authored 400px. */
body:not(:has(.admin-container)) .signature-panel.is-in-rail #signatureCanvas {
  width: 100%;
  height: 150px;
  max-width: 100%;
}

/* Pill tabs, the eduloo .st-tabs pattern: a padded track holding an inset
   active pill, rather than an underline hanging off a bare button row. Shape
   and metrics are eduloo's (4px gutter, 12px track / 8px pill radius, flex-1
   tabs at 34px, 700 weight); the colour is loopdf's brand red, not eduloo's
   purple - the pattern travels between projects, the palette does not. */
body:not(:has(.admin-container)) .signature-panel.is-in-rail .signature-tabs {
  display: flex;
  gap: 4px;
  padding: 4px;
  margin: 0;
  /* !important throughout: .signature-tab is a <button>, and base_elements
     paints every button's background and colour with !important - the same
     rule that blanked the tag swatch grid. The track is only transparent
     because the template's own var(--item-bg) does not resolve. */
  background: var(--tool-canvas) !important;
  border: 0;
  border-radius: 12px;
}

body:not(:has(.admin-container)) .signature-panel.is-in-rail .signature-tab {
  flex: 1;
  min-width: 0;
  height: 34px;
  margin: 0;
  padding: 0 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0 !important;
  border-radius: 8px;
  background: transparent !important;
  box-shadow: none !important;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  color: var(--muted-text) !important;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background 0.15s ease,
    color 0.15s ease;
}

body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-tab:hover {
  color: var(--text-color) !important;
}

body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-tab.active {
  background: color-mix(
    in srgb,
    var(--primary-blue) 13%,
    var(--card-bg)
  ) !important;
  color: var(--primary-blue) !important;
  box-shadow: none !important;
}

/* The old active marker was an underline drawn with ::after. The pill carries
   that job now, and leaving both reads as two selection cues. */
body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-tab.active::after,
body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-tab::after {
  display: none;
}

/* Every control inside the rail keeps to its width. */
body:not(:has(.admin-container)) .signature-panel.is-in-rail input[type='text'],
body:not(:has(.admin-container)) .signature-panel.is-in-rail select,
body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-preview {
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

body:not(:has(.admin-container))
  .signature-panel.is-in-rail
  .signature-font-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* Apply follows the signature controls, like every other tool's action. */
body:not(:has(.admin-container)) .signature-panel.is-in-rail #applySignature {
  margin-top: 18px !important;
  width: 100%;
}

@media (max-width: 900px) {
  body:not(:has(.admin-container)) .sign-pdf-container.is-shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'toolbar' 'main' 'rail' 'result';
  }

  body:not(:has(.admin-container)) .sign-pdf-container.is-shell .sign-rail {
    border-left: 0;
    border-top: 1px solid var(--border-color);
  }
}

/* Sign PDF adopts the same shell box as every other tool: a bounded, centred
   panel rather than a full-bleed slab. Same measure, border, radius and canvas
   tint, so moving between tools does not change the page's shape. */
body:not(:has(.admin-container)) .sign-pdf-container.is-shell {
  max-width: var(--tool-shell-max);
  margin: 0 auto 44px;
  background: var(--tool-canvas);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  box-shadow: none;
  overflow: hidden;
}

/* The toolbar is the shell's header strip, not a floating bar. */
body:not(:has(.admin-container)) .sign-pdf-container.is-shell .sign-toolbar {
  background: var(--card-bg);
  border-bottom: 1px solid var(--border-color);
  margin: 0;
  padding: 12px 16px;
}

/* The document sits on the canvas tint, centred, with room to breathe. */
body:not(:has(.admin-container))
  .sign-pdf-container.is-shell
  .sign-main-content {
  background: var(--tool-canvas);
  padding: 18px var(--tool-canvas-pad) var(--tool-canvas-pad);
}

body:not(:has(.admin-container)) .sign-pdf-container.is-shell .pdf-container {
  padding: 0;
}

/* The empty state is the whole point of the page before a file exists, so it
   gets the shell's height rather than a thin strip. */
body:not(:has(.admin-container))
  .sign-pdf-container.is-shell
  .sign-empty-state {
  min-height: 360px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* Page navigation reads as a control strip above the document. */
body:not(:has(.admin-container)) .sign-pdf-container.is-shell .page-navigation {
  margin: 0 0 14px;
  gap: 10px;
}

/* Zoom controls, sitting with the paging controls above the document. */
body:not(:has(.admin-container)) .sign-pdf-container.is-shell .page-navigation {
  justify-content: center;
}

body:not(:has(.admin-container)) .page-zoom {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 14px;
  padding-left: 14px;
  border-left: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .page-zoom .page-zoom-level {
  min-width: 58px;
  margin: 0 !important;
  padding: 0 8px !important;
  height: 34px;
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

body:not(:has(.admin-container)) .page-zoom .button-icon {
  margin: 0 !important;
}

/* Sign PDF rail: Date sits below the signature builder as the other tool that
   drops something onto the page, rather than alone in the toolbar. */
body:not(:has(.admin-container)) .sign-rail__insert,
body:not(:has(.admin-container)) .sign-rail__group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .sign-rail__insert-label,
body:not(:has(.admin-container)) .sign-rail__group-label {
  /* Matches .signature-stroke-label so it reads as a section title in the same
     voice as the rest of the panel, not a small-caps eyebrow. */
  font-size: 13px;
  font-weight: 500;
  color: var(--muted-text);
}

body:not(:has(.admin-container)) .sign-rail__insert > .button,
body:not(:has(.admin-container)) .sign-rail__group > .button {
  width: 100%;
  margin: 0 !important;
  justify-content: center;
}

/* The mirrored pager sits under the document, so its divider belongs on top of
   it rather than under it as on the original above the page. */
body:not(:has(.admin-container)) .page-navigation--mirror {
  border-top: 1px solid var(--border-color);
  border-bottom: 0;
}

/* Zoomed pages must stay reachable.
   The document sits in a centred flex container that was overflow:visible, so
   anything wider than the container was simply clipped by .sign-main-content
   with no way to scroll to it - and because it is centred, it was cut on BOTH
   sides. The container scrolls instead.
   'safe center' matters: plain centring pushes overflow past the container's
   start edge, where scrolling cannot reach it. Safe centring falls back to
   start alignment as soon as the content no longer fits. */
body:not(:has(.admin-container)) .sign-pdf-container .pdf-container {
  overflow: auto;
  justify-content: safe center;
  overscroll-behavior-x: contain;
}

/* Never let the flex container squash the page to fit - the rendered width is
   the zoom level, and it must match the canvas backing store or the placement
   coordinates drift. */
body:not(:has(.admin-container)) .sign-pdf-container .pdf-container > canvas {
  flex: 0 0 auto;
}

/* Sign PDF rail: the document actions, moved down from the old toolbar strip.
   Download leads on its own line; Share and reset share the next one, so the
   rail's narrow column never forces them to wrap awkwardly. */
body:not(:has(.admin-container)) .sign-rail__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .sign-rail__actions > .button {
  margin: 0 !important;
  justify-content: center;
  /* Download has no border and Share has one, so their padding-derived heights
     differ by 2px. Pinned so all three read as one set. */
  min-height: 43.4px;
}

body:not(:has(.admin-container)) .sign-rail__actions > #downloadBtn {
  flex: 1 0 100%;
}

body:not(:has(.admin-container)) .sign-rail__actions > #shareBtn {
  flex: 1;
}

/* A label wrapping a radio or checkbox lays the control out inline, so it
   aligns to the text baseline rather than the text's centre - visibly off
   against bold option text. Flex centres the two against each other, and keeps
   a wrapped second line beside the control instead of under it. */
body:not(:has(.admin-container)) .tool-rail label:has(> input[type='radio']),
body:not(:has(.admin-container))
  .tool-rail
  label:has(> input[type='checkbox']) {
  display: flex;
  align-items: center;
  gap: 8px;
}

body:not(:has(.admin-container)) .tool-rail label > input[type='radio'],
body:not(:has(.admin-container)) .tool-rail label > input[type='checkbox'] {
  flex: 0 0 auto;
  margin: 0;
}

/* Page-preview cards (delete/extract/organize): the framework lays the select
   control out as a column - a full-width checkbox above a centred "Select" -
   so the box sits far left while its label sits centred, reading as two
   unrelated things. One centred row instead, box beside its word.
   Overridden here rather than edited in pdf_preview.css, which is shared. */
body:not(:has(.admin-container)) .preview-card-checkbox {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* Full width, so justify-content actually centres the pair in the card - at
     auto width the row shrank to content and sat left. */
  width: 100%;
}

body:not(:has(.admin-container)) .preview-card-checkbox-input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 0;
}

body:not(:has(.admin-container)) .preview-card-checkbox-label {
  text-align: left;
}

/* Delete pages: selection shortcuts, mode toggle and the live count. */
body:not(:has(.admin-container)) .delete-quick-select {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
}

body:not(:has(.admin-container)) .delete-quick-select-label {
  font-size: 13px;
  color: var(--muted-text);
}

body:not(:has(.admin-container)) .delete-quick-select-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

body:not(:has(.admin-container)) .delete-quick-select-buttons > .button {
  margin: 0 !important;
  flex: 1 1 auto;
  min-width: 58px;
  justify-content: center;
}

body:not(:has(.admin-container)) .delete-keep-mode {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  font-size: 13px;
  cursor: pointer;
}

body:not(:has(.admin-container)) .delete-keep-mode > input[type='checkbox'] {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 0;
}

body:not(:has(.admin-container)) .delete-summary {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--muted-text);
  min-height: 18px;
}

/* The one state worth interrupting for: the selection would empty the PDF. */
body:not(:has(.admin-container)) .delete-summary.is-warning {
  color: var(--error-color, #dc3545);
  font-weight: 600;
}

/* Overlay PDF: the staged file rows, once they sit in the rail.
   Their authored layout stacks the name under the size/remove row, which costs
   109px per file in a 340px column. Re-laid as a compact card: name over size,
   drag handle and remove flanking. display:contents lets the grandchildren take
   part in the row grid without rebuilding the markup the tool re-renders. */
body:not(:has(.admin-container)) .tool-rail-files .overlay-file-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 8px;
  row-gap: 1px;
  padding: 9px 11px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
}

body:not(:has(.admin-container))
  .tool-rail-files
  .overlay-file-item
  .file-item-content {
  display: contents;
}

body:not(:has(.admin-container))
  .tool-rail-files
  .overlay-file-item
  .file-item-drag-handle {
  grid-column: 1;
  grid-row: 1 / span 2;
  cursor: grab;
  opacity: 0.55;
}

/* Name first: it is what identifies the layer. */
body:not(:has(.admin-container))
  .tool-rail-files
  .overlay-file-item
  .overlay-file-header {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  /* Its authored vertical padding and loose line-height are for a full-width
     row; in the rail they just make the card tall. */
  padding: 0;
  line-height: 1.35;
}

body:not(:has(.admin-container))
  .tool-rail-files
  .overlay-file-item
  .overlay-file-name {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
  font-size: 13px;
  line-height: 1.35;
}

body:not(:has(.admin-container))
  .tool-rail-files
  .overlay-file-item
  .file-item-info {
  grid-column: 2;
  grid-row: 2;
  min-width: 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--muted-text);
}

body:not(:has(.admin-container))
  .tool-rail-files
  .overlay-file-item
  .file-item-remove {
  grid-column: 3;
  grid-row: 1 / span 2;
  margin: 0 !important;
}

/* The rail's dropdowns are the base custom-dropdown component: a wrapper around
   a trigger button. Both were carrying full field chrome - background, border,
   padding - so every dropdown rendered as a box inside a box. The wrapper is a
   positioning container only; the trigger is the control. */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail .custom-dropdown {
  background: none !important;
  border: 0 !important;
  padding: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}

/* With the wrapper's padding gone the trigger spans the rail, and it takes the
   same shape as the text inputs and option cards beside it. */
body:not(:has(.admin-container))
  .card.tool-shell
  .tool-rail
  .custom-dropdown-trigger {
  width: 100% !important;
  padding: 10px 12px !important;
  border-radius: 10px !important;
  font-size: 14px;
}

/* ocr-pdf and extract-images describe the loaded file with .extract-file-box
   tiles - a 64px icon over a label and value - laid out three across. In the
   shell's narrow file-card column they stack instead, 153px each, so the facts
   about one file ran 478px down the page. Collapsed to the same quiet rows the
   other tools' cards use: the tile chrome and the icon carry no information
   the value does not. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .extract-file-boxes {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
}

body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .extract-file-box {
  display: block;
  width: 100%;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  text-align: center;
}

body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .extract-file-box-icon,
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .extract-file-box-label {
  display: none;
}

body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .extract-file-box-value {
  margin: 0;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--muted-text);
}

/* The filename leads, as on every other file card. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-filecard
  .extract-file-box:first-child
  .extract-file-box-value {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-color);
  overflow-wrap: anywhere;
}

/* remove-password: the rail explains what the button will do, since the
   password itself is asked for in a dialog. */
body:not(:has(.admin-container)) .remove-password-hint {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--muted-text);
}

/* A result that carries a page preview earns the whole canvas column - at the
   480px the plain "done, here's your download" results use, the rendered page
   and its pager are squeezed into half the available width. Results without a
   preview keep the narrow measure: a line of text and three buttons do not
   read better stretched. */
body:not(:has(.admin-container)) .card.tool-shell > .result-area:has(canvas),
body:not(:has(.admin-container))
  .card.tool-shell
  > .result-area:has(.pdf-preview-container) {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* ---- result controls, once moved into the rail --------------------------- */

/* Download / Share / Remove become icon-only: three labelled buttons do not
   fit a 340px column side by side, and stacked they push everything else off
   screen. font-size:0 hides the label visually while leaving it in the
   accessibility tree, so the buttons still announce themselves. */
body:not(:has(.admin-container)) .tool-rail .tool-rail-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .tool-rail .tool-rail-actions > .button {
  flex: 1;
  min-width: 0;
  margin: 0 !important;
  padding: 0 !important;
  height: 43.4px;
  /* !important: the base button rule sets font-size with it too. */
  font-size: 0 !important;
  /* Gap zeroed for the same reason: the hidden label still counts as a flex
     item, and its gap would shift the icon off centre. */
  gap: 0 !important;
  justify-content: center;
}

body:not(:has(.admin-container)) .tool-rail .tool-rail-actions > .button .fas {
  margin: 0 !important;
  font-size: 15px !important;
}

body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-actions
  .tooltip-wrapper {
  flex: 0 0 auto;
}

/* "Do you want to edit the pdf?" collapses to its button in the rail. */
body:not(:has(.admin-container)) .tool-rail .tool-rail-edit {
  margin-top: 10px;
}

body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-edit
  .result-edit-pdf-inner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: none;
}

body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-edit
  .result-edit-pdf-icon,
body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-edit
  .result-edit-pdf-text {
  display: none;
}

body:not(:has(.admin-container)) .tool-rail .tool-rail-edit .button {
  width: 100%;
  margin: 0 !important;
  justify-content: center;
}

/* "Continue to..." as a quiet list, one tool per line. */
body:not(:has(.admin-container)) .tool-rail .tool-rail-continue {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border-color);
}

body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-continue
  .result-continue-header {
  margin-bottom: 8px;
}

body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-continue
  .result-continue-title {
  font-size: 13px;
  font-weight: 600;
}

body:not(:has(.admin-container))
  .tool-rail
  .tool-rail-continue
  .result-continue-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* ═══ Result drawer ═══════════════════════════════════════════════════════
   One panel for every tool's outcome. Slides in over the page when work
   finishes: the document stays on the canvas behind it, and everything you do
   with the result - download, share, edit, discard, continue - lives here.
   Replaces the per-tool result panels that used to grow inside the page.
   ═══════════════════════════════════════════════════════════════════════════ */
body:not(:has(.admin-container)) .result-drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 1400;
  background: color-mix(in srgb, var(--text-color) 42%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s ease;
}

body:not(:has(.admin-container)) .result-drawer-scrim.is-open {
  opacity: 1;
  pointer-events: auto;
}

body:not(:has(.admin-container)) .result-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1401;
  width: 420px;
  max-width: 92vw;
  display: flex;
  flex-direction: column;
  background: var(--card-bg);
  border-left: 1px solid var(--border-color);
  box-shadow: -18px 0 48px
    color-mix(in srgb, var(--text-color) 16%, transparent);
  transform: translateX(100%);
  transition: transform 0.34s cubic-bezier(0.22, 0.61, 0.36, 1);
}

body:not(:has(.admin-container)) .result-drawer.is-open {
  transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
  body:not(:has(.admin-container)) .result-drawer,
  body:not(:has(.admin-container)) .result-drawer-scrim {
    transition: none;
  }
}

body:not(:has(.admin-container)) .result-drawer__head {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  /* Right padding clears the corner close button. */
  padding: 18px 56px 18px 20px;
  border-bottom: 1px solid var(--border-color);
}

body:not(:has(.admin-container)) .result-drawer__status {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 15px;
  background: color-mix(
    in srgb,
    var(--success-color, #2f7d51) 14%,
    transparent
  );
  color: var(--success-color, #2f7d51);
}

body:not(:has(.admin-container)) .result-drawer__status.is-error {
  background: color-mix(in srgb, var(--error-color, #b0521c) 16%, transparent);
  color: var(--error-color, #b0521c);
}

body:not(:has(.admin-container)) .result-drawer__title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading-color);
}

body:not(:has(.admin-container)) .result-drawer__sub {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--muted-text);
}

/* Anchored to the drawer's own top-right corner, where a close control is
   looked for, rather than riding along at the end of the header's flex row.
   The selector carries `.result-drawer button` because the base button rule is
   `body.theme-* button.button` (0,2,2) - a plain class guard ties lower and
   loses, which is what left this looking like a bordered box. */
body:not(:has(.admin-container)) .result-drawer button.result-drawer__close {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 1;
  width: 34px !important;
  min-width: 0 !important;
  height: 34px !important;
  margin: 0 !important;
  padding: 0 !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  border: 0 !important;
  border-radius: 999px !important;
  background: none !important;
  box-shadow: none !important;
  color: var(--muted-text) !important;
  font-size: 15px !important;
  cursor: pointer;
}

body:not(:has(.admin-container))
  .result-drawer
  button.result-drawer__close:hover {
  background: var(--item-hover-bg) !important;
  color: var(--text-color) !important;
}

body:not(:has(.admin-container))
  .result-drawer
  button.result-drawer__close
  .fas {
  margin: 0 !important;
}

body:not(:has(.admin-container)) .result-drawer__body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

body:not(:has(.admin-container)) .result-drawer__foot {
  padding: 14px 20px 18px;
  border-top: 1px solid var(--border-color);
  background: var(--card-bg);
}

/* The actions the tool rendered, re-laid for a 420px column: download leads on
   its own line, the rest share the next one. */
body:not(:has(.admin-container)) .result-drawer__foot .result-download {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}

body:not(:has(.admin-container))
  .result-drawer__foot
  .result-download
  > .button {
  flex: 1;
  min-width: 0;
  margin: 0 !important;
  justify-content: center;
}

body:not(:has(.admin-container))
  .result-drawer__foot
  .result-download
  > .button-primary {
  flex: 1 0 100%;
}

/* Inside the drawer the result panel is just a container - its own frame,
   tint and centring were for sitting in the page. */
body:not(:has(.admin-container)) .result-drawer .result-area {
  display: block !important;
  max-width: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
}

body:not(:has(.admin-container)) .result-drawer .optimize-success-banner {
  display: block;
  padding: 0;
  border: 0;
  background: none;
}

body:not(:has(.admin-container)) .result-drawer .optimize-success-info {
  display: none;
}

body:not(:has(.admin-container)) .result-drawer .optimize-stats-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

body:not(:has(.admin-container)) .result-drawer .result-edit-pdf {
  margin: 0;
}

body:not(:has(.admin-container)) .result-drawer .result-continue {
  margin: 0;
  padding: 0;
  border: 0;
}

body:not(:has(.admin-container)) .result-drawer .result-continue-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Re-open control: closing the drawer must not lose the result. */
body:not(:has(.admin-container)) .result-reopen {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 16px !important;
}

/* Under 720px it is a bottom sheet - same DOM, same behaviour. */
@media (max-width: 720px) {
  body:not(:has(.admin-container)) .result-drawer {
    top: auto;
    left: 0;
    width: 100%;
    max-width: 100%;
    height: 84vh;
    border-left: 0;
    border-top: 1px solid var(--border-color);
    border-radius: 16px 16px 0 0;
    transform: translateY(100%);
  }
  body:not(:has(.admin-container)) .result-drawer.is-open {
    transform: translateY(0);
  }
}

/* Extracted images: the per-item action becomes a small download icon pinned to
   the top-right of its own image, instead of a full-width labelled button under
   it. The label was wider than the thumbnail it belonged to and pushed the grid
   twice as tall as the pictures. */
body:not(:has(.admin-container)) .image-preview-item {
  position: relative;
}

body:not(:has(.admin-container)) .image-preview-item .image-preview-actions,
body:not(:has(.admin-container)) .image-preview-item > .image-preview-download {
  position: absolute;
  top: 8px;
  right: 8px;
  margin: 0;
  padding: 0;
  z-index: 2;
}

body:not(:has(.admin-container))
  .image-preview-item
  .image-preview-actions
  button.image-preview-button,
body:not(:has(.admin-container))
  .image-preview-item
  > button.image-preview-download {
  width: 32px !important;
  min-width: 0 !important;
  height: 32px !important;
  margin: 0 !important;
  padding: 0 !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  border-radius: 999px !important;
  /* Label hidden visually, kept for screen readers. */
  font-size: 0 !important;
  /* The hidden label is still a flex item, so the button's 10px gap was being
     centred along with it - pushing the icon 5px off-centre. */
  gap: 0 !important;
  background: var(--card-bg) !important;
  border: 1px solid var(--border-color) !important;
  color: var(--text-color) !important;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--text-color) 18%, transparent);
  opacity: 0;
  transition:
    opacity 0.15s ease,
    background 0.15s ease;
}

body:not(:has(.admin-container))
  .image-preview-item
  .image-preview-actions
  button.image-preview-button
  .fas,
body:not(:has(.admin-container))
  .image-preview-item
  > button.image-preview-download
  .fas {
  margin: 0 !important;
  font-size: 13px !important;
}

/* Revealed on hover or keyboard focus - and always on touch, where there is no
   hover to reveal it with. These repeat the full selector shape of the rule
   above: a shorter `.image-preview-item:hover .image-preview-button` guard
   scores (0,4,1) against that rule's (0,4,2) and loses, which would leave the
   download permanently invisible. */
body:not(:has(.admin-container))
  .image-preview-item:hover
  .image-preview-actions
  button.image-preview-button,
body:not(:has(.admin-container))
  .image-preview-item:focus-within
  .image-preview-actions
  button.image-preview-button,
body:not(:has(.admin-container))
  .image-preview-item:hover
  > button.image-preview-download,
body:not(:has(.admin-container))
  .image-preview-item:focus-within
  > button.image-preview-download {
  opacity: 1;
}

@media (hover: none) {
  body:not(:has(.admin-container))
    .image-preview-item
    .image-preview-actions
    button.image-preview-button,
  body:not(:has(.admin-container))
    .image-preview-item
    > button.image-preview-download {
    opacity: 1;
  }
}

body:not(:has(.admin-container))
  .image-preview-item
  .image-preview-button:hover,
body:not(:has(.admin-container))
  .image-preview-item
  > .image-preview-download:hover {
  background: var(--item-hover-bg) !important;
}

/* Continue-to cards: the bottom border was missing, so hovering lit three sides
   and left the card open at the base. Restated on all four sides, and the hover
   colour applied to the whole box. */
body:not(:has(.admin-container)) a.continue-tool-card,
body:not(:has(.admin-container)) .continue-tool-card {
  border: 1px solid var(--border-color) !important;
}

body:not(:has(.admin-container)) a.continue-tool-card:hover,
body:not(:has(.admin-container)) .continue-tool-card:hover {
  border-color: var(--primary-color) !important;
  background: var(--item-hover-bg);
}

/* Editing is the most capable thing you can do with a finished file, so in the
   drawer it is a promoted card rather than another grey button in a stack: an
   accent-tinted surface, the editor's mark in a chip, what it does underneath,
   and a chevron. It reads as a destination, which is what it is. */
body:not(:has(.admin-container)) .result-drawer .result-edit-pdf {
  /* Space before "Continue to..." so the promoted card reads as its own thing
     rather than the first row of that list. */
  margin: 0 0 18px;
  padding: 0;
  border: 0;
  background: none;
}

body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-inner {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  border: 1px solid
    color-mix(in srgb, var(--primary-color) 26%, var(--border-color));
  border-radius: 14px;
  background: color-mix(in srgb, var(--primary-color) 7%, var(--card-bg));
  transition:
    border-color 0.15s ease,
    background 0.15s ease,
    transform 0.12s ease;
}

body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-inner:hover {
  border-color: var(--primary-color);
  background: color-mix(in srgb, var(--primary-color) 11%, var(--card-bg));
  transform: translateY(-1px);
}

body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  /* The base style pads this by 16px and gives the glyph a 24px line box, which
     together pushed the icon 10px below the chip's centre. */
  padding: 0 !important;
  border-radius: 11px;
  background: color-mix(in srgb, var(--primary-color) 16%, transparent);
  color: var(--primary-color);
  font-size: 15px;
  line-height: 1;
}

body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-icon i,
body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-icon svg,
body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-icon .icon {
  display: block;
  margin: 0 !important;
  font-size: 15px !important;
  line-height: 1 !important;
}

body:not(:has(.admin-container)) .result-drawer .result-edit-pdf-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading-color);
}

body:not(:has(.admin-container)) .result-edit-pdf-hint {
  font-size: 12px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--muted-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The whole card is the target; the button is its hit area and its chevron. */
body:not(:has(.admin-container)) .result-drawer .result-edit-pdf .button {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 14px !important;
  background: none !important;
  box-shadow: none !important;
  font-size: 0 !important;
  gap: 0 !important;
  /* !important: the base button rule centres its content with it, which left
     the chevron sitting against the title instead of at the card's edge. */
  justify-content: flex-end !important;
  align-items: center !important;
}

body:not(:has(.admin-container))
  .result-drawer
  .result-edit-pdf
  .button::after {
  content: '';
  width: 8px;
  height: 8px;
  margin-right: 18px;
  border-top: 2px solid var(--muted-text);
  border-right: 2px solid var(--muted-text);
  transform: rotate(45deg);
}

body:not(:has(.admin-container))
  .result-drawer
  .result-edit-pdf-inner:hover
  .button::after {
  border-color: var(--primary-color);
}

/* Result stats in the drawer.
   Three tiles with big icons work across a wide page; in a 420px column they
   wrap, and the icon takes more room than the number it decorates. Re-laid as a
   plain label/value list - the figures are the point, and stacking them lets
   the eye compare 1.12 MB against 969.56 KB down a single edge. */
body:not(:has(.admin-container)) .result-drawer .optimize-stats-grid {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  overflow: hidden;
}

body:not(:has(.admin-container)) .result-drawer .optimize-stat-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  width: auto;
  min-width: 0;
  margin: 0;
  padding: 10px 13px;
  border: 0;
  border-bottom: 1px solid var(--border-color);
  border-radius: 0;
  background: none;
  box-shadow: none;
  text-align: left;
}

body:not(:has(.admin-container)) .result-drawer .optimize-stat-card:last-child {
  border-bottom: 0;
}

/* The icon stays, just at the size of a bullet rather than a tile: enough to
   tell the rows apart at a glance without competing with the figure. */
body:not(:has(.admin-container)) .result-drawer .optimize-stat-icon {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin: 0;
  padding: 0;
  border-radius: 7px;
  background: var(--item-bg);
  font-size: 12px;
  line-height: 1;
}

/* The tools set 28px on these glyphs for a full-width tile; inside a 24px chip
   that simply overflows, which is why the chip looked absent and the icons
   oversized. */
body:not(:has(.admin-container)) .result-drawer .optimize-stat-icon .icon,
body:not(:has(.admin-container)) .result-drawer .optimize-stat-icon i,
body:not(:has(.admin-container)) .result-drawer .optimize-stat-icon svg {
  width: auto;
  height: auto;
  margin: 0 !important;
  font-size: 12px !important;
  line-height: 1;
}

body:not(:has(.admin-container)) .result-drawer .optimize-stat-label {
  grid-column: 2;
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted-text);
}

body:not(:has(.admin-container)) .result-drawer .optimize-stat-value {
  grid-column: 3;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--heading-color);
  font-variant-numeric: tabular-nums;
}

/* A saving is good news, so the row says so: a downward arrow and the positive
   colour, rather than a bare number the reader has to interpret. */
body:not(:has(.admin-container))
  .result-drawer
  .optimize-stat-card[data-stat-trend='down']
  .optimize-stat-value {
  color: var(--success-color, #2f7d51);
}

body:not(:has(.admin-container))
  .result-drawer
  .optimize-stat-card[data-stat-trend='down']
  .optimize-stat-value::before {
  content: '';
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 6px solid currentColor;
  transform: translateY(1px);
}

/* Vertical rhythm inside the drawer.
   The body sets `gap`, but that only reaches its own children - and everything
   a tool renders (banner, stats, editor card, continue list) arrives nested
   inside the adopted result element, so those blocks were stacking with no
   space at all between them. Spaced here instead, at the level they live at. */
body:not(:has(.admin-container)) .result-drawer .result-area > * + * {
  margin-top: 18px;
}

/* A banner with its actions moved to the foot has nothing left to say; without
   this it still contributes a gap. */
body:not(:has(.admin-container)) .result-drawer .optimize-success-banner:empty,
body:not(:has(.admin-container))
  .result-drawer
  .optimize-success-banner:not(:has(*)) {
  display: none;
}

/* The list heading owns the space above itself, so it does not sit on the block
   before it. */
body:not(:has(.admin-container)) .result-drawer .result-continue-header {
  margin-bottom: 10px;
}

/* The drop zone hovers quietly.
   It had a gradient sweep, then Loo walking across; both were motion for its
   own sake on a control whose job is to be a target. The border and background
   shift on hover already say it is interactive, and nothing moves. */
body:not(:has(.admin-container)) .dropzone::before,
body:not(:has(.admin-container)) .dropzone::after {
  display: none;
}

body:not(:has(.admin-container)) .dropzone.drag-over::before {
  animation: none;
}

/* Before a file exists there is nothing to contain: the card was drawing a
   tinted, bordered 1240px panel around a 620px drop zone, so the eye read a
   frame with a hole in it. The drop zone is the object at that point, and it
   carries its own surface and dashed edge - it sits straight on the page until
   there is a document, a rail and a result to hold together. */
body:not(:has(.admin-container)) .tools-section ~ .card:not(.has-file),
body:not(:has(.admin-container)) .card.tool-shell:not(.has-file) {
  background: none;
  border-color: transparent;
  box-shadow: none;
}

/* The rail's surface still runs the full height of the shell - it is the panel
   the canvas sits beside. Only its buttons stopped being pinned to the floor;
   they follow the controls they belong to. */
body:not(:has(.admin-container)) .card.tool-shell > .tool-rail {
  align-self: stretch;
}

/* A result is read in the drawer, never in the page.
   Tools render into their .result-area and the drawer adopts it a moment later;
   in between, the panel was painting in the page - which is the green "success"
   block with Download All that flashed after a conversion and then vanished as
   the drawer took it. Hidden wherever it sits in the page, shown only once the
   drawer is hosting it. */
body:not(:has(.admin-container)) .card .result-area,
body:not(:has(.admin-container)) .tools-section ~ .card .result-area,
body:not(:has(.admin-container)) main .result-area {
  display: none !important;
}

body:not(:has(.admin-container)) .result-drawer .result-area {
  display: block !important;
}

/* Space between staged file rows, independent of whether the list ends up
   laid out as flex (our rule) or block (the tool's inline style). */
body:not(:has(.admin-container)) .card.tool-shell .tool-rail-files > * + * {
  margin-top: 8px;
}

/* The merge drag hint is the framework's info alert and should look like one.
   Something in the cascade was flattening its padding to 0, which squashed it
   into a 26px strip - the "compressed" look. Restated to the component's own
   metrics so it reads as a normal alert again. */
body:not(:has(.admin-container)) .alert.merge-drag-info {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  line-height: 1.5;
}

/* ═══ Landing: privacy ════════════════════════════════════════════════════
   A short, factual section rather than a badge wall: what runs locally, how a
   server tool is marked, and what happens to a file that does travel. The
   middle card shows the very shield the tools carry, so the marker is learned
   here and recognised there.
   ═══════════════════════════════════════════════════════════════════════════ */
.pdf-privacy {
  max-width: 1140px;
  margin: 0 auto;
  padding: 72px 24px 8px;
}

.privacy-grid {
  display: grid;
  /* Three, explicitly: auto-fit resolved to four tracks at this width and left
     the row with a hole where a fourth card would be. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-top: 34px;
}

@media (max-width: 900px) {
  .privacy-grid {
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  }
}

/* Icon and heading share the first row; the body spans both columns beneath
   them. Running the copy under the icon rather than indenting it keeps the
   measure intact - these cards are ~300px wide, and giving up the icon column
   would wrap the text a line or two earlier. */
.privacy-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 12px;
  row-gap: 8px;
  align-items: center;
  padding: 22px 22px 24px;
  border: 1px solid var(--border-color);
  border-radius: 16px;
  background: var(--card-bg);
}

.privacy-card-icon {
  grid-column: 1;
  grid-row: 1;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--primary-color) 12%, transparent);
  color: var(--primary-color);
}

.privacy-card h3 {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--heading-color);
}

.privacy-card p {
  grid-column: 1 / -1;
  grid-row: 2;
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--muted-text);
}

@media (max-width: 640px) {
  .pdf-privacy {
    padding: 48px 18px 4px;
  }

  .privacy-grid {
    margin-top: 24px;
  }
}

/* Merge already has a canvas: the shell's left column. Its page-order block was
   drawing a second surface inside it - background, border and padding - so the
   pages sat in a panel within a panel. Stripped back to plain content on the
   canvas, the way every other tool's preview behaves. */
body:not(:has(.admin-container)) .card.tool-shell .merge-all-pages-container {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* Option cards in the rail.
   The component lays title, description and control out in one row - fine
   across a wide page, but in a 303px rail it gave the title 114px and the
   description 145px, so headings wrapped mid-phrase and the text ran into the
   radio. Re-laid as a card: title over description, control kept to the side. */
body:not(:has(.admin-container)) .tool-rail .selectable-card {
  /* !important: the compact variant sets display:flex with it, which is what
     kept the row layout even though every grid placement below applied. */
  display: grid !important;
  /* One column: the component positions its radio absolutely at right:16px, so
     it never joins the grid - a control column just collapsed to 0 and let the
     text run underneath it. The right padding reserves that space instead. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    'title'
    'desc';
  align-items: center;
  row-gap: 3px;
  padding: 13px 46px 13px 15px;
}

/* Kept vertically centred against the card rather than pinned near its top,
   which looked detached once the card grew to two lines. */
body:not(:has(.admin-container)) .tool-rail .selectable-card > input {
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
}

body:not(:has(.admin-container)) .tool-rail .selectable-card-title {
  grid-area: title;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading-color);
}

body:not(:has(.admin-container)) .tool-rail .selectable-card-title .fas {
  flex: 0 0 auto;
  margin: 0 !important;
  font-size: 13px;
  color: var(--primary-color);
}

body:not(:has(.admin-container)) .tool-rail .selectable-card-desc {
  grid-area: desc;
  min-width: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted-text);
}

/* ═══ Compare PDF ═════════════════════════════════════════════════════════
   Compare is the one tool whose output is an answer rather than a file, so the
   diff owns the canvas and the rail drives it. Diff colours are kept clear of
   the brand red, which stays on actions - a highlight must never read as a
   button.
   ═══════════════════════════════════════════════════════════════════════════ */
body:not(:has(.admin-container)) {
  --diff-add: #2f7d51;
  --diff-remove: #b0521c;
  --diff-change: #7a5bd6;
}

body.theme-dark:not(:has(.admin-container)) {
  --diff-add: #6fcf97;
  --diff-remove: #e0a06a;
  --diff-change: #a996f0;
}

/* A and B are roles, not an order: the direction of the comparison is the one
   thing a reader must not have to guess. */
body:not(:has(.admin-container)) .compare-dropzone-title {
  display: flex;
  align-items: center;
  gap: 8px;
}

body:not(:has(.admin-container)) .compare-side {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 7px;
  background: var(--tint, var(--item-bg));
  color: var(--primary-color);
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 500;
}

body:not(:has(.admin-container)) .compare-side-role {
  font-size: 13px;
  font-weight: 600;
  color: var(--heading-color);
}

/* ── summary in the rail ─────────────────────────────────────────────────── */
body:not(:has(.admin-container)) .tool-rail .compare-summary-grid {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  overflow: hidden;
}

body:not(:has(.admin-container)) .tool-rail .compare-summary-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 9px 12px;
  border: 0;
  border-bottom: 1px solid var(--border-color);
  background: none;
  text-align: left;
}

body:not(:has(.admin-container)) .tool-rail .compare-summary-item:last-child {
  border-bottom: 0;
}

/* A dot per row, coloured by what the number counts. */
body:not(:has(.admin-container)) .tool-rail .compare-summary-item::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted-text);
}

body:not(:has(.admin-container))
  .tool-rail
  .compare-summary-item[data-kind='text']::before {
  background: var(--diff-change);
}

body:not(:has(.admin-container))
  .tool-rail
  .compare-summary-item[data-kind='visual']::before {
  background: var(--diff-remove);
}

body:not(:has(.admin-container))
  .tool-rail
  .compare-summary-item[data-kind='delta']::before {
  background: var(--diff-add);
}

body:not(:has(.admin-container)) .tool-rail .compare-summary-item span {
  font-size: 13px;
  color: var(--muted-text);
}

body:not(:has(.admin-container)) .tool-rail .compare-summary-item strong {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 14px;
  font-weight: 500;
  color: var(--heading-color);
  font-variant-numeric: tabular-nums;
}

/* ── rail controls ───────────────────────────────────────────────────────── */
body:not(:has(.admin-container)) .compare-rail-label {
  margin: 18px 0 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted-text);
}

body:not(:has(.admin-container)) .compare-modes {
  display: flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  background: var(--item-bg);
}

body:not(:has(.admin-container)) button.compare-mode {
  flex: 1;
  padding: 7px 6px !important;
  border: 0 !important;
  border-radius: 8px !important;
  background: none !important;
  box-shadow: none !important;
  color: var(--muted-text) !important;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

body:not(:has(.admin-container)) button.compare-mode[aria-pressed='true'] {
  background: var(--card-bg) !important;
  color: var(--heading-color) !important;
}

body:not(:has(.admin-container)) .compare-check {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 12px;
  font-size: 13px;
  cursor: pointer;
}

body:not(:has(.admin-container)) .compare-check input {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 0;
}

body:not(:has(.admin-container)) .compare-jump {
  display: flex;
  align-items: center;
  gap: 8px;
}

body:not(:has(.admin-container)) button.compare-jump-btn {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  padding: 0 !important;
  margin: 0 !important;
  border-radius: 10px !important;
  font-size: 0 !important;
  gap: 0 !important;
}

body:not(:has(.admin-container)) button.compare-jump-btn .fas {
  margin: 0 !important;
  font-size: 13px !important;
}

body:not(:has(.admin-container)) .compare-jump-count {
  flex: 1;
  text-align: center;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12.5px;
  color: var(--muted-text);
  font-variant-numeric: tabular-nums;
}

/* ── film strip: colour says what kind, position says where ──────────────── */
body:not(:has(.admin-container)) .compare-filmstrip {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

body:not(:has(.admin-container)) button.compare-film {
  position: relative;
  width: 30px;
  height: 40px;
  margin: 0 !important;
  padding: 0 !important;
  border: 1px solid var(--border-color) !important;
  border-radius: 5px !important;
  background: var(--card-bg) !important;
  box-shadow: none !important;
  cursor: pointer;
}

body:not(:has(.admin-container)) button.compare-film span {
  position: absolute;
  inset: auto 0 2px 0;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 9px;
  color: var(--muted-text);
}

body:not(:has(.admin-container)) button.compare-film[data-kind='add'] {
  border-color: color-mix(
    in srgb,
    var(--diff-add) 55%,
    var(--border-color)
  ) !important;
  background: color-mix(
    in srgb,
    var(--diff-add) 12%,
    var(--card-bg)
  ) !important;
}

body:not(:has(.admin-container)) button.compare-film[data-kind='remove'] {
  border-color: color-mix(
    in srgb,
    var(--diff-remove) 55%,
    var(--border-color)
  ) !important;
  background: color-mix(
    in srgb,
    var(--diff-remove) 12%,
    var(--card-bg)
  ) !important;
}

body:not(:has(.admin-container)) button.compare-film[data-kind='change'] {
  border-color: color-mix(
    in srgb,
    var(--diff-change) 55%,
    var(--border-color)
  ) !important;
  background: color-mix(
    in srgb,
    var(--diff-change) 12%,
    var(--card-bg)
  ) !important;
}

body:not(:has(.admin-container)) button.compare-film.is-target {
  outline: 2px solid var(--primary-color);
  outline-offset: 1px;
}

/* ── page rows on the canvas ─────────────────────────────────────────────── */
body:not(:has(.admin-container)) .compare-page.is-target {
  border-color: color-mix(
    in srgb,
    var(--primary-color) 45%,
    var(--border-color)
  );
  box-shadow: 0 0 0 3px
    color-mix(in srgb, var(--primary-color) 12%, transparent);
}

body:not(:has(.admin-container)) .compare-chips {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

body:not(:has(.admin-container)) .compare-chip {
  padding: 2px 8px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.7;
}

body:not(:has(.admin-container)) .compare-chip.add {
  color: var(--diff-add);
}
body:not(:has(.admin-container)) .compare-chip.remove {
  color: var(--diff-remove);
}
body:not(:has(.admin-container)) .compare-chip.change {
  color: var(--diff-change);
}
body:not(:has(.admin-container)) .compare-chip.visual {
  color: var(--diff-remove);
}

body:not(:has(.admin-container)) .compare-chip.same {
  color: var(--muted-text);
  border-color: var(--border-color);
  font-weight: 500;
}

body:not(:has(.admin-container)) .compare-page-header {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Overlay: one column, B beneath A's highlight layer. Side by side answers
   "what does it say now"; overlay answers "did anything move". */
body:not(:has(.admin-container)) .compare-page.is-overlay .compare-page-grid {
  grid-template-columns: 1fr;
}

body:not(:has(.admin-container))
  .compare-page.is-overlay
  .compare-canvas-wrap:last-child {
  display: none;
}

/* The comparison needs the whole canvas: it was capped at 560px, and two 260px
   columns plus their gap need 536px of the 526px that left - so the pair
   silently collapsed into a stack, which is the one layout this tool must not
   have. Full width, and the pair is pinned to two columns rather than left to
   auto-fit: side by side is the point. */
body:not(:has(.admin-container)) .card.tool-shell #compareViewer {
  max-width: none;
  width: 100%;
}

body:not(:has(.admin-container)) .card.tool-shell .compare-page-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

body:not(:has(.admin-container))
  .card.tool-shell
  .compare-page.is-overlay
  .compare-page-grid {
  grid-template-columns: 1fr;
}

/* Both pages are the same size, so neither side reads as the important one. */
body:not(:has(.admin-container)) .card.tool-shell .compare-canvas-wrap {
  min-width: 0;
}

body:not(:has(.admin-container)) .card.tool-shell .compare-canvas,
body:not(:has(.admin-container)) .card.tool-shell .compare-overlay-canvas {
  width: 100%;
  height: auto;
}

/* Narrow screens have no room for two pages: there the stack is the right
   answer rather than a failure. */
@media (max-width: 820px) {
  body:not(:has(.admin-container)) .card.tool-shell .compare-page-grid {
    grid-template-columns: 1fr;
  }
}

/* ── The rail follows you down the canvas ─────────────────────────────────
   On a long canvas - a comparison, a page grid - the controls scrolled out of
   the viewport, so every jump to the next difference had to be followed by a
   scroll back up to reach the button again. The rail sticks instead.

   Its surface still runs the full height, but that is now painted by the card
   as a right-hand band rather than by the rail element itself: a sticky element
   cannot also stretch to the container's height, and the panel reading as
   full-height is what matters visually, not which element paints it. */
body:not(:has(.admin-container)) .card.tool-shell.has-file {
  background-image: linear-gradient(
    to right,
    transparent calc(100% - var(--tool-rail)),
    var(--card-bg) calc(100% - var(--tool-rail))
  );
}

@media (min-width: 861px) {
  body:not(:has(.admin-container)) .card.tool-shell > .tool-rail {
    position: sticky;
    top: 14px;
    align-self: start;
    /* The band above paints the column now. */
    background: none;
    /* No scrollbars of its own: the controls are short, and a panel that
       scrolls independently of the page reads as a second document. If the rail
       ever outgrows the viewport the page scroll still reaches it. */
    overflow: visible;
  }
}

/* The card clipped its children with overflow:hidden - which also disables
   position:sticky anywhere inside it, so the rail scrolled away no matter what
   it declared. The clip is only there to keep the canvas inside the rounded
   corners, so the corners are clipped where they actually are instead. */
body:not(:has(.admin-container)) .card.tool-shell {
  overflow: visible;
}

body:not(:has(.admin-container)) .card.tool-shell > .tool-rail {
  border-top-right-radius: inherit;
  border-bottom-right-radius: inherit;
}

/* The canvas and the rail start on the same line: the comparison viewer
   carried a 24px top margin that the rail had no counterpart for, so the two
   columns began at different heights. */
body:not(:has(.admin-container)) .card.tool-shell #compareViewer {
  margin-top: 0;
}

/* The rail's title and the first row's title sit on the same line: the head
   padded its heading 7px lower than the row header did, so the two columns read
   as starting at slightly different heights even though their panels align. */
body:not(:has(.admin-container))
  .card.tool-shell
  > .tool-rail
  > .tool-rail__head {
  padding-top: 10px;
  padding-bottom: 14px;
}

/* A page opened full size wants far more room than a form dialog. The base
   modal sets a fixed 640px width, which max-width alone cannot widen - hence
   the explicit width, and the !important to beat it. */
body:not(:has(.admin-container)) .modal .modal-content.compare-fullpage-dialog {
  /* Sized to the page rather than to a fixed measure: a portrait page in a
     1240px dialog is a narrow sheet marooned in empty space. The dialog takes
     the page's width and the page takes all the height going. */
  width: auto !important;
  max-width: min(1240px, 94vw) !important;
}

body:not(:has(.admin-container)) .compare-fullpage-body {
  max-height: min(86vh, 1100px);
}

body:not(:has(.admin-container)) .compare-fullpage-canvas {
  width: auto;
  max-width: 100%;
  /* Room for the dialog's own header and footer inside the viewport. */
  max-height: calc(min(86vh, 1100px) - 8px);
  height: auto;
  object-fit: contain;
}

/* OCR's action row, once the drawer hosts it in the pinned foot. */
body:not(:has(.admin-container)) .result-drawer__foot .ocr-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}

body:not(:has(.admin-container)) .result-drawer__foot .ocr-actions > .button {
  flex: 1;
  min-width: 0;
  margin: 0 !important;
  justify-content: center;
}

body:not(:has(.admin-container))
  .result-drawer__foot
  .ocr-actions
  > .button-primary {
  flex: 1 0 100%;
}

/* The recognised text is the result: it gets room to be read. */
body:not(:has(.admin-container)) .result-drawer .ocr-text-preview {
  max-height: 46vh;
  overflow: auto;
  padding: 12px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  background: var(--item-bg);
  font-size: 13px;
  line-height: 1.6;
}
