/* FormsPal PDF Editor landing page. Token values copied from the shared
   FormsPal design system (ai.formspal.com, 2026-07-11). The footer rules at
   the bottom of this file are verbatim from ai.formspal.com/page.css. */

@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("assets/fraunces-latin.woff2") format("woff2");
}

:root {
  --primary: #0e8a5f;
  --primary-dark: #0b6e4c;
  --btn: #0b6e4c;
  --primary-light: #e6f4ee;
  --ink: #1c2530;
  --ink-soft: #51606f;
  --faint: #6b7785;
  --line: #cdd5de;
  --bg: #f7f9fb;
  --card: #ffffff;
  --footbg: #11181c;
  --footink: #c4ccd4;
  --footline: #243038;
  --radius: 12px;
  --white: #ffffff;
  --headbg: rgba(247, 249, 251, 0.88);
  --dc-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* CTA orange: formspal.com's accent. The hero button keeps the bright
     brand orange (AA as 19px-bold large text); the family header pill is
     14.5px, so --dc-btn uses the darker pair to clear 4.5:1 with white.
     Upstream note: sync this token change back to the shared header source. */
  --cta: #ea580c;
  --cta-hover: #c2410c;
  --dc-btn: #c2410c;
  --dc-btn-hover: #9a3412;
  /* Layered elevation: tight contact + mid falloff + wide ambient, so cards
     read as lit objects instead of wearing a uniform halo. */
  --shadow: 0 1px 2px rgba(16, 38, 30, 0.05), 0 4px 10px rgba(16, 38, 30, 0.05), 0 12px 28px rgba(16, 38, 30, 0.06);
  /* Top-edge highlight for dark-theme elevation; fully transparent in light. */
  --edge-hi: inset 0 1px 0 rgba(255, 255, 255, 0);
  /* Two-step vertical rhythm: one section boundary, one title-to-content gap. */
  --sp-section: 88px;
  --sp-title: 36px;
  /* One motion voice: ease-out, settle fast. */
  --ease: cubic-bezier(0.2, 0, 0, 1);
}
html[data-theme="dark"] {
  --primary: #16a571;
  --primary-dark: #34c188;
  --btn: #0c7a54;
  --primary-light: #143323;
  --ink: #f2f5f7;
  --ink-soft: #aab5bf;
  --faint: #8e99a4;
  --line: #2a3036;
  --bg: #15181b;
  /* Dark elevation = a lighter surface + a top-edge highlight, not shadow
     (black-on-black smearing was all the old 20px blur bought us). */
  --card: #21262d;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  --edge-hi: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  --footbg: #0c1114;
  --footink: #aab5bf;
  --footline: #1c252b;
  --white: #1e2329;
  --headbg: rgba(21, 24, 27, 0.88);
}

:root { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

* { box-sizing: border-box; }

/* Keyboard escape hatch past the sticky mega menu (~100 tab stops). */
.skip-link {
  position: absolute; left: -9999px; z-index: 100;
  background: var(--cta); color: #fff; font-weight: 700;
  padding: 10px 18px; border-radius: 0 0 10px 0; text-decoration: none;
}
.skip-link:focus { left: 0; top: 0; }

/* In-page anchors must clear the sticky header. */
#stores, #faq, #main { scroll-margin-top: 72px; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  color: var(--ink); background: var(--bg); line-height: 1.55;
}
/* Light-on-dark serifs bloom under subpixel AA; grayscale only in dark. */
html[data-theme="dark"] body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
img { max-width: 100%; height: auto; }
a { color: var(--primary-dark); }
.wrap { max-width: 1080px; margin: 0 auto; padding: 0 20px; }
/* Display type: em-based tracking that tightens with size, display leading
   (body's 1.55 is paragraph leading), balanced rag on multi-line headings. */
h1, h2 {
  font-family: "Fraunces", Georgia, serif; font-weight: 600;
  letter-spacing: -0.018em; line-height: 1.15;
  font-optical-sizing: auto; text-wrap: balance;
}
.hero .sub, .tile p, .faq details p, .privacy li { text-wrap: pretty; }

/* Brand-green selection keeps each theme's own text color legible. */
::selection { background: rgba(14, 138, 95, 0.25); }
html[data-theme="dark"] ::selection { background: rgba(52, 193, 136, 0.38); }

/* One focus ring for every page-owned interactive element. */
.badge:focus-visible, .cta-alt a:focus-visible, .privacy a:focus-visible,
.faq details a:focus-visible, .skip-link:focus-visible {
  outline: 3px solid var(--primary); outline-offset: 2px; border-radius: 4px;
}
.badge:focus-visible { border-radius: 12px; }

/* ---------- hero ---------- */
.hero { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 56px; align-items: center; padding: 48px 0 var(--sp-section); }
.eyebrow { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.4px; color: var(--primary-dark); margin: 0 0 10px; }
.hero h1 { font-size: 52px; line-height: 1.08; letter-spacing: -0.024em; font-weight: 640; margin: 0 0 18px; }
.hero .sub { font-size: 19px; color: var(--ink-soft); margin: 0 0 28px; max-width: 34em; }
.cta-btn {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--cta); color: #fff; text-decoration: none;
  border-radius: 11px; padding: 14px 30px; font-size: 19px; font-weight: 700;
  box-shadow: 0 1px 3px rgba(154, 52, 18, 0.25);
  transition: background-color 180ms var(--ease), box-shadow 180ms var(--ease), transform 120ms var(--ease);
}
/* 19px bold = WCAG "large text", so white on the brand orange (3.55:1) meets
   AA; at 17px it silently failed the 4.5:1 normal-text bar. */
.cta-btn:hover { background: var(--cta-hover); box-shadow: 0 5px 14px rgba(154, 52, 18, 0.3); }
.cta-btn:active { transform: scale(0.98); box-shadow: 0 1px 3px rgba(154, 52, 18, 0.25); transition-duration: 80ms; }
.cta-btn:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
/* Clean white browser mark (currentColor = the button's white text). */
.cta-ico { width: 19px; height: 19px; flex: none; color: #fff; }
/* --ink-soft, not --faint: 14px text on the page background needs 4.5:1. */
.cta-alt { margin: 12px 0 0; font-size: 14px; color: var(--ink-soft); }
.cta-alt a { color: inherit; }
.hero-art { position: relative; text-align: center; }
/* Aurora rim light: a soft OKLCH color wheel (green, cyan, violet, amber)
   turns behind the shot like studio rim lighting. It is a blurred CIRCLE
   rotated via transform, so its silhouette never changes: the 40px blur
   rasterizes once and the rotation stays GPU-composited. Brightens with
   hover; holds a static gradient under reduced motion. */
.hero-art::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 120%; aspect-ratio: 1;
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  background: conic-gradient(in oklch,
    oklch(72% 0.16 160), oklch(74% 0.12 210), oklch(68% 0.17 300),
    oklch(80% 0.13 90), oklch(72% 0.16 160));
  filter: blur(40px) saturate(1.2); opacity: 0.26;
  transition: opacity 350ms var(--ease);
}
html[data-theme="dark"] .hero-art::before { opacity: 0.45; }
.hero-art:hover::before { opacity: 0.4; }
html[data-theme="dark"] .hero-art:hover::before { opacity: 0.62; }
@media (prefers-reduced-motion: no-preference) {
  .hero-art::before { animation: fp-aurora 26s linear infinite; }
}
@keyframes fp-aurora { to { transform: translate(-50%, -50%) rotate(360deg); } }
.hero-art picture, .hero-art img { position: relative; }
/* The shot floats in front of the aurora. The <picture> is the visible card:
   it clips an 8px white capture strip baked into the bottom of both popup
   assets (img pulls up by 8/720 of the width) and carries the ring + lift
   shadows, since overflow:hidden on it would clip any shadow set on the img. */
.hero-art img { width: 100%; display: block; margin-bottom: -1.12%; }
.hero-art picture {
  overflow: hidden; border-radius: 16px;
  box-shadow: 0 0 0 1px rgba(16, 38, 30, 0.08), 0 24px 64px rgba(16, 38, 30, 0.24), 0 4px 16px rgba(16, 38, 30, 0.12);
}
html[data-theme="dark"] .hero-art picture {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.14), 0 28px 70px rgba(0, 0, 0, 0.6), 0 2px 8px rgba(0, 0, 0, 0.5);
}
.art-dark { display: none; }
html[data-theme="dark"] .art-dark { display: block; }
html[data-theme="dark"] .art-light { display: none; }

/* ---------- feature tiles ---------- */
.section-title { font-size: 32px; text-align: center; margin: 0 0 var(--sp-title); }
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; padding-bottom: var(--sp-section); }
.tile {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow), var(--edge-hi); padding: 22px; display: flex; flex-direction: column; gap: 10px;
  transition: box-shadow 200ms var(--ease), border-color 200ms var(--ease), transform 200ms var(--ease);
}
.tile:hover { border-color: rgba(14, 138, 95, 0.35); box-shadow: 0 10px 28px rgba(16, 38, 30, 0.12), var(--edge-hi); }
html[data-theme="dark"] .tile:hover { border-color: rgba(22, 165, 113, 0.4); box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55), var(--edge-hi); }
/* Shadows carry the light-theme lift; soften the doubled hard border (scoped:
   the --line token itself feeds the shared header and must not change). */
.tile, .faq details { border-color: rgba(28, 37, 48, 0.10); }
html[data-theme="dark"] .tile, html[data-theme="dark"] .faq details { border-color: var(--line); }
.tile .t-ico { color: var(--primary); }
.tile .t-ico svg { width: 26px; height: 26px; display: block; }
.tile h3 { margin: 0; font-size: 17.5px; text-wrap: balance; }
.tile p { margin: 0 0 4px; font-size: 14.5px; color: var(--ink-soft); }
/* The <picture> wrapper is the flex child, so it carries the bottom-alignment
   (margin-top:auto on the inner img never worked through the wrapper). */
.tile picture { display: block; margin-top: auto; }
.tile-shot { border-radius: 10px; border: 1px solid var(--line); display: block; width: 100%; box-shadow: 0 1px 3px rgba(16, 38, 30, 0.07); }
html[data-theme="dark"] .tile-shot { border-color: rgba(255, 255, 255, 0.08); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); }
/* Theme-paired imagery: each shot ships in both themes and swaps with the page.
   Hiding the <picture> too (where :has exists) removes the phantom inline gap
   an empty wrapper leaves behind; the img rules stay as the fallback. */
html[data-theme="light"] .only-dark { display: none; }
html[data-theme="dark"] .only-light { display: none; }
html[data-theme="light"] picture:has(.only-dark), html[data-theme="light"] picture:has(.art-dark) { display: none; }
html[data-theme="dark"] picture:has(.only-light), html[data-theme="dark"] picture:has(.art-light) { display: none; }

/* ---------- store badges ---------- */
.stores { text-align: center; padding-bottom: var(--sp-section); }
.badges { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }
/* Official download-badge convention: solid dark pill, full-color store logo,
   white two-line text. Dark in both page themes so the Chrome and Firefox
   logos (which have white centers) always read, and all three stay uniform. */
.badge {
  display: inline-flex; align-items: center; gap: 11px; text-decoration: none;
  background: #16191d; color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.16); border-radius: 12px; padding: 10px 18px;
  font-size: 15px; font-weight: 600;
  transition: transform 180ms var(--ease), border-color 180ms var(--ease);
}
.badge:hover { border-color: rgba(255, 255, 255, 0.42); }
.badge:active { transform: translateY(0) scale(0.98); transition-duration: 80ms; }
@media (prefers-reduced-motion: no-preference) {
  .badge:hover { transform: translateY(-1px); }
}
/* On the dark page the pill needs one elevation step or it melts into --bg. */
html[data-theme="dark"] .badge { background: #1f252b; border-color: rgba(255, 255, 255, 0.15); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.04); }
.badge small { display: block; font-size: 10.5px; font-weight: 500; color: rgba(255, 255, 255, 0.6); text-align: left; letter-spacing: 0.01em; }
.badge .b-ico { width: 28px; height: 28px; flex: none; }
/* Chrome and Firefox carry their own brand colors; the Apple mark is white. */
.badge .b-ico-apple { color: #fff; }
.badge span { text-align: left; line-height: 1.16; }
.stores .badge-note { margin: 16px 0 0; font-size: 14px; color: var(--ink-soft); }

/* ---------- privacy panel ---------- */
.privacy {
  text-align: center;
  background: linear-gradient(180deg, #eaf6f0 0%, #e1f0e9 100%);
  border: 1px solid rgba(14, 138, 95, 0.24);
  border-radius: 20px; padding: 48px 48px 40px;
  max-width: 920px; margin: 0 auto var(--sp-section);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.65), 0 1px 2px rgba(16, 38, 30, 0.04);
}
html[data-theme="dark"] .privacy {
  background: linear-gradient(180deg, #17382a 0%, #102a1f 100%);
  border-color: rgba(52, 193, 136, 0.26);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.privacy-shield {
  display: inline-flex; width: 54px; height: 54px; border-radius: 16px;
  background: var(--primary); color: #fff; align-items: center; justify-content: center;
  margin-bottom: 16px;
}
.privacy-shield svg { width: 28px; height: 28px; }
.privacy h2 { font-size: 32px; margin: 0 0 24px; }
.privacy h2 em { font-style: normal; color: var(--primary-dark); font-weight: 700; }
.privacy ul {
  margin: 0 auto 20px; padding: 0; list-style: none; max-width: 680px;
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px 40px; text-align: left;
}
.privacy li { display: flex; align-items: flex-start; gap: 12px; font-size: 15px; color: var(--ink); line-height: 1.45; }
.privacy li::before {
  content: "\2713"; flex: none; width: 22px; height: 22px; margin-top: 1px; border-radius: 50%;
  background: var(--primary); color: #fff; font-size: 12px; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center;
}
.privacy > p { margin: 0; font-size: 14px; color: var(--ink-soft); }
.privacy > p a { color: var(--primary-dark); font-weight: 600; }

/* ---------- FAQ ---------- */
.faq { padding-bottom: var(--sp-section); max-width: 760px; margin: 0 auto; }
.faq h2 { text-align: center; font-size: 32px; margin: 0 0 var(--sp-title); }
.faq details {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 20px; margin-bottom: 12px; box-shadow: var(--edge-hi);
}
/* Custom disclosure: the UA triangle reads unrefined; a right-aligned chevron
   rotates on open, and the answer fades up (motion-gated). */
.faq summary {
  font-weight: 700; font-size: 15.5px; cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; width: 8px; height: 8px; margin-right: 2px;
  border-right: 2px solid var(--faint); border-bottom: 2px solid var(--faint);
  transform: rotate(45deg) translateY(-1px);
  transition: transform 200ms var(--ease);
}
.faq details[open] summary::after { transform: rotate(225deg) translateY(-1px); }
@media (prefers-reduced-motion: no-preference) {
  .faq details[open] > p { animation: fp-faq-open 200ms var(--ease); }
}
@keyframes fp-faq-open {
  from { opacity: 0; transform: translateY(-4px); }
}
.faq summary:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
.faq details p { margin: 10px 0 4px; font-size: 14.5px; color: var(--ink-soft); max-width: 62ch; }

/* ---------- closing CTA ---------- */
.closer { text-align: center; padding-bottom: 72px; }
.closer .section-title { margin-bottom: 22px; }

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  :root { --sp-section: 56px; --sp-title: 28px; }
  .hero { grid-template-columns: 1fr; gap: 32px; padding: 32px 0 var(--sp-section); text-align: center; }
  .hero .sub { margin-left: auto; margin-right: auto; }
  .hero h1 { font-size: 38px; }
  .tiles { grid-template-columns: 1fr 1fr; }
  .privacy ul { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .tiles { grid-template-columns: 1fr; }
  .hero-art picture { width: min(300px, 100%); }
  .cta-btn { width: 100%; justify-content: center; }
  .badges { flex-direction: column; align-items: center; gap: 10px; }
  .badge { width: 100%; max-width: 300px; }
  .privacy { padding: 32px 22px 28px; border-radius: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  html { scroll-behavior: auto !important; }
}

/* ==== FormsPal site footer, copied verbatim from ai.formspal.com/page.css on 2026-07-11. Re-sync by re-running Task 0 of the landing-page plan. ==== */

/* ---------- footer ---------- */



















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

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

/* ==== FormsPal family header (mega menu), copied from
   statute-of-limitations.formspal.com landing.css on 2026-07-12;
   dark selectors rewritten to html[data-theme]. ==== */
@media(max-width:560px){.site-head-inner{gap:10px;padding:11px 14px}.site-brand b,.site-signin{display:none}.site-cta{padding:8px 13px}}
.site-signin{text-decoration:none;color:var(--ink-soft);font-weight:600;font-size:14.5px;padding:8px 10px}
.site-signin:hover{color:var(--primary-dark)}
/* Push the action cluster (toggle, sign in, CTA) to the right edge at every
   width, including when the nav collapses to the burger. */
.site-theme-toggle{margin-left:auto;width:38px;height:38px;border-radius:50%;flex:none;padding:0;cursor:pointer;background:var(--white);border:1.5px solid var(--line);display:inline-flex;align-items:center;justify-content:center}
.site-theme-toggle:hover{border-color:var(--primary)}
.site-theme-toggle svg{width:17px;height:17px}
.site-theme-toggle .sun{display:none;stroke:#e8a32b}
.site-theme-toggle .moon{display:block;stroke:var(--primary)}
html[data-theme="dark"] .site-theme-toggle .sun{display:block}
html[data-theme="dark"] .site-theme-toggle .moon{display:none}

/* ==== Ambient depth + motion, ported from trust.formspal.com (2026-07-13).
   Everything below reads the existing tokens, works in both themes, and is
   inert under prefers-reduced-motion. The reveal class is only ever attached
   by page.js when motion is allowed, so content never hides without it. ==== */

/* Decorative layers (hero wash, package shadows) may extend past the viewport
   edge; clip there so they can never summon a horizontal scrollbar. clip (not
   hidden) adds no scroll container; older engines ignore it harmlessly. */
body { overflow-x: clip; }

/* Aurora mesh: three fixed brand-tinted radials give the page quiet depth.
   The grain layer (local asset: CSP img-src is 'self', no data: URIs) kills
   gradient banding and adds a matte tooth. Both sit behind all content. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(58% 48% at 12% -4%, rgba(14, 138, 95, 0.09), transparent 70%),
    radial-gradient(52% 44% at 104% 6%, rgba(234, 88, 12, 0.06), transparent 68%),
    radial-gradient(80% 62% at 50% 108%, rgba(14, 138, 95, 0.05), transparent 72%);
}
html[data-theme="dark"] body::before {
  background:
    radial-gradient(58% 48% at 12% -4%, rgba(22, 165, 113, 0.16), transparent 70%),
    radial-gradient(52% 44% at 104% 6%, rgba(234, 88, 12, 0.10), transparent 68%),
    radial-gradient(80% 62% at 50% 108%, rgba(22, 165, 113, 0.08), transparent 72%);
}
body::after {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: 0.025; mix-blend-mode: multiply;
  background: url("assets/grain.svg"); background-size: 140px 140px;
}
html[data-theme="dark"] body::after { opacity: 0.04; mix-blend-mode: overlay; }

/* Reading-progress hairline above the sticky header (header is z-index 30). */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
  transform: scaleX(0); transform-origin: 0 50%; pointer-events: none;
  background: linear-gradient(90deg, var(--primary-dark), var(--primary));
  box-shadow: 0 0 10px rgba(14, 138, 95, 0.5);
}
html[data-theme="dark"] .scroll-progress { box-shadow: 0 0 10px rgba(22, 165, 113, 0.5); }

/* Once the page scrolls, the glass header earns a soft drop shadow. */
.site-head { transition: box-shadow 250ms var(--ease); }
.site-head.scrolled { box-shadow: 0 6px 22px -12px rgba(16, 38, 30, 0.35); }
html[data-theme="dark"] .site-head.scrolled { box-shadow: 0 6px 22px -12px rgba(0, 0, 0, 0.6); }

/* Hero glows: painted as radial gradients on a full-bleed pseudo-element, not
   as blurred divs. Gradient falloff is smooth by construction, so there is no
   blur filter to clip into visible seams and no overflow/scrollbar concern;
   they simply breathe in on load. The copy/art columns sit above. */
.hero { position: relative; }
.hero-copy { position: relative; }
main { position: relative; }
main::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 760px; pointer-events: none;
  background:
    radial-gradient(56% 84% at 10% -12%, rgba(14, 138, 95, 0.12), transparent 66%),
    radial-gradient(48% 72% at 94% -8%, rgba(234, 88, 12, 0.06), transparent 62%);
}
html[data-theme="dark"] main::before {
  background:
    radial-gradient(56% 84% at 10% -12%, rgba(22, 165, 113, 0.17), transparent 66%),
    radial-gradient(48% 72% at 94% -8%, rgba(234, 88, 12, 0.10), transparent 62%);
}
@media (prefers-reduced-motion: no-preference) {
  main::before { animation: fp-glow-in 1.8s var(--ease) both; }
}
@keyframes fp-glow-in { from { opacity: 0; } }

/* Gradient sheen on the hero's key phrase (52px display text clears large-text
   contrast with the darker token in the mix). Static under reduced motion. */
.grad {
  background: linear-gradient(92deg, var(--primary-dark), var(--primary), var(--primary-dark));
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
@media (prefers-reduced-motion: no-preference) {
  .grad { animation: fp-sheen 9s ease-in-out infinite; }
}
@keyframes fp-sheen { 0%, 100% { background-position: 0% 0; } 50% { background-position: 100% 0; } }

/* Hand-drawn underline, drawn on like a signature. The resting state is the
   finished stroke, so reduced-motion (and no-JS) visitors see it complete.
   Below 860px the hero centers, and the squiggle follows it. */
.sig { display: block; width: min(250px, 62%); margin: 0 0 16px; color: var(--primary); }
@media (max-width: 860px) { .sig { margin-left: auto; margin-right: auto; } }
html[data-theme="dark"] .sig { color: var(--primary-dark); }
@media (prefers-reduced-motion: no-preference) {
  .sig path { stroke-dasharray: 100; stroke-dashoffset: 100; animation: fp-sig-draw 1.5s 350ms var(--ease) forwards; }
}
@keyframes fp-sig-draw { to { stroke-dashoffset: 0; } }

/* Eyebrow picks up the trust-center gradient dash. */
.eyebrow { display: inline-flex; align-items: center; gap: 10px; }
.eyebrow::before {
  content: ""; width: 26px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--primary), transparent);
}

/* CTA shine: a skewed specular sweep crosses the button on hover. */
.cta-btn { position: relative; overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .cta-btn::after {
    content: ""; position: absolute; top: 0; left: -75%; width: 45%; height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.3), transparent);
    transform: skewX(-18deg); transition: left 600ms var(--ease); pointer-events: none;
  }
  .cta-btn:hover::after { left: 130%; }
}

/* Header action cluster: the copied family header expects its children flat
   inside .site-head-inner, but this page wraps them in .site-right, which was
   an unstyled block, so the toggle, Sign In, and CTA sat misaligned on a text
   baseline. Make the wrapper the flex row the originals assumed. */
.site-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.site-right .site-theme-toggle { margin-left: 0; }

/* Header CTA: the same life as the hero button, scaled down. Lift + orange
   glow + shine sweep on hover, press feedback, and a visible focus ring.
   (Kept out of the verbatim family-header block so re-syncs stay clean.) */
.site-cta {
  position: relative; overflow: hidden;
  box-shadow: 0 1px 2px rgba(154, 52, 18, 0.25);
  transition: background-color 180ms var(--ease), box-shadow 180ms var(--ease), transform 120ms var(--ease);
}
.site-cta:hover { box-shadow: 0 4px 12px rgba(154, 52, 18, 0.35); }
.site-cta:active { transform: scale(0.97); transition-duration: 80ms; }
.site-cta:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .site-cta:hover { transform: translateY(-1px); }
  .site-cta::after {
    content: ""; position: absolute; top: 0; left: -75%; width: 45%; height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.28), transparent);
    transform: skewX(-18deg); transition: left 500ms var(--ease); pointer-events: none;
  }
  .site-cta:hover::after { left: 130%; }
  .site-cta:active { transform: translateY(0) scale(0.97); }
}

/* Section hairlines fade at the edges instead of a hard full-width rule. */
.ruled { position: relative; padding-top: 44px; }
.ruled::before {
  content: ""; position: absolute; top: 0; left: 20px; right: 20px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--line) 16%, var(--line) 84%, transparent);
}

/* Pointer spotlight: cards get a soft brand highlight that tracks the cursor
   (--mx/--my set from page.js; the -30% resting spot keeps a faint top glow). */
.tile {
  background:
    radial-gradient(260px 220px at var(--mx, 50%) var(--my, -30%), rgba(14, 138, 95, 0.07), transparent 60%),
    var(--card);
}
html[data-theme="dark"] .tile {
  background:
    radial-gradient(260px 220px at var(--mx, 50%) var(--my, -30%), rgba(22, 165, 113, 0.10), transparent 60%),
    var(--card);
}
.faq details {
  background:
    radial-gradient(300px 170px at var(--mx, 50%) var(--my, -30%), rgba(14, 138, 95, 0.05), transparent 60%),
    var(--card);
}
html[data-theme="dark"] .faq details {
  background:
    radial-gradient(300px 170px at var(--mx, 50%) var(--my, -30%), rgba(22, 165, 113, 0.08), transparent 60%),
    var(--card);
}

/* Hero shot in the aurora: the <picture> is only the tilt carrier (vars set
   by page.js on capable pointers), the img carries the object shadows, and
   the whole assembly levitates. On hover the shadow deepens and the aurora
   behind (see .hero-art::before above) brightens. */
.hero-art { perspective: 1100px; }
.hero-art picture {
  display: block; position: relative; width: min(360px, 100%); margin: 0 auto;
  will-change: transform;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 250ms var(--ease), box-shadow 350ms var(--ease);
}
@media (prefers-reduced-motion: no-preference) {
  .hero-art { animation: fp-float 7s ease-in-out infinite alternate; }
}
@keyframes fp-float { from { transform: translateY(4px); } to { transform: translateY(-8px); } }
.hero-art:hover picture {
  box-shadow:
    0 0 0 1px rgba(16, 38, 30, 0.08),
    0 32px 80px rgba(16, 38, 30, 0.28), 0 8px 24px rgba(16, 38, 30, 0.14),
    0 24px 72px rgba(14, 138, 95, 0.18);
}
html[data-theme="dark"] .hero-art:hover picture {
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.16),
    0 32px 80px rgba(0, 0, 0, 0.68), 0 6px 18px rgba(0, 0, 0, 0.5),
    0 24px 72px rgba(22, 165, 113, 0.22);
}

/* Tile mini-demos: the three shotless tiles carry "data" built from the
   popup's own visual language (chip colors match popup.html's --c-* tokens,
   the dropzone echoes its dashed drop area, the pills echo the privacy
   checklist). Each sits at the tile foot like the screenshot tiles. */
.convert-demo {
  margin-top: auto; padding: 16px 0 6px;
  display: flex; align-items: center; justify-content: center; gap: 12px;
}
.fmt {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; color: #fff;
  padding: 4px 9px; border-radius: 6px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}
.fmt-pdf { background: #c1574f; }
.fmt-doc { background: #5d88bd; }
.fmt-xls { background: #72a957; }
.fmt-ppt { background: #cb7f3f; }
.fmt-png { background: #dab04a; }
.fmt-jpg { background: #ce973c; }
.fmt-fan { display: flex; flex-wrap: wrap; gap: 6px; max-width: 148px; }
.convert-arrows { width: 24px; height: 24px; flex: none; color: var(--primary); transition: transform 250ms var(--ease); }
@media (prefers-reduced-motion: no-preference) {
  .tile:hover .convert-arrows { transform: scaleX(1.25); }
}

.drop-demo {
  margin-top: auto; padding: 13px 12px;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  border: 1.5px dashed rgba(14, 138, 95, 0.45); border-radius: 10px;
  color: var(--ink-soft); font-size: 13px; font-weight: 600;
  background: rgba(14, 138, 95, 0.04);
}
html[data-theme="dark"] .drop-demo { border-color: rgba(52, 193, 136, 0.4); background: rgba(22, 165, 113, 0.07); }
.drop-demo svg { width: 18px; height: 18px; flex: none; color: var(--primary); }

.priv-demo { margin-top: auto; padding-top: 14px; display: flex; flex-wrap: wrap; gap: 8px; }
.priv-pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 600; color: var(--ink);
  padding: 5px 12px 5px 8px; border-radius: 999px;
  border: 1px solid rgba(14, 138, 95, 0.3); background: rgba(14, 138, 95, 0.07);
}
html[data-theme="dark"] .priv-pill { border-color: rgba(52, 193, 136, 0.32); background: rgba(22, 165, 113, 0.1); }
.priv-pill::before {
  content: "\2713"; flex: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--primary); color: #fff; font-size: 10px; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center;
}

/* Scroll reveal: page.js attaches .reveal only when motion is allowed, then
   .in fades each element up. Tiles and badges stagger by grid position. */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity 650ms var(--ease), transform 650ms var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.tile.reveal:nth-child(3n - 1), .badge.reveal:nth-child(2) { transition-delay: 90ms; }
.tile.reveal:nth-child(3n), .badge.reveal:nth-child(3) { transition-delay: 180ms; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* Shared-frame token map (property-owned): the vendored frame reads --fp-*
   and follows the page theme (data-theme + fpTheme, fleet standard). CTA
   uses the darker orange pair so 14.5px white text clears 4.5:1. */
:root {
  --fp-header-h: 64px;
  --fp-bg: var(--bg);
  --fp-ink: var(--ink);
  --fp-green: var(--primary);
  --fp-green-soft: var(--primary-dark);
  --fp-orange: var(--dc-btn);
  --fp-orange-hover: var(--dc-btn-hover);
  --fp-orange-ink: #ffffff;
}

/* fp-shared-frame:start (vendored css; update via scripts/sync-shared-frame.sh) */
/* FormsPal shared header. Scope everything under .site-head (plus :root/html
   for variables and the no-JS fallback). Fleet look: dark-first, green
   primary, orange CTA. Properties override the --fp-* variables. */

/* The sticky bar would otherwise cover whatever a keyboard Tab or an anchor
   jump scrolls to the top of the viewport (WCAG 2.2 SC 2.4.11). */
html {
  scroll-padding-top: calc(var(--fp-header-h, 64px) + 8px);
}

:root {
  --fp-header-h: 64px;
  --fp-ease: cubic-bezier(0.2, 0, 0, 1);
  --fp-dur: 150ms;
}

.site-head {
  position: sticky;
  top: 0;
  z-index: 50;
  /* min-height, not height: if the measured collapse ever fails to fire, a
     wrapped nav grows the bar instead of overlapping the page beneath it.
     Content never exceeds 44px plus padding in the normal case, so the
     rendered height stays 64px and CLS is unchanged. */
  min-height: var(--fp-header-h);
  background: var(--fp-bg, #0b1f17);
  color: var(--fp-ink, #eaf5ef);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  --fp-head-soft: color-mix(in oklab, var(--fp-ink, #eaf5ef) 82%, var(--fp-bg, #0b1f17));
  --fp-head-muted: color-mix(in oklab, var(--fp-ink, #eaf5ef) 70%, var(--fp-bg, #0b1f17));
}
html[data-theme="light"] .site-head {
  background: var(--fp-bg, #f4faf7);
  color: var(--fp-ink, #10231a);
  border-bottom-color: rgba(0, 0, 0, 0.08);
  --fp-head-soft: color-mix(in oklab, var(--fp-ink, #10231a) 82%, var(--fp-bg, #f4faf7));
  --fp-head-muted: color-mix(in oklab, var(--fp-ink, #10231a) 70%, var(--fp-bg, #f4faf7));
}

/* The frame owns the box model of its own padded controls. Every control
   that combines padding with a 44px floor would otherwise render at
   44 + padding wherever the host page ships no reset: measured on a page
   with none, .site-cta, .site-nav a and .site-drop-list a all came out at
   60px instead of 44. Five properties ship a global reset, but
   formspal-legal-tools scopes its own to `.lp *` and `.dc-app *` and the
   frame sits at body level outside both, so the same markup rendered two
   different bars across the fleet. It is also latent breakage: the
   collapsed panel is positioned at top: var(--fp-header-h), so a property
   that lowered that token would grow the bar past it while the panel
   stayed put. <button> already gets border-box from the UA sheet; the
   anchors do not, and the frame should not depend on either.

   .site-nav-wrap is in this list for the same reason at a different scale.
   It is not a 44px control, but it is the one box here where padding meets
   a viewport-relative bound: collapsed, it carries
   max-height: calc(100vh - var(--fp-header-h)) together with
   padding: 8px 16px 16px. Under content-box those add rather than nest, so
   the panel's border box is the max-height plus 24px of padding plus its
   1px border. Measured at 700x600 the collapsed panel's bottom landed at
   625 against a 600px viewport, 25px past the fold, and the overshoot is
   the part holding the last row of links. Border-box makes the bound mean
   what it says. This one predates the 44px floors and is identical in
   v0.7.1, but the rule above claims the frame owns the box model of its own
   padded boxes, and this is the box where the claim pays. */
.site-head .site-cta,
.site-head .site-nav a,
.site-head .site-drop-btn,
.site-head .site-menu-btn,
.site-head .site-drop-list a,
.site-head .site-drop-list span[aria-current],
.site-head .site-nav-wrap,
/* The frame's own layout containers must not inherit the host page's box model.
   A property whose reset is scoped (e.g. `.lp * { box-sizing: border-box }`)
   leaves these in content-box, where max-width applies to the CONTENT box and
   the 16px padding is added on top: the bar then renders 32px wider than the
   footer's matching 1120px container and the two land on different edges. */
.site-head-inner {
  box-sizing: border-box;
}

.site-head-inner {
  max-width: 1120px;
  min-height: var(--fp-header-h);
  margin: 0 auto;
  padding: 0 16px;
  display: flex;
  align-items: center;
  gap: 20px;
}

.site-head .site-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  /* 44px floor: Apple HIG's default control size, and WCAG 2.5.5 AAA. The
     64px bar absorbs a 44px control with no change to its own height.
     min-width is deliberately NOT set here: on a flex item it would replace
     the automatic minimum size (min-width: auto, i.e. min-content) and let
     the brand be squeezed below its own nowrap content. Measured at 480px
     with the app name "Statute of Limitations", a 44px floor gave an 85px
     box around 202.6px of content: the trailing text ran out over the
     hamburger and, with justify-content: center, the logo mark clipped off
     the left edge. The floor is needed only below 430px, where the wordmark
     and app name are both hidden and the 28px mark alone would be the whole
     target, so it lives in that breakpoint with the centering it needs. */
  min-height: 44px;
  color: inherit;
  text-decoration: none;
  font-size: 17px;
  white-space: nowrap;
}
.site-head .site-brand svg { width: 28px; height: 28px; flex: none; }
.site-head .site-brand .app {
  color: var(--fp-head-soft);
  font-weight: 500;
}

.site-head .site-nav-wrap {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  flex: 1;
}

.site-head .site-dropdown { position: relative; }

.site-head .site-drop-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: 4px;
  font: inherit;
  font-size: 14px;
  color: inherit;
  background: none;
  border: 0;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
}
.site-head .site-drop-btn:hover,
.site-head .site-drop-btn[aria-expanded="true"] {
  background: rgba(255, 255, 255, 0.08);
}
html[data-theme="light"] .site-head .site-drop-btn:hover,
html[data-theme="light"] .site-head .site-drop-btn[aria-expanded="true"] {
  background: rgba(0, 0, 0, 0.06);
}
.site-head .site-drop-btn .caret { width: 14px; height: 14px; }

.site-head .site-drop-list {
  list-style: none;
  margin: 0;
  padding: 6px;
}
.site-head .site-drop-list a,
.site-head .site-drop-list span[aria-current] {
  display: block;
  padding: 8px 12px;
  border-radius: 8px;
  color: inherit;
  text-decoration: none;
  font-size: 14px;
  white-space: nowrap;
}
.site-head .site-drop-list a:hover {
  background: var(--fp-green, #0e8a5f);
  color: #fff;
}
.site-head .site-drop-list span[aria-current] { color: var(--fp-head-muted); }

/* JS-enabled: dropdowns collapse into popovers. Without the fp-js class
   (JS disabled or failed) the lists stay in normal flow, fully visible. */
html.fp-js .site-head .site-drop-list {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 230px;
  background: var(--fp-bg, #0e2a1f);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}
html[data-theme="light"].fp-js .site-head .site-drop-list {
  background: var(--fp-bg, #ffffff);
  border-color: rgba(0, 0, 0, 0.1);
}
html.fp-js .site-head .site-dropdown.open .site-drop-list { display: block; }

.site-head .site-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  /* Never overflow: hidden here. It converts "does not fit" into "silently
     disappears": measured at 768px the nav wanted 244px, got 79px, and lost
     two links entirely with no scrollbar to hint at it. header.js decides
     fit now. Wrapping is the visible, debuggable fallback. */
  flex-wrap: wrap;
}
.site-head .site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: inherit;
  text-decoration: none;
  font-size: 14px;
  padding: 8px 10px;
  border-radius: 8px;
  white-space: nowrap;
}
.site-head .site-nav a:hover { background: rgba(255, 255, 255, 0.08); }
html[data-theme="light"] .site-head .site-nav a:hover { background: rgba(0, 0, 0, 0.06); }

.site-head .site-right {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
  flex: none;
}

.site-head .site-menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  color: inherit;
  background: none;
  border: 0;
  padding: 8px;
  border-radius: 8px;
  cursor: pointer;
  margin-left: auto;
}
.site-head .site-menu-btn svg { width: 22px; height: 22px; display: block; }

/* No-JS fallback (all widths): without the fp-js class the dropdown lists
   stay in normal flow as plain visible link lists, so the bar can no longer
   hold a fixed height. It grows instead, and the nav wraps to its own full
   width row below the brand, which itself stacks when it runs out of width.
   The hamburger never appears without JS, so nothing here may be gated on
   the collapse class: only header.js sets it. This path is not the rare
   one it sounds like. ocr-web and pdf-extension both load header.js with
   defer, against the documented contract, so it is what paints on every
   page load there until the script runs. */
html:not(.fp-js) .site-head {
  height: auto;
  min-height: var(--fp-header-h);
}
html:not(.fp-js) .site-head .site-head-inner {
  flex-wrap: wrap;
  height: auto;
  padding: 8px 16px;
}
html:not(.fp-js) .site-head .site-nav-wrap {
  flex-basis: 100%;
  /* The panel has to stack here, not under html.fp-nav-collapsed. Only
     header.js ever sets that class, so with no script the wrap stayed a
     single unwrapped row: measured at 375px with fp-js absent, the document
     was 527px wide against a 375px viewport, and the wrap itself 511px
     inside a 343px box. That is the reflow failure (WCAG 1.4.10, measured
     at 320px) the 719px media block used to cover, because it applied
     whether or not fp-js was present.

     Wrapping rather than an unconditional column, and rather than a second
     breakpoint: nothing without JS can measure fit, and the fit point is
     property-owned (nav copy, page-nav slot). Wrap answers it from the
     content at every width. The groups sit side by side while they fit
     (at 1280px the no-JS bar is still the same single row it was) and
     stack when they do not, which is what the removed block did below
     719px. */
  flex-wrap: wrap;
  /* Bounded like the JS panel: without this the stacked groups make a
     header taller than the phone showing it. */
  max-height: calc(100vh - var(--fp-header-h));
  overflow: auto;
}
html:not(.fp-js) .site-head .site-menu-btn {
  display: none;
}

/* Collapsed: one hamburger; dropdown groups and page nav stack in a panel.
   Height stays fixed and the panel overlays below the bar (no CLS).

   Driven by a class rather than a width because the fit point is not a
   constant. It moves with the nav copy, the CTA label, and anything a
   property puts in .site-right, including the plan pill that only appears
   after sign-in. header.js sets this class from a real measurement. */
html.fp-nav-collapsed .site-head .site-menu-btn { display: inline-flex; }
html.fp-nav-collapsed .site-head .site-nav-wrap {
  display: none;
  position: absolute;
  top: var(--fp-header-h);
  left: 0;
  right: 0;
  flex-direction: column;
  align-items: stretch;
  background: var(--fp-bg, #0b1f17);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding: 8px 16px 16px;
  max-height: calc(100vh - var(--fp-header-h));
  overflow: auto;
}
html[data-theme="light"].fp-nav-collapsed .site-head .site-nav-wrap { background: var(--fp-bg, #f4faf7); }
html.fp-nav-collapsed .site-head.menu-open .site-nav-wrap { display: flex; }
html.fp-js.fp-nav-collapsed .site-head .site-drop-list,
html.fp-js.fp-nav-collapsed .site-head .site-dropdown.open .site-drop-list {
  position: static;
  display: block;
  min-width: 0;
  border: 0;
  box-shadow: none;
  background: none;
}
html.fp-nav-collapsed .site-head .site-drop-btn { pointer-events: none; }
html.fp-nav-collapsed .site-head .site-drop-btn .caret { display: none; }
html.fp-nav-collapsed .site-head .site-nav { flex-direction: column; align-items: stretch; }
/* There is deliberately no html:not(.fp-js).fp-nav-collapsed rule here.
   header.js adds fp-js at execute time and fp-nav-collapsed only after
   that, so the combination cannot occur and any rule written for it is
   dead code that reads like the no-JS fallback while doing nothing. The
   no-JS layout lives in one place, the html:not(.fp-js) block above. */

/* The hamburger belongs with the other controls, not adrift mid bar.
   .site-menu-btn and .site-right both carry margin-left: auto, and flexbox
   splits the free space between two auto margins: measured at 768px the
   brand ended at x=171.9, the hamburger sat at x=284.6 and the right
   cluster started at x=441.2, leaving 92.6px of dead space on each side.
   Dropping the right cluster's auto margin while collapsed hands all the
   free space to the hamburger's own, so the bar reads the way it does
   expanded: brand left, controls right. Scoped to the collapsed state
   because .site-right's auto margin is what right-aligns the cluster when
   the nav is a normal flex item.

   The coupling this creates: while collapsed, .site-right is right-aligned
   only because the hamburger's auto margin is still in the row absorbing
   the free space. Take the button out of the markup, or have a property
   force it display: none while collapsed, and nothing pushes: the cluster
   slides left from x=441.2 to x=191.9 and sits mid bar. No property in the
   fleet does either today, and the frame ships the button in header.html,
   so this is a note for whoever changes that, not a live bug. */
html.fp-nav-collapsed .site-head .site-right { margin-left: 0; }

/* Hallmark · component: header right-side controls · genre: modern-minimal
 * theme: FormsPal fleet tokens (--fp-*)
 * states: default · hover · focus-visible · active (loading/error/success N/A for nav)
 * Right-side controls: shared base styles. Properties may override, but the
 * bar ships finished. */

.site-head .site-drop-btn .caret {
  transition: transform var(--fp-dur) var(--fp-ease);
}
.site-head .site-drop-btn[aria-expanded="true"] .caret {
  transform: rotate(180deg);
}

.site-head .site-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: background-color var(--fp-dur) var(--fp-ease);
}
.site-head .site-theme-toggle svg {
  width: 18px;
  height: 18px;
  display: block;
  stroke: currentColor;
}
.site-head .site-theme-toggle .moon { display: none; }
html[data-theme="light"] .site-head .site-theme-toggle .sun { display: none; }
html[data-theme="light"] .site-head .site-theme-toggle .moon { display: block; }
.site-head .site-theme-toggle:hover { background: rgba(255, 255, 255, 0.08); }
html[data-theme="light"] .site-head .site-theme-toggle:hover { background: rgba(0, 0, 0, 0.06); }
.site-head .site-theme-toggle:active { transform: translateY(1px); }

.site-head .site-cta {
  display: inline-flex;
  align-items: center;
  /* The frame owns this button's box, so it owns the containing block for
     anything a property decorates it with. Two properties add a ::after gleam
     that sweeps on hover, sized in percentages. Without position: relative
     those percentages resolved against .site-head, which is sticky and
     therefore the nearest positioned ancestor: the gleam came out 630px wide
     and 64px tall on a 150x44 button, and swept the full width of the bar.
     overflow: hidden then keeps it inside the rounded rect. Harmless for
     properties that add no decoration. */
  position: relative;
  overflow: hidden;
  min-height: 44px;
  padding: 8px 14px;
  border-radius: 10px;
  background: var(--fp-orange, #ef8b2d);
  color: var(--fp-orange-ink, #1c1206);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--fp-dur) var(--fp-ease), transform var(--fp-dur) var(--fp-ease);
}
.site-head .site-cta:hover { background: var(--fp-orange-hover, #f79c47); }
.site-head .site-cta:active { transform: translateY(1px); }

.site-head .site-theme-toggle:focus-visible,
.site-head .site-cta:focus-visible,
.site-head .site-drop-btn:focus-visible,
.site-head .site-menu-btn:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .site-head .site-drop-btn .caret,
  .site-head .site-theme-toggle,
  .site-head .site-cta {
    transition-duration: 0.01ms;
  }
}

/* Design elevation: glass bar, live tier badge, dropdown entrance.
   All motion is transform/opacity only and collapses under reduced motion. */

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  html.fp-js .site-head {
    background: color-mix(in oklab, var(--fp-bg, #0b1f17) 86%, transparent);
    -webkit-backdrop-filter: blur(12px) saturate(1.4);
    backdrop-filter: blur(12px) saturate(1.4);
  }
  html[data-theme="light"].fp-js .site-head {
    background: color-mix(in oklab, var(--fp-bg, #f4faf7) 86%, transparent);
  }
}

.site-head .site-brand svg {
  transition: transform var(--fp-dur) var(--fp-ease);
}
.site-head .site-brand:hover svg {
  transform: rotate(-4deg) scale(1.06);
}

.site-head .tier-badge[hidden] { display: none; }
.site-head .tier-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: inherit;
  white-space: nowrap;
  border: 1px solid color-mix(in oklab, var(--fp-green, #0e8a5f) 45%, transparent);
  background: color-mix(in oklab, var(--fp-green, #0e8a5f) 14%, transparent);
}
.site-head .tier-dot {
  position: relative;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--fp-green-soft, #34d399);
}
.site-head .tier-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: inherit;
  animation: fp-live 2.4s var(--fp-ease) infinite;
}
@keyframes fp-live {
  0% { transform: scale(1); opacity: 0.7; }
  70%, 100% { transform: scale(2.6); opacity: 0; }
}

html.fp-js .site-head .site-dropdown.open .site-drop-list {
  animation: fp-drop 160ms var(--fp-ease);
}
@keyframes fp-drop {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .site-head .tier-dot::after,
  html.fp-js .site-head .site-dropdown.open .site-drop-list {
    animation: none;
  }
  .site-head .site-brand svg {
    transition-duration: 0.01ms;
  }
}

/* Narrow screens: the bar sheds furniture in priority order (logo, hamburger,
   CTA, toggle, plan pill) instead of overflowing. Without this the right
   cluster keeps its full width and forces horizontal page scroll. */
@media (max-width: 560px) {
  .site-head .site-head-inner { gap: 12px; padding: 0 14px; }
  .site-head .site-brand b { display: none; }
  .site-head .site-cta { padding: 8px 12px; font-size: 13.5px; }
  .site-head .site-right { gap: 8px; min-width: 0; }
}
/* The 44px hit regions are 30px wider than what they replaced, and until
   this block paid for them the collapsed bar simply overflowed. Against
   v0.7.1 at a 320px viewport: brand 28 to 44, hamburger 38 to 44, theme
   toggle 36 to 44. The row ran to x=343.5 where v0.7.1 ended it at 313.5,
   and the document read 320/343 (23px of horizontal scroll) where v0.7.1
   read 320/320. That is a WCAG 1.4.10 reflow failure at the reference
   width, and it only appears with the plan pill shown, which is the state
   this release exists for: ocr-web ships the badge hidden and reveals it
   after sign-in, so it was signed-in phone users who got the scrollbar.

   The 30px comes back out of spacing and pill chrome, never out of a hit
   region. Each number continues a ladder the wider blocks already walk:
   inner gap 20/12/8, inner padding 16/14/10, .site-right gap 10/8/6.
   Collapsed, the row is brand + hamburger + cluster, so the inner gap is
   spent twice and only the LEFT inner padding moves the far edge that
   decides scrollWidth. Budget at 320px, pill shown: 10 + 44 + 8 + 44 + 8 +
   (9 + 6 + 44 + 6 + 134.5) = 313.5, back to where v0.7.1 had it, with
   every control still 44px. */
@media (max-width: 430px) {
  .site-head .site-head-inner { gap: 8px; padding: 0 10px; }
  .site-head .site-brand .app { display: none; }
  /* Only here is the brand small enough to need the floor: wordmark and app
     name are both gone and the 28px mark alone would be the target. Above
     this width the nowrap content is already wider than 44px, so declaring
     the floor there only broke the automatic minimum size. */
  .site-head .site-brand { min-width: 44px; justify-content: center; }
  .site-head .site-right { gap: 6px; }
  /* The pill is already only a dot here: .tier-label goes to display: none
     just below, so the border, background and 7px of side padding are a
     ring around a 7px dot and 14px of the row. Shed the ring, keep the
     indicator. The dot and its live pulse both survive, so a signed-in user
     still sees plan status, and the badge keeps its title attribute. The
     pill is last in the priority order at the head of this narrow-screen
     section, and the ring is chrome rather than content, which is why it
     goes before any 44px control is touched. */
  .site-head .tier-badge {
    padding: 0;
    gap: 0;
    border-color: transparent;
    background: none;
  }
  .site-head .tier-label { display: none; }
  .site-head .site-cta { padding: 7px 10px; font-size: 13px; }
}

/* Stacked rows get the floor only where the frame is actually thumbed. Above
   900px the dropdown keeps its denser pointer rhythm: rows are 33px tall
   and 230px+ wide, clearing WCAG 2.5.8 AA on size alone, no exception
   needed. */
@media (max-width: 900px) {
  .site-head .site-drop-list a,
  .site-head .site-drop-list span[aria-current] {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
}

/* FormsPal shared footer. Scope everything under .site-foot (plus html for
   theme variants). Dark-first; properties override the --fp-* variables.
   No JS: the footer is fully static. */

.site-foot {
  background: var(--fp-bg, #0b1f17);
  color: var(--fp-ink, #eaf5ef);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  /* Dimmed text uses mixed colors, never opacity. Opacity dims toward
     whatever is behind: that keeps contrast on a dark backdrop and destroys
     it on a light one, which is how the light theme fell under 4.5:1. */
  --fp-foot-soft: color-mix(in oklab, var(--fp-ink, #eaf5ef) 85%, var(--fp-bg, #0b1f17));
  --fp-foot-label: color-mix(in oklab, var(--fp-ink, #eaf5ef) 78%, var(--fp-bg, #0b1f17));
  --fp-foot-muted: color-mix(in oklab, var(--fp-ink, #eaf5ef) 70%, var(--fp-bg, #0b1f17));
  --fp-foot-link: color-mix(in oklab, var(--fp-green, #0e8a5f) 45%, #fff);
}
html[data-theme="light"] .site-foot {
  /* Fallbacks must flip with the theme too: a property that does not define
     --fp-ink/--fp-bg would otherwise dim light-theme text using the dark
     default ink and land at ~1.5:1. */
  --fp-foot-soft: color-mix(in oklab, var(--fp-ink, #10231a) 85%, var(--fp-bg, #f4faf7));
  --fp-foot-label: color-mix(in oklab, var(--fp-ink, #10231a) 78%, var(--fp-bg, #f4faf7));
  --fp-foot-muted: color-mix(in oklab, var(--fp-ink, #10231a) 70%, var(--fp-bg, #f4faf7));
  --fp-foot-link: color-mix(in oklab, var(--fp-green, #0e8a5f) 72%, #000);
}
html[data-theme="light"] .site-foot {
  background: var(--fp-bg, #f4faf7);
  color: var(--fp-ink, #10231a);
  border-top-color: rgba(0, 0, 0, 0.08);
}

/* Same reasoning as .site-head-inner in header.css: own the box model rather
   than inheriting whatever reset the host page happens to have. */
.site-foot .foot-cols,
.site-foot .foot-bottom-inner,
.site-foot .foot-ghost {
  box-sizing: border-box;
}

.site-foot .foot-cols {
  max-width: 1120px;
  margin: 0 auto;
  padding: 40px 16px 28px;
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr 1fr;
  gap: 28px;
}

.site-foot .foot-brand svg { width: 34px; height: 34px; }
.site-foot .foot-brand b {
  display: inline-block;
  margin-left: 8px;
  font-size: 17px;
  vertical-align: super;
}
.site-foot .foot-brand p {
  font-size: 14px;
  line-height: 1.5;
  color: var(--fp-foot-soft);
  margin: 10px 0;
}
.site-foot .foot-brand a {
  color: var(--fp-foot-link);
  text-decoration: none;
  font-size: 14px;
}
.site-foot .foot-addr {
  font-style: normal;
  font-size: 13px;
  color: var(--fp-foot-label);
  margin-top: 12px;
  line-height: 1.5;
}
.site-foot .foot-addr strong { display: block; }

.site-foot .foot-col .foot-col-title {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fp-foot-label);
  margin: 4px 0 12px;
  font-weight: 600;
}
.site-foot .foot-col ul { list-style: none; margin: 0; padding: 0; }
.site-foot .foot-col li { margin: 0 0 9px; }
.site-foot .foot-col a {
  color: var(--fp-foot-soft);
  text-decoration: none;
  font-size: 14px;
}
.site-foot .foot-col a:hover { color: var(--fp-foot-link); }
.site-foot .foot-col span[aria-current] { font-size: 14px; color: var(--fp-foot-muted); }

.site-foot .foot-bottom { border-top: 1px solid rgba(255, 255, 255, 0.08); }
html[data-theme="light"] .site-foot .foot-bottom { border-top-color: rgba(0, 0, 0, 0.08); }
.site-foot .foot-bottom-inner {
  max-width: 1120px;
  margin: 0 auto;
  padding: 14px 16px 18px;
  font-size: 13px;
  color: var(--fp-foot-soft);
}
.site-foot .foot-disclaimer { margin: 0 0 10px; line-height: 1.55; }
.site-foot .foot-legal { display: block; }
.site-foot .foot-legal a {
  color: inherit;
  text-decoration: none;
  margin-right: 14px;
}
.site-foot .foot-legal a:hover { color: var(--fp-foot-link); }

/* The frame owns focus for its own components: a property that ships no
   global focus style (or resets outlines) must not lose the focus ring. */
.site-foot a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
  border-radius: 4px;
}

@media (max-width: 900px) {
  .site-foot .foot-cols { grid-template-columns: 1fr 1fr; }
  .site-foot .foot-brand { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .site-foot .foot-cols { grid-template-columns: 1fr; }
}

/* Match the header's gutter scale. The bar narrows to 14px then 10px so it can
   shed furniture instead of overflowing, but the footer stayed at a flat 16px,
   so footer content sat 2px then 6px inboard of the brand directly above it.
   Two gutters on one page is visible as a broken alignment line on any phone. */
@media (max-width: 560px) {
  .site-foot .foot-cols,
  .site-foot .foot-bottom-inner,
  .site-foot .foot-ghost { padding-inline: 14px; }
}
@media (max-width: 430px) {
  .site-foot .foot-cols,
  .site-foot .foot-bottom-inner,
  .site-foot .foot-ghost { padding-inline: 10px; }
}

/* Design elevation: signature top rule, heading accent ticks, link
   micro-shift, ghost wordmark half-cropped behind the bottom bar. */

.site-foot {
  border-top: 2px solid var(--fp-green, #0e8a5f);
}
.site-foot .foot-col .foot-col-title::before {
  content: "";
  display: block;
  width: 18px;
  height: 2px;
  margin-bottom: 8px;
  background: var(--fp-green, #0e8a5f);
}
.site-foot .foot-col a {
  display: inline-block;
  transition: color var(--fp-dur, 150ms) var(--fp-ease, ease-out), transform var(--fp-dur, 150ms) var(--fp-ease, ease-out);
}
.site-foot .foot-col a:hover {
  transform: translateX(2px);
}
.site-foot .foot-ghost {
  max-width: 1120px;
  margin: 8px auto -0.4em;
  padding: 0 16px;
  font-weight: 800;
  font-size: clamp(40px, 13vw, 190px);
  white-space: nowrap;
  line-height: 1;
  letter-spacing: -0.045em;
  opacity: 0.05;
  user-select: none;
  pointer-events: none;
  overflow-wrap: anywhere;
}
.site-foot .foot-bottom {
  position: relative;
  background: var(--fp-bg, #0b1f17);
}
html[data-theme="light"] .site-foot .foot-bottom {
  background: var(--fp-bg, #f4faf7);
}
@media (prefers-reduced-motion: reduce) {
  .site-foot .foot-col a { transition-duration: 0.01ms; }
}

/* Footer rows are 14px type on a 9px rhythm: a 16.5px box at 25.5px pitch.
   That clears WCAG 2.5.8 AA on the spacing exception but sits well under the
   44px Apple asks for. Raised only where the footer is thumbed; above 900px
   the columns keep their denser desktop rhythm. */
/* A second @media (max-width: 900px) block on purpose: keep it separate
   from the one above. The "design elevation" section earlier in this file
   sets .site-foot .foot-col a { display: inline-block } at equal
   specificity. Merging these rules up there would put them before that one
   in source order, so inline-block would win the cascade and silently
   shrink the 44px row back down to a text-width link. */
@media (max-width: 900px) {
  .site-foot .foot-col li { margin: 0; }
  .site-foot .foot-col a,
  .site-foot .foot-col span[aria-current] {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
  /* Width needs the floor too: these are short words, and a hit region is
     44x44, not 44 tall. Measured at 880px before this rule: Privacy 44.19,
     Cookies 48.64, Terms 37.21, CCPA 34.76, DMCA 38.32. They are inline-flex
     boxes on a line box, so widening them pushes their neighbours along the
     row instead of changing any layout around it. */
  .site-foot .foot-legal a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    margin-right: 18px;
  }
}
/* fp-shared-frame:end */

/* Hub browse mega-dropdown (property-owned): one shared-frame dropdown at
   every width. Six category groups sit in a 3-across grid with compact rows;
   the panel spans the bar and scrolls past 70vh. All 110 dofollow links stay
   server-rendered. */
.site-head .site-dropdown.site-dropdown-mega { position: static; }
html.fp-js .site-head .site-dropdown-mega .site-drop-list {
  left: 16px;
  right: 16px;
  max-width: 1088px;
  margin: 0 auto;
  max-height: min(74vh, 680px);
  overflow: auto;
  padding: 20px 24px;
  display: none;
}
html.fp-js .site-head .site-dropdown-mega.open .site-drop-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px 28px;
  align-items: start;
}
.site-head .site-mega .mega-group { min-width: 0; }
.site-head .site-mega .mega-cat {
  margin: 0 0 6px;
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fp-green, #0e8a5f);
}
.site-head .site-mega .mega-cols { display: block; }
.site-head .site-mega .mega-cols ul { list-style: none; margin: 0; padding: 0; }
.site-head .site-drop-list.site-mega a {
  padding: 3px 8px;
  font-size: 13.5px;
}
.site-head .site-mega .mega-head {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  opacity: 0.55;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 8px 0 2px;
}
.site-head .site-mega .mega-group > .mega-cols > .mega-head:first-child,
.site-head .site-mega .mega-cols > .mega-col:first-child > .mega-head { margin-top: 0; }
.site-head .site-mega .mega-sub { padding-left: 12px; }
.site-head .site-drop-list.site-mega .mega-sub a { font-size: 12.5px; opacity: 0.8; }
@media (max-width: 900px) {
  html.fp-js .site-head .site-dropdown-mega.open .site-drop-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Collapsed bar: the mega panel stacks inside the hamburger, so the desktop
   overlay geometry (inset, centring, own scroller) has to come off and the
   panel has to be laid out as plain blocks.

   Keyed to the frame's collapsed class, not to a width. This was
   @media (max-width: 719px) back when the frame collapsed on that
   breakpoint. Since frame v0.9.0 it collapses on a live measurement of
   whether the nav fits, which for this property's 110 link browse menu is
   about 855px, so the old media query left 720px to 855px (iPad portrait
   included) governed by the desktop display: none above, with the frame's
   pointer-events: none on .site-drop-btn making the panel unopenable too.

   Specificity: the two selectors here are (0,5,1) and (0,6,1). They beat
   this property's own desktop rules above, (0,4,1) and (0,5,1), on weight
   or, for the (0,5,1) tie, on source order. Against the frame's collapsed
   rules, (0,4,1) and (0,6,1), they win on weight and on source order
   respectively, the vendored block being spliced in above. */
html.fp-js.fp-nav-collapsed .site-head .site-dropdown-mega .site-drop-list,
html.fp-js.fp-nav-collapsed .site-head .site-dropdown-mega.open .site-drop-list {
  left: auto; right: auto; margin: 0; max-height: none; overflow: visible;
  padding: 6px; display: block;
}

