/* TestID Hunter - marketing site custom styles
   Tailwind does most of the work; this file holds brand tokens and small overrides. */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

:root {
  --brand-blue: #2383e2;
  --brand-blue-dark: #0b6bcb;
  --rank-solid: #0f7b0f;
  --rank-usable: #2383e2;
  --rank-weak: #e03e3e;
  --text: #37352f;
  --muted: #787774;
  --subtle: #9b9a97;
  --bg: #ffffff;
  --bg-subtle: #fafaf9;
  --border: #e3e2de;
}

html {
  scroll-behavior: smooth;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
}

body {
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  line-height: 1.6;
}

code, pre {
  font-family: 'SF Mono', 'Fira Code', ui-monospace, Menlo, monospace;
  font-size: 0.9em;
}

pre {
  background: #0d1117;
  color: #e6edf3;
  padding: 18px 20px;
  border-radius: 8px;
  overflow-x: auto;
  line-height: 1.55;
  max-width: 100%;
  /* Prevent the pre from forcing its parent wider than the viewport */
  min-width: 0;
}

/* Tailwind grids: allow cells to shrink below their content's min-content
   width. Without this, wide <pre> blocks push the cell (and the whole
   viewport) beyond 375px on mobile. */
[class*="grid-cols-"] > * {
  min-width: 0;
}

:not(pre) > code {
  background: #f1efeb;
  padding: 2px 6px;
  border-radius: 3px;
  color: var(--text);
}

/* --- Inline SVG icon utility ---
   Used wherever a small icon sits next to text (badges, headers, inside
   <pre><code> blocks). Inherits color via `currentColor` so one SVG markup
   works on dark + light backgrounds. Tailwind text-* classes can still
   recolor it. */
.sf-icon {
  display: inline-block;
  vertical-align: -0.15em;
  flex-shrink: 0;
}

/* --- Rank badges (Solid / Usable / Weak) --- */
.rank-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
}
.rank-solid { background: #e8f5e9; color: var(--rank-solid); }
.rank-usable { background: #e3f2ff; color: var(--rank-usable); }
.rank-weak { background: #fdeaea; color: var(--rank-weak); }

/* --- Mockups (HTML/CSS screenshots, used instead of real PNGs) --- */
.mockup {
  position: relative;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
  font-size: 13px;
}
.mockup-hero {
  aspect-ratio: 16 / 10;
  background: #fafaf9;
}
/* Compact variant used in the 3-step "How it works" section */
.mockup-hero--compact {
  aspect-ratio: 4 / 3;
}
/* Animated hero - needs more vertical room than the 16:10 default to
   show the whole app (header + form + Save button) AND the floating
   panel + notification without clipping the bottom. Matches the compact
   4:3 ratio. */
.mockup-hero--animated {
  aspect-ratio: 4 / 3;
}

/* ---------------------------------------------------------------
   Animated hero: a cursor (SVG) tours the form and a selection
   frame highlights each element in turn, with a live hover badge -
   mirrors what the extension actually does in the browser.
   --------------------------------------------------------------- */
.mockup-hero--animated .mockup-form-row,
.mockup-hero--animated .mockup-btn {
  position: relative;
}
.mockup-hero--animated .mockup-input {
  position: relative;
}

.mockup-selection {
  position: absolute;
  inset: -4px;
  border: 2px dashed;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  z-index: 0;
}
.mockup-selection--solid  { border-color: var(--rank-solid); background: rgba(15, 123, 15, 0.08); }
.mockup-selection--usable { border-color: var(--rank-usable); background: rgba(35, 131, 226, 0.09); }
.mockup-selection--weak   { border-color: var(--rank-weak); background: rgba(224, 62, 62, 0.09); }

.mockup-selection-badge {
  position: absolute;
  bottom: -24px;
  left: -2px;
  color: #ffffff;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 10px;
  font-weight: 600;
  padding: 3px 7px;
  border-radius: 3px;
  white-space: nowrap;
  letter-spacing: 0.1px;
  /* Stay above sibling/parent content even when the selection is at z-index:0 */
  z-index: 4;
}
.mockup-selection--solid  .mockup-selection-badge { background: var(--rank-solid); }
.mockup-selection--usable .mockup-selection-badge { background: var(--rank-usable); }
.mockup-selection--weak   .mockup-selection-badge { background: var(--rank-weak); }

/* Animation loop = 12s. Six clicks (Full name skipped / Email / Save / Stop
   / Results / Copy) ending on the generated ticket. Timing redesigned for
   a natural cadence: short 2% (240ms) click presses and tight dwells so
   the mouse actually feels like it's navigating. 1% = 120ms. */

/* Selections fade in at the click moment, linger ~6% so the reader has
   time to register the rank, then fade while the cursor travels away. */
@keyframes selection-tour-1 {
  0%, 8%    { opacity: 0; }
  10%, 18%  { opacity: 1; }
  20%, 100% { opacity: 0; }
}
@keyframes selection-tour-2 {
  0%, 21%   { opacity: 0; }
  23%, 31%  { opacity: 1; }
  33%, 100% { opacity: 0; }
}
@keyframes selection-tour-3 {
  0%, 32%   { opacity: 0; }
  34%, 42%  { opacity: 1; }
  44%, 100% { opacity: 0; }
}
.mockup-anim-target-1 { animation: selection-tour-1 12s 1 forwards ease-in-out; }
.mockup-anim-target-2 { animation: selection-tour-2 12s 1 forwards ease-in-out; }
.mockup-anim-target-3 { animation: selection-tour-3 12s 1 forwards ease-in-out; }

/* ---- Click feedback: each target briefly "presses" at its click moment
   (2% = 240ms, matches a natural mouse click). Same intensity everywhere
   (scale 0.95 + brightness 0.88). New click timeline:
     click 1 (Full name / skipped) : 10-12%
     click 2 (Email / usable)      : 23-25%
     click 3 (Save / weak)         : 34-36%
     click 4 (Stop)                : 46-48%
     click 5 (Results)             : 62-64%
     click 6 (Copy)                : 80-82%  (cursor-only, no button pulse) */
@keyframes click-pulse-input-1 {
  0%, 9%, 13%, 100% { transform: scale(1);    filter: none; }
  10%, 12%           { transform: scale(0.95); filter: brightness(0.88); }
}
@keyframes click-pulse-input-2 {
  0%, 22%, 26%, 100% { transform: scale(1);    filter: none; }
  23%, 25%           { transform: scale(0.95); filter: brightness(0.88); }
}
@keyframes click-pulse-save {
  0%, 33%, 37%, 100% { transform: scale(1);   filter: none; }
  34%, 36%           { transform: scale(0.95); filter: brightness(0.88); }
}
@keyframes click-pulse-stop {
  0%, 45%, 49%, 100% { transform: scale(1);   filter: none; }
  46%, 48%           { transform: scale(0.95); filter: brightness(0.88); }
}
@keyframes click-pulse-results {
  0%, 54%, 58%, 100% { transform: scale(1);   filter: none; }
  55%, 57%           { transform: scale(0.95); filter: brightness(0.88); }
}
/* Targets: use explicit click-pulse-N classes on each element since
   :nth-of-type counts tag siblings (not class siblings) and misses here. */
.mockup-hero--animated .mockup-click-pulse-1 {
  animation: click-pulse-input-1 12s 1 forwards ease-in-out;
  transition: background 0.1s;
}
.mockup-hero--animated .mockup-click-pulse-2 {
  animation: click-pulse-input-2 12s 1 forwards ease-in-out;
}
.mockup-hero--animated .mockup-btn {
  animation: click-pulse-save 12s 1 forwards ease-in-out;
}
/* Stop and Results buttons already have a state animation (rec/paused);
   stack the click pulse alongside via comma. */
.mockup-hero--animated .mockup-panel-stop {
  animation: panel-state-rec 12s 1 forwards, click-pulse-stop 12s 1 forwards ease-in-out;
}
.mockup-hero--animated .mockup-panel-results {
  animation: panel-state-paused 12s 1 forwards, click-pulse-results 12s 1 forwards ease-in-out;
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .mockup-hero--animated .mockup-form-row .mockup-input,
  .mockup-hero--animated .mockup-btn,
  .mockup-hero--animated .mockup-panel-stop,
  .mockup-hero--animated .mockup-panel-results {
    animation: none;
  }
}
/* Mobile: animations restent activées (feedback visuel important). */

/* Animated cursor (macOS-style arrow). Positioned in % so the tour
   scales with whatever width the .mockup-hero takes on the page. */
.mockup-cursor {
  position: absolute;
  width: 18px;
  height: 22px;
  /* The tip of the SVG arrow sits at pixel (2, 2) of the 18x22 image.
     Negative margin shifts the image up/left so the tip visually lands
     exactly on the CSS top/left anchor point. */
  margin: -2px 0 0 -2px;
  /* Scale origin anchored on the tip so the cursor-click scale(0.78)
     pulse shrinks AROUND the tip instead of pulling the cursor down. */
  transform-origin: 2px 2px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 28'><path d='M3 2 L3 22 L8 17 L12 26 L15 25 L11 16 L20 16 Z' fill='%23111' stroke='%23fff' stroke-width='1.5' stroke-linejoin='round'/></svg>") center/contain no-repeat;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.25));
  z-index: 12;
  pointer-events: none;
  /* Two animations cohabitate: cursor-tour animates top/left (position),
     cursor-click animates transform (click pulse). */
  animation:
    cursor-tour 12s 1 forwards cubic-bezier(0.4, 0, 0.2, 1),
    cursor-click 12s 1 forwards ease-out;
  /* Default position = top-left safe corner (no UI elements there) */
  top: 8%;
  left: 8%;
}

/* Cursor tour - coordinates come from CSS custom properties that JS
   measures from the actual DOM (see initCursorTargets in main.js).
   Fallback values match the hardcoded desktop estimate if JS is disabled.
   Each target window ENCLOSES its click pulse so the cursor is clearly
   "on" the element at press time. */
@keyframes cursor-tour {
  0%, 3%     { top: 8%; left: 8%; }
  9%, 14%    { top: var(--cursor-t1-y, 36%);  left: var(--cursor-t1-x, 30%); }  /* Full name (click 10-12) */
  22%, 27%   { top: var(--cursor-t2-y, 53%);  left: var(--cursor-t2-x, 30%); }  /* Email      (click 23-25) */
  33%, 38%   { top: var(--cursor-t3-y, 66%);  left: var(--cursor-t3-x, 18%); }  /* Save       (click 34-36) */
  45%, 50%   { top: var(--cursor-t4-y, 45%);  left: var(--cursor-t4-x, 80%); }  /* Stop       (click 46-48) */
  54%, 57%   { top: var(--cursor-t5-y, 45%);  left: var(--cursor-t5-x, 80%); }  /* Results    (click 55-57) */
  65%, 100%  { top: var(--cursor-t6-y, 45%);  left: var(--cursor-t6-x, 91%); }  /* Copy       (click 80-82) */
}

/* Measurement freeze: while JS measures each target, we neutralize
   animations, transforms and opacity so getBoundingClientRect() returns
   each element's final/visible position (especially the ticket + Results
   button that are otherwise offset/invisible). */
.mockup-measuring *,
.mockup-measuring *::before,
.mockup-measuring *::after {
  animation: none !important;
  transform: none !important;
  opacity: 1 !important;
  transition: none !important;
}
/* Note: the ticket used to be display:none on mobile, which required a
   measuring-time override to force visibility. That display:none is gone,
   and forcing display:block on the ticket + ALL descendants was flattening
   the flex header (.mockup-ticket-header) during measurement - the Copy
   button ended up stacked BELOW the filename instead of next to it, so its
   measured Y was ~30-50px too low. The `opacity: 1 !important` above is
   enough to make the ticket (opacity:0 by default) visible for measurement
   without breaking its internal flex layout. */

/* Click pulse - snappy scale-down (2% = 240ms, matches natural mouse click). */
@keyframes cursor-click {
  0%, 9%     { transform: scale(1); }
  10%, 12%   { transform: scale(0.78); }   /* click 1: Full name (skipped) */
  13%, 22%   { transform: scale(1); }
  23%, 25%   { transform: scale(0.78); }   /* click 2: Email */
  26%, 33%   { transform: scale(1); }
  34%, 36%   { transform: scale(0.78); }   /* click 3: Save */
  37%, 45%   { transform: scale(1); }
  46%, 48%   { transform: scale(0.78); }   /* click 4: Stop */
  49%, 54%   { transform: scale(1); }
  55%, 57%   { transform: scale(0.78); }   /* click 5: Results */
  58%, 79%   { transform: scale(1); }
  80%, 82%   { transform: scale(0.78); }   /* click 6: Copy */
  83%, 100%  { transform: scale(1); }
}

/* Animated "Steps" counter in the mockup panel - Solid click is SKIPPED
   (since Skip solid elements is checked). So only Usable (click 2) and
   Weak (click 3) increment. Sequence: 0 -> 1 -> 2. */
.mockup-counter {
  position: relative;
  display: inline-block;
  min-width: 10px;
  height: 1em;
  text-align: right;
  vertical-align: top;
}
.mockup-counter-val {
  position: absolute;
  top: 0;
  right: 0;
  opacity: 0;
}
@keyframes counter-0 {
  0%, 25%    { opacity: 1; }   /* stays 0 through skipped Full name click */
  26%, 100%  { opacity: 0; }
}
@keyframes counter-1 {
  0%, 25%    { opacity: 0; }
  26%, 36%   { opacity: 1; }   /* +1 after Email click (23-25%) */
  37%, 100%  { opacity: 0; }
}
@keyframes counter-2 {
  0%, 36%    { opacity: 0; }
  37%, 100%  { opacity: 1; }   /* +1 after Save click (34-36%), stays */
}
.mockup-counter-0 { animation: counter-0 12s 1 forwards; }
.mockup-counter-1 { animation: counter-1 12s 1 forwards; }
.mockup-counter-2 { animation: counter-2 12s 1 forwards; }

/* Brief green "All OK" flash on the Solid target (target 1) to show that
   skipSolid is in effect - matches extension's flashSkipped() behavior.
   Positioned ABOVE the input while the selection badge sits BELOW, so
   both are visible at the same time during the Solid click. */
.mockup-skipped-flash {
  position: absolute;
  top: -22px;
  left: 0;
  background: var(--rank-solid);
  color: #ffffff;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 3px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  letter-spacing: 0.2px;
  z-index: 4;
}
/* Same time window as selection-tour-1 so both badges fire together */
@keyframes skipped-flash {
  0%, 8%    { opacity: 0; }
  10%, 18%  { opacity: 1; }
  20%, 100% { opacity: 0; }
}
.mockup-hero--animated .mockup-skipped-flash {
  animation: skipped-flash 12s 1 forwards;
}

/* Panel state: REC stays until the Stop click is RELEASED (48%), then
   fades to Paused. The swap happens AFTER the click feedback so the press
   is actually seen. Stop click = 46-48%, fade 48-52%. */
@keyframes panel-state-rec {
  0%, 48%   { opacity: 1; }
  52%, 100% { opacity: 0; }
}
@keyframes panel-state-paused {
  0%, 48%   { opacity: 0; }
  52%, 100% { opacity: 1; }
}
.mockup-panel-state-rec    { animation: panel-state-rec 12s 1 forwards; }
.mockup-panel-state-paused { animation: panel-state-paused 12s 1 forwards; opacity: 0; }

/* Paused badge (replaces REC) */
.mockup-panel-paused-badge {
  display: inline-flex;
  align-items: center;
  background: #f1f1ef;
  color: #787774;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  letter-spacing: 0.4px;
}

/* Results button */
.mockup-panel-results {
  background: #37352f;
  color: #ffffff;
  text-align: center;
  padding: 7px 0;
  border-radius: 5px;
  font-weight: 600;
  font-size: 12px;
  margin-top: 2px;
}

/* The Stop and Results buttons share the same slot; stack them.
   Extra breathing room above (margin via bottom offset) so the click
   visibly lands on the button center, not flush against "Skip solid". */
.mockup-panel .mockup-panel-state-rec.mockup-panel-stop,
.mockup-panel .mockup-panel-state-paused.mockup-panel-results {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 14px;
  margin-top: 10px;
}

/* Ticket preview = raw markdown code, like in a ticket editor draft.
   Slides in after the Results click (at 78%) and stays till loop reset. */
.mockup-ticket {
  position: absolute;
  top: 14px;                         /* anchor to TOP so the start of the
                                        .md (title, quote, item #1) is
                                        always visible; any overflow clips
                                        at the bottom */
  left: 14px;
  right: 14px;
  max-height: calc(100% - 28px);     /* 14px margin top + 14px bottom */
  display: flex;                     /* flex column so the code pane can
                                        shrink within max-height */
  flex-direction: column;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.14);
  z-index: 11;
  opacity: 0;
  transform: translateY(10px);
  overflow: hidden;
}
.mockup-ticket-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  background: #ebeae7;
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  color: var(--muted);
}
.mockup-ticket-lights {
  width: 52px;
  height: 10px;
  background:
    radial-gradient(circle, #ff5f56 5px, transparent 5px) 0 50% / 18px 10px no-repeat,
    radial-gradient(circle, #ffbd2e 5px, transparent 5px) 18px 50% / 18px 10px no-repeat,
    radial-gradient(circle, #27c93f 5px, transparent 5px) 36px 50% / 16px 10px no-repeat;
  flex-shrink: 0;
}
.mockup-ticket-filename {
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-weight: 600;
  color: var(--text);
}

/* Copy button in the ticket header, right-aligned. Decorative in the
   mockup - matches the real "Copy Markdown" action in the extension. */
.mockup-ticket-copy {
  margin-left: auto;
  /* Fixed min-width so swapping "Copy" -> "Copied" (or "Copier" -> "Copié")
     at the click moment doesn't cause a width jump. Covers the widest
     EN/FR variant ("Copied" with check icon). */
  position: relative;
  min-width: 76px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: #ffffff;
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 4px;
  padding: 3px 8px;
  font-size: 10px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  line-height: 1.4;
  letter-spacing: 0.1px;
  transition: all 0.1s;
}
/* Two stacked states - default (Copy icon + label) and done (check +
   "Copied"/"Copié"). Default stays in flow so the button has a natural
   height; done is absolute and overlays it. */
.mockup-copy-state {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.mockup-copy-done {
  position: absolute;
  inset: 0;
  justify-content: center;
  opacity: 0;
}
.mockup-ticket-copy:hover {
  color: var(--brand-blue);
  border-color: var(--brand-blue);
}
.mockup-ticket-copy svg {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
}

/* Copy button flashes blue at the 6th click (80-82%) and STAYS blue until
   the loop restarts - so the "copied" state is the final resting image. */
@keyframes copy-btn-click {
  0%, 79%   { background: #ffffff; border-color: var(--border); color: var(--text); }
  80%, 100% { background: var(--brand-blue); border-color: var(--brand-blue); color: #ffffff; }
}
.mockup-hero--animated .mockup-ticket-copy {
  animation: copy-btn-click 12s 1 forwards;
}
/* At the same moment (80%), swap the label from "Copy" → "Copied" with a
   check icon. The swap is synced so bg + text + icon change together. */
@keyframes copy-label-default {
  0%, 79%   { opacity: 1; }
  80%, 100% { opacity: 0; }
}
@keyframes copy-label-done {
  0%, 79%   { opacity: 0; }
  80%, 100% { opacity: 1; }
}
.mockup-hero--animated .mockup-copy-default { animation: copy-label-default 12s 1 forwards; }
.mockup-hero--animated .mockup-copy-done    { animation: copy-label-done    12s 1 forwards; }

@media (prefers-reduced-motion: reduce) {
  .mockup-hero--animated .mockup-ticket-copy,
  .mockup-hero--animated .mockup-copy-default,
  .mockup-hero--animated .mockup-copy-done { animation: none; }
}

/* The code pane */
.mockup-ticket-code {
  padding: 10px 14px;
  font-family: 'SF Mono', 'Fira Code', ui-monospace, monospace;
  font-size: 11px;
  line-height: 1.55;
  color: var(--text);
  background: #ffffff;
  overflow: hidden;
  flex: 1;               /* fill space under the header in the flex column */
  min-height: 0;         /* allow shrinking below content min-content height */
}
.mockup-ticket-code .md-line { white-space: pre; }
.mockup-ticket-code .md-empty { height: 0.55em; }

/* Markdown syntax coloring (VSCode-ish, subtle on white bg) */
.md-heading   { color: #005cc5; font-weight: 700; }
.md-bold      { color: #24292f; font-weight: 700; }
.md-code      { color: #d73a49; background: #f6f8fa; padding: 1px 4px; border-radius: 3px; }
.md-quote     { color: #6a737d; font-style: italic; }
.md-bullet    { color: #6a737d; }
.md-rank-ok   { color: var(--rank-usable); font-weight: 600; }
.md-rank-weak { color: var(--rank-weak);   font-weight: 600; }
.md-code-fence {
  display: block;
  background: #f6f8fa;
  padding: 4px 8px;
  border-radius: 4px;
  color: #24292f;
  margin: 2px 0;
}

/* Realistic mini-screenshots embedded in the md code pane - they mimic
   the actual element captured (not a generic gradient rectangle). Looks
   like what a rendered md viewer would show for an embedded screenshot.
   Each shot has a dashed border in the rank's color. */
.mockup-md-shot {
  display: block;
  margin: 5px 0 5px 14px;
  padding: 6px 9px;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 5px;
  max-width: 240px;
  font-family: 'Inter', system-ui, sans-serif;
  line-height: 1.2;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.mockup-md-shot-label {
  font-size: 8px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 3px;
  letter-spacing: 0.2px;
}
.mockup-md-shot-input {
  padding: 4px 7px;
  background: #ffffff;
  border: 1.5px dashed;
  border-radius: 3px;
  font-size: 9px;
  color: #4a4a4a;
  font-family: 'Inter', system-ui, sans-serif;
}
.mockup-md-shot-btn {
  padding: 5px 10px;
  background: #2f2b6b;
  color: #ffffff;
  border: 1.5px dashed;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 600;
  text-align: center;
  font-family: 'Inter', system-ui, sans-serif;
}
/* Rank-colored dashed "capture" borders */
.mockup-md-shot--usable .mockup-md-shot-input { border-color: var(--rank-usable); }
.mockup-md-shot--weak .mockup-md-shot-btn     { border-color: var(--rank-weak); }

/* Subtle horizontal separator to divide each element entry */
.md-separator {
  display: block;
  height: 1px;
  background: #f1efeb;
  margin: 6px 0;
}

/* Ticket reveal - pops up AFTER the Results click is released (57%) so it
   clearly appears AS A CONSEQUENCE of the click. Results click = 55-57%. */
@keyframes ticket-reveal {
  0%, 58%   { opacity: 0; transform: translateY(10px); }
  64%, 100% { opacity: 1; transform: translateY(0); }
}
.mockup-hero--animated .mockup-ticket {
  animation: ticket-reveal 12s 1 forwards cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .mockup-counter-0,
  .mockup-counter-1 { animation: none; opacity: 0; }
  .mockup-counter-2 { animation: none; opacity: 1; }
  .mockup-panel-state-rec { animation: none; opacity: 1; }
  .mockup-panel-state-paused { animation: none; opacity: 0; }
  .mockup-ticket { animation: none; opacity: 0; }
  .mockup-skipped-flash { animation: none; }
}
/* (consolidated into the single mobile block below) */

/* The hero mockup ignores user hover entirely - it's a decorative scene,
   not an interactive widget. `pointer-events: none` makes sure mouseovers
   don't pause the animation (the previous :hover rule was nice in theory
   but disruptive in practice: any mouse passing through the area froze
   the cursor mid-sequence and left the user staring at a dead frame). */
.mockup-hero--animated,
.mockup-hero--animated * {
  pointer-events: none;
}

/* Respect reduced-motion preference */
@media (prefers-reduced-motion: reduce) {
  .mockup-cursor,
  .mockup-anim-target-1,
  .mockup-anim-target-2,
  .mockup-anim-target-3 {
    animation: none;
  }
  /* Show the weak one as a static representative */
  .mockup-anim-target-3 { opacity: 1; }
}

/* Mobile (< 640px): freeze the hero in a clean static "mid-recording"
   snapshot. All animations OFF, cursor hidden, ticket hidden, only the
   Weak selection on Save visible to convey the product concept. */
@media (max-width: 640px) {
  /* Flip the Save-button selection badge above (bottom:-24px would be
     clipped by the mockup overflow:hidden on narrow viewports). */
  .mockup-hero--animated .mockup-anim-target-3 .mockup-selection-badge {
    bottom: auto;
    top: -22px;
  }

  /* Let the hero grow to fit content on narrow screens (no fixed ratio).
     All animations run normally - the JS measures target centers relative
     to the hero at any viewport, so the cursor tour still lands correctly. */
  .mockup-hero--animated { aspect-ratio: auto; }
}

/* Mini page content (behind the panel) */
.mockup-page {
  padding: 20px 28px;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.mockup-app-header {
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.mockup-app-logo {
  font-weight: 700;
  color: #1a1a1a;
  font-size: 14px;
  display: inline-flex;
  gap: 6px;
  align-items: center;
}
.mockup-form-title {
  font-weight: 700;
  font-size: 15px;
  color: var(--text);
  margin-top: 4px;
}
.mockup-form-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mockup-form-row label {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}
.mockup-input {
  background: #ffffff;
  border: 1px solid #d8d7d3;
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13px;
  color: #4a4a4a;
}
.mockup-input--hover {
  border: 2px dashed var(--rank-weak);
  background: #fdeaea40;
}
.mockup-btn {
  background: #2f2b6b;
  color: white;
  border: none;
  border-radius: 6px;
  padding: 9px 20px;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  align-self: flex-start;
  /* Extra top space so the selection badge of the Email input above
     (bottom: -24px) doesn't fall on top of the Save button. */
  margin-top: 16px;
}

/* Floating panel (top-right) */
.mockup-panel {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 200px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.06);
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 12px;
  overflow: hidden;
}
/* Compact variant used in the "How it works" 3-up grid */
.mockup-panel--compact {
  width: 160px;
}
/* On narrow viewports the 200px panel hides most of the mini-app.
   Shrink and reposition so both panel and app stay readable. */
@media (max-width: 640px) {
  .mockup-panel {
    width: 150px;
    top: 10px;
    right: 10px;
    font-size: 11px;
  }
  .mockup-panel-header { padding: 7px 10px 7px 8px; }
  /* Keep enough bottom padding for the absolute Stop/Results button so it
     doesn't overlap the "Pages" row. */
  .mockup-panel-body { padding: 8px 10px 48px; gap: 6px; }
  .mockup-panel-stop { padding: 6px 0; font-size: 11px; }
  .mockup-panel-results { padding: 6px 0; font-size: 11px; }
  .mockup-panel .mockup-panel-state-rec.mockup-panel-stop,
  .mockup-panel .mockup-panel-state-paused.mockup-panel-results {
    left: 8px;
    right: 8px;
    bottom: 8px;
  }
  .mockup-panel-name { font-size: 11px; }
  .mockup-page { padding: 14px 18px; gap: 10px; }
  .mockup-form-row label { font-size: 10px; }
  .mockup-input { padding: 6px 10px; font-size: 12px; }
  .mockup-btn { padding: 7px 16px; font-size: 12px; }
}
.mockup-panel-header {
  display: flex;
  align-items: center;
  padding: 9px 12px 9px 10px;
  background: #fafaf9;
  border-bottom: 1px solid var(--border);
  position: relative;
}
/* REC badge pushed to the far right; Paused badge layers on top at the
   same spot (one is visible at a time via opacity). */
.mockup-panel-header .mockup-panel-state-rec {
  margin-left: auto;
}
.mockup-panel-header .mockup-panel-state-paused.mockup-panel-paused-badge {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
}
.mockup-panel-brand {
  font-weight: 700;
  color: var(--text);
  display: inline-flex;
  gap: 5px;
  align-items: center;
  font-size: 12px;
}
.mockup-panel-rec {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--rank-weak);
  color: white;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  letter-spacing: 0.4px;
}
.mockup-rec-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: white;
  animation: pulse 1.2s infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
.mockup-panel-body {
  padding: 10px 12px 54px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mockup-panel-name {
  font-weight: 600;
  color: var(--text);
  font-size: 12px;
}
.mockup-panel-stat {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: 11px;
}
.mockup-panel-stat strong {
  color: var(--text);
  font-weight: 700;
}
.mockup-panel-check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--muted);
  padding-top: 2px;
}
.mockup-panel-check::before {
  content: "";
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  background: var(--brand-blue) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path d='M3 6.5l2 2 4-4.5' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/10px no-repeat;
  border-radius: 2px;
}
.mockup-panel-stop {
  background: var(--rank-weak);
  color: white;
  text-align: center;
  padding: 7px 0;
  border-radius: 5px;
  font-weight: 600;
  font-size: 12px;
  margin-top: 2px;
}

/* Hover-weak mockup (live cadre + badge) */
.mockup-hover {
  padding: 40px;
  background: #fafaf9;
  min-height: 200px;
}
.mockup-hover-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 320px;
}
.mockup-hover-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}
.mockup-hover-badge {
  display: inline-block;
  margin-top: 8px;
  background: var(--rank-weak);
  color: white;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 4px;
  line-height: 1.4;
  max-width: max-content;
}

/* Results-list mockup */
.mockup-results {
  padding: 14px 16px 18px;
  min-height: 240px;
}
.mockup-results-header {
  font-weight: 600;
  color: var(--text);
  font-size: 13px;
  padding: 6px 0 12px;
  border-bottom: 1px solid var(--border);
}
.mockup-results-header small {
  font-weight: 400;
  color: var(--subtle);
  margin-left: 6px;
}
.mockup-step-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}
.mockup-step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 6px;
  background: #fafaf9;
  font-size: 12px;
}
.mockup-step-num {
  width: 22px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
}
.mockup-step-num--solid  { background: var(--rank-solid); }
.mockup-step-num--usable { background: var(--rank-usable); }
.mockup-step-num--weak   { background: var(--rank-weak); }
.mockup-step-tag {
  font-family: 'SF Mono', monospace;
  color: var(--muted);
  font-size: 11px;
}
.mockup-step-testid {
  font-family: 'SF Mono', monospace;
  font-weight: 600;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mockup-step-text {
  color: var(--subtle);
  font-size: 11px;
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: none;
}
@media (min-width: 640px) {
  .mockup-step-text { display: inline; }
}

/* Ticket-export mockup (markdown + zip combo) */
.mockup-export {
  padding: 16px;
  background: #fafaf9;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 240px;
}
.mockup-export pre {
  margin: 0;
  font-size: 11px;
  padding: 12px 14px;
}
.mockup-export-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--subtle);
  letter-spacing: 0.6px;
  text-transform: uppercase;
}

/* Copy-image mockup */
.mockup-copy-image {
  position: relative;
  padding: 16px;
  background: #fafaf9;
  min-height: 240px;
}
.mockup-thumb {
  position: relative;
  background: linear-gradient(135deg, #ebeae7 0%, #d8d7d3 100%);
  border-radius: 8px;
  padding: 8px;
  height: 180px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 12px;
  overflow: hidden;
}
.mockup-thumb::before {
  content: "";
  position: absolute;
  inset: 60px 100px;
  background: white;
  border: 2px solid var(--rank-weak);
  border-radius: 4px;
}
.mockup-thumb::after {
  content: "data-testid=\"merge-button\"";
  position: absolute;
  top: 40px;
  left: 96px;
  background: var(--rank-weak);
  color: white;
  font-family: 'SF Mono', monospace;
  font-size: 10px;
  font-weight: 600;
  padding: 3px 7px;
  border-radius: 3px;
  white-space: nowrap;
}
.mockup-copy-btn {
  position: absolute;
  top: 24px;
  right: 24px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: white;
  color: var(--brand-blue);
  border: 1px solid var(--brand-blue);
  border-radius: 4px;
  padding: 4px 9px;
  font-size: 11px;
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(0,0,0,0.08);
}
.mockup-copy-hint {
  margin-top: 14px;
  padding: 10px 14px;
  background: white;
  border-radius: 6px;
  border: 1px solid var(--border);
  font-size: 12px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 10px;
}
.mockup-copy-hint strong { color: var(--text); }

/* --- Browser mock chrome (for screenshot embeds, matches results.html) --- */
.browser-mock {
  background: #ebeae7;
  border: 1px solid var(--border);
  border-radius: 10px 10px 0 0;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--muted);
  font-family: 'SF Mono', monospace;
}
.browser-mock-lights {
  width: 52px;
  height: 12px;
  background:
    radial-gradient(circle, #ff5f56 6px, transparent 6px) 0 50% / 18px 12px no-repeat,
    radial-gradient(circle, #ffbd2e 6px, transparent 6px) 18px 50% / 18px 12px no-repeat,
    radial-gradient(circle, #27c93f 6px, transparent 6px) 36px 50% / 16px 12px no-repeat;
  flex-shrink: 0;
}
.browser-mock-url {
  flex: 1;
  background: white;
  border: 1px solid #d8d7d3;
  border-radius: 6px;
  padding: 4px 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- FAQ accordion --- */
.faq-item {
  border-bottom: 1px solid var(--border);
}
.faq-item summary {
  cursor: pointer;
  padding: 18px 0;
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "＋";
  color: var(--subtle);
  font-size: 18px;
  flex-shrink: 0;
  transition: transform 0.15s;
}
.faq-item[open] summary::after {
  content: "−";
  transform: rotate(0deg);
}
.faq-item .faq-body {
  padding: 0 0 18px 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.7;
}

/* --- Section separators --- */
.section {
  padding: 96px 0;
}
.section-tight {
  padding: 64px 0;
}
@media (max-width: 768px) {
  .section { padding: 64px 0; }
  .section-tight { padding: 48px 0; }
}

/* --- Gradient backgrounds used sparingly --- */
.bg-subtle {
  background: var(--bg-subtle);
}

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 22px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  transition: all 0.12s;
  cursor: pointer;
  border: none;
  font-family: inherit;
}
.btn-primary {
  background: var(--brand-blue);
  color: white;
}
.btn-primary:hover {
  background: var(--brand-blue-dark);
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(35, 131, 226, 0.25);
}
.btn-outline {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}
.btn-outline:hover {
  background: var(--bg-subtle);
  border-color: var(--text);
}

/* --- Inputs in contact form --- */
.form-input, .form-select, .form-textarea {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  background: white;
  transition: border 0.1s, box-shadow 0.1s;
}
.form-input:focus, .form-select:focus, .form-textarea:focus {
  outline: none;
  border-color: var(--brand-blue);
  box-shadow: 0 0 0 3px rgba(35, 131, 226, 0.12);
}
.form-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 6px;
}

/* --- Honeypot field (bot trap).
   Off-screen but not `display: none` because some bots detect that. */
.honeypot {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* --- Math captcha — narrow input, the question text is injected by JS --- */
.form-captcha-input {
  max-width: 120px;
}
[data-captcha-question] {
  font-family: 'SF Mono', 'Fira Code', ui-monospace, Menlo, monospace;
  font-weight: 700;
  color: var(--brand-blue);
  margin-left: 4px;
}

/* --- Contact modal (native <dialog>) --- */
.contact-modal {
  max-width: 620px;
  width: min(620px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 32px 80px rgba(15, 23, 42, 0.25), 0 0 0 1px rgba(0, 0, 0, 0.04);
  background: #ffffff;
  color: var(--text);
  overflow: hidden;
}
.contact-modal::backdrop {
  background: rgba(15, 23, 42, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.contact-modal:not([open]) { display: none; }
.contact-modal[open] {
  animation: modal-pop 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes modal-pop {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Scrollable inner body so long forms don't push the modal out of the viewport */
.contact-modal-body {
  overflow-y: auto;
  max-height: calc(100vh - 120px);
  padding: 12px 40px 36px;
}
.contact-modal-topbar {
  display: flex;
  justify-content: flex-end;
  padding: 10px 12px 0;
  margin: 0;
}
.contact-modal-close {
  background: transparent;
  border: none;
  font-size: 32px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 4px 12px;
  border-radius: 6px;
  font-family: inherit;
  transition: all 0.1s;
}
.contact-modal-close:hover {
  color: var(--text);
  background: var(--bg-subtle);
}
@media (max-width: 640px) {
  .contact-modal-body { padding: 8px 20px 28px; }
}

/* --- Pricing cards --- */
.pricing-card {
  background: white;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: transform 0.15s, box-shadow 0.15s;
}
.pricing-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06);
}
.pricing-card--featured {
  border: 2px solid var(--brand-blue);
  box-shadow: 0 10px 40px rgba(35, 131, 226, 0.12);
  position: relative;
}
.pricing-card--featured::before {
  content: attr(data-featured-label);
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--brand-blue);
  color: white;
  padding: 4px 14px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
}

/* --- ROI calculator sliders --- */
.roi-slider {
  width: 100%;
  margin: 8px 0;
  accent-color: var(--brand-blue);
}
.roi-value {
  font-weight: 700;
  color: var(--brand-blue);
  font-variant-numeric: tabular-nums;
}
.roi-output {
  background: linear-gradient(135deg, #2383e2 0%, #0b6bcb 100%);
  color: white;
  padding: 24px 28px;
  border-radius: 12px;
  font-size: 20px;
  font-weight: 500;
  text-align: center;
  box-shadow: 0 8px 24px rgba(35, 131, 226, 0.22);
}
.roi-output strong {
  font-weight: 700;
  font-size: 1.2em;
}

/* Detailed breakdown of how the ROI numbers are computed. Goal: make the
   client see it's honest math, not marketing inflation. */
.roi-method {
  margin-top: 24px;
  padding: 18px 22px;
  background: #fafaf9;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 13px;
  color: var(--muted);
}
.roi-method-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.4px;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.roi-method-list {
  list-style: none;
  padding: 0;
  margin: 0 0 14px 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  line-height: 1.55;
}
.roi-method-list li {
  padding-left: 16px;
  position: relative;
}
.roi-method-list li::before {
  content: '→';
  position: absolute;
  left: 0;
  color: var(--brand-blue);
  font-weight: 700;
}
.roi-method-list strong {
  color: var(--text);
  font-weight: 600;
}
.roi-method-note {
  margin: 0;
  padding: 10px 14px;
  background: #ffffff;
  border-left: 3px solid var(--brand-blue);
  border-radius: 0 6px 6px 0;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.55;
}

/* --- Top nav --- */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--border);
}
/* Exclude CTA buttons so they keep their own color (white on blue). */
.nav a:not(.btn) {
  color: var(--muted);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: color 0.1s;
}
.nav a:not(.btn):hover { color: var(--text); }

/* --- Visual: integration logos placeholder --- */
.logo-chip {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 18px;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  transition: all 0.1s;
}
.logo-chip:hover {
  border-color: var(--brand-blue);
  color: var(--text);
}

/* --- Small utility: .check renders a green SVG checkmark before the text.
   Uses an inline SVG as a background-image (encoded as data URI) so we
   stay emoji-free. The stroke color matches --rank-solid. */
.check::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 8px;
  vertical-align: -0.15em;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230f7b0f' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>") center/contain no-repeat;
}
