/* ═══════════════════════════════════════════════════════════════════
   TOOL PAGE DESIGN SYSTEM   (prefix: tp-)

   Structure this stylesheet serves — every /tools/{slug} page:

     hero  →  the tool IS the hero. Headline + the working panel, no
              separate marketing banner above an unrelated widget.
     workspace → one centred panel; once the tool produces output the
              page becomes a two-column workbench (controls stay put,
              results open beside them) instead of pushing controls
              off-screen.
     how   →  numbered steps
     faq   →  accordion
     cta   →  closing action

   Every colour resolves from styles.css tokens so light and dark are
   the same stylesheet. Where a tint has no token, both themes are
   declared explicitly — never a single hardcoded hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Local tokens ─────────────────────────────────────────────────── */
:root {
  --tp-panel:        var(--card);
  --tp-panel-glass:  rgba(255, 255, 255, .82);
  --tp-panel-inset:  #F8FAFC;
  --tp-line:         var(--border);
  --tp-line-soft:    rgba(226, 232, 240, .7);
  --tp-scrim:        rgba(15, 23, 42, .55);
  --tp-ok:           #059669;
  --tp-ok-bg:        rgba(5, 150, 105, .10);
  --tp-err:          #DC2626;
  --tp-err-bg:       rgba(220, 38, 38, .07);
  --tp-err-line:     rgba(220, 38, 38, .22);
  --tp-knob:         #FFFFFF;
  --tp-flow-grid:    rgba(15, 23, 42, .04);
  --tp-sweep:        rgba(6, 182, 212, .16);
  --tp-wave-lit:     rgba(6, 182, 212, .38);
  --tp-match:        #0E7490;
  --tp-stage-h:      5.5rem;  /* floor only — the stage still grows to its tallest mode */
  --tp-mark:         #FEF08A;
  --tp-mark-current: #FDE047;
  --vte-res-bg:      linear-gradient(180deg, #F5F8FF 0%, #FFFFFF 55%);
  --vte-res-glow:    radial-gradient(ellipse 70% 100% at 50% 0%, rgba(37, 99, 235, .16), transparent 70%);
  --vte-res-shadow:  0 28px 64px -34px rgba(37, 99, 235, .45), 0 4px 16px rgba(15, 23, 42, .06);
  --vte-head-bg:     linear-gradient(180deg, rgba(219, 234, 254, .45), transparent);
  --tp-badge-glow:   rgba(37, 99, 235, .55);
  --vte-head-glyph:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='22'/%3E%3C/svg%3E");
}

[data-theme="dark"] {
  --tp-panel:        var(--card);
  --tp-panel-glass:  rgba(15, 23, 42, .82);
  --tp-panel-inset:  #0B1220;
  --tp-line:         var(--border);
  --tp-line-soft:    rgba(148, 163, 184, .14);
  --tp-scrim:        rgba(2, 6, 23, .72);
  --tp-ok:           #34D399;
  --tp-ok-bg:        rgba(52, 211, 153, .12);
  --tp-err:          #F87171;
  --tp-err-bg:       rgba(248, 113, 113, .10);
  --tp-err-line:     rgba(248, 113, 113, .28);
  --tp-knob:         #94A3B8;
  --tp-flow-grid:    rgba(148, 163, 184, .06);
  --tp-sweep:        rgba(34, 211, 238, .20);
  --tp-wave-lit:     rgba(34, 211, 238, .42);
  --tp-match:        #22D3EE;
  --tp-stage-h:      5.5rem;
  --tp-mark:         rgba(250, 204, 21, .32);
  --tp-mark-current: rgba(250, 204, 21, .58);
  --vte-res-bg:      linear-gradient(180deg, #0A1120 0%, #020617 55%);
  --vte-res-glow:    radial-gradient(ellipse 70% 100% at 50% 0%, rgba(59, 130, 246, .28), transparent 70%);
  --vte-res-shadow:  0 28px 64px -34px rgba(2, 6, 23, .9), 0 4px 16px rgba(2, 6, 23, .5);
  --vte-head-bg:     linear-gradient(180deg, rgba(59, 130, 246, .12), transparent);
  --tp-badge-glow:   rgba(34, 211, 238, .45);
  --vte-head-glyph:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='22'/%3E%3C/svg%3E");
}

/* ═══════════════════════════════════════════════════════════════════
   1 · HERO — headline and tool share one space
   ═══════════════════════════════════════════════════════════════════ */
.tp-hero {
  position: relative;
  padding: 56px 0 72px;
  overflow: hidden;
  isolation: isolate;
}

/* ── The canvas ───────────────────────────────────────────────────
   A tool page paints its own hero background: mesh wash, three colour
   glows, a 48px measurement grid, two scanner hairlines and a ring of
   floating platform marks. Same recipe the homepage hero uses, owned
   here so a tool page never depends on the homepage's markup or CSS —
   each tool's blade lays out its own set of marks. */
.tp-canvas {
  pointer-events: none;
  position: absolute;
  inset: 0;
  overflow: hidden;
  contain: layout paint;
}

.tp-canvas-mesh {
  position: absolute;
  inset: 0;
  background: var(--gradient-mesh);
  opacity: .9;
}

.tp-canvas-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(3rem);
  transform: translateZ(0);
}
.tp-canvas-glow--top {
  top: -8rem;
  left: 50%;
  width: 32.5rem;
  height: 32.5rem;
  transform: translateX(-50%) translateZ(0);
  background: rgba(37, 99, 235, .15);
}
.tp-canvas-glow--left {
  top: 33%;
  left: -6rem;
  width: 24rem;
  height: 24rem;
  background: rgba(6, 182, 212, .20);
}
.tp-canvas-glow--right {
  right: 0;
  bottom: 0;
  width: 28rem;
  height: 28rem;
  background: rgba(139, 92, 246, .15);
}

.tp-canvas-grid {
  position: absolute;
  inset: 0;
  opacity: .06;
  background-image:
      linear-gradient(var(--foreground) 1px, transparent 1px),
      linear-gradient(90deg, var(--foreground) 1px, transparent 1px);
  background-size: 48px 48px;
}

.tp-canvas-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
}
.tp-canvas-line--1 {
  top: 36.33%;
  background: linear-gradient(to right, transparent, rgba(6, 182, 212, .3), transparent);
}
.tp-canvas-line--2 {
  top: 66.66%;
  background: linear-gradient(to right, transparent, rgba(37, 99, 235, .2), transparent);
}

/* A mark is placed by the blade (top/left/size/delay as inline style) so
   each tool can arrange its own constellation. */
.tp-canvas-mark {
  position: absolute;
  display: grid;
  place-items: center;
  width: var(--s, 72px);
  height: var(--s, 72px);
  border-radius: 1rem;
  border: 1px solid rgba(226, 232, 240, .6);
  background: rgba(255, 255, 255, .4);
  box-shadow: var(--shadow-soft);
  backdrop-filter: blur(12px);
  opacity: .85;
  animation: tp-float var(--dur, 10s) ease-in-out var(--delay, 0s) infinite;
}
[data-theme="dark"] .tp-canvas-mark {
  background: rgba(30, 41, 59, .3);
  border-color: rgba(30, 41, 59, .6);
}

.tp-canvas-mark svg {
  width: calc(var(--s, 72px) * .45);
  height: calc(var(--s, 72px) * .45);
  opacity: .9;
}

@keyframes tp-float {
  0%, 100% { transform: translateY(0)     rotate(var(--rot, 0deg)); }
  50%      { transform: translateY(-14px) rotate(var(--rot, 0deg)); }
}

/* Everything above the canvas has to be lifted out of its way. */
.tp-hero > .container {
  position: relative;
  z-index: 1;
}

/* The marks crowd the copy once the hero narrows. */
@media (max-width: 991px) {
  .tp-canvas-mark { display: none; }
}

.tp-hero-head {
  text-align: center;
  max-width: 720px;
  margin: 0 auto 34px;
}

.tp-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px 5px 10px;
  border-radius: 50px;
  background: var(--card);
  border: 1px solid var(--tp-line);
  box-shadow: var(--shadow-sm);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  margin-bottom: 20px;
}

.tp-eyebrow::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gradient-scanner);
  box-shadow: 0 0 0 3px var(--primary-soft);
}

.tp-hero-head h1 {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4.6vw, 3.1rem);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.03em;
  color: var(--foreground);
  margin-bottom: 16px;
}

.tp-hero-head h1 em {
  font-style: normal;
  background: var(--gradient-scanner);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.tp-hero-head p {
  font-size: 1.02rem;
  line-height: 1.7;
  color: var(--muted-foreground);
  max-width: 580px;
  margin: 0 auto;
}

/* Trust row — facts about the tool, stated once, near the action. */
.tp-trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 22px;
}

.tp-trust span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 13px;
  border-radius: 50px;
  background: var(--card);
  border: 1px solid var(--tp-line);
  font-size: .74rem;
  font-weight: 600;
  color: var(--muted-foreground);
}

.tp-trust span::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--tp-ok);
}

/* ═══════════════════════════════════════════════════════════════════
   2 · WORKSPACE — centred, then splits into a workbench
   ═══════════════════════════════════════════════════════════════════ */
.tp-workspace {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 56rem;          /* the homepage widget's own width */
  margin: 0 auto;
  transition: max-width .35s ease;
}

/* The two glows the homepage search box wears, so the tool sits on the
   hero canvas the same way rather than floating on it as a flat card. */
.tp-workspace::before,
.tp-workspace::after {
  content: '';
  position: absolute;
  pointer-events: none;
  z-index: 0;
  filter: blur(2rem);
}
.tp-workspace::before {
  inset: -2rem;
  border-radius: 2.5rem;
  background: linear-gradient(135deg, rgba(37,99,235,.10), rgba(6,182,212,.15), rgba(20,184,166,.10));
}
.tp-workspace::after {
  inset: -.5rem 1rem;
  border-radius: 2rem;
  background: var(--gradient-primary);
  opacity: .2;
}

/* Added by each tool's JS the moment it has something to show. The
   controls panel keeps its place so the input can be changed and re-run
   without scrolling back — the results simply open next to it. */
.tp-workspace.is-expanded {
  display: grid;
  grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
  align-items: start;
  gap: 20px;
  max-width: 1220px;
}

@media (max-width: 991px) {
  .tp-workspace.is-expanded {
    display: flex;
    max-width: 56rem;
  }
}

/* ── Panel ────────────────────────────────────────────────────────── */
.tp-panel {
  position: relative;
  z-index: 1;
  background: var(--tp-panel-glass);
  backdrop-filter: blur(28px) saturate(180%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  border: 1px solid var(--tp-line-soft);
  border-radius: 22px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

/* The scanner hairline. Only the panel that *does the work* wears it,
   so the eye lands on the input first on a page with several panels. */
.tp-panel--primary::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--gradient-scanner);
  z-index: 3;
}

.tp-panel-head {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 18px 22px;
  border-bottom: 1px solid var(--tp-line);
}

.tp-panel-icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: var(--primary-soft);
  font-size: 1rem;
  line-height: 1;
}

.tp-panel-head h2,
.tp-panel-head h3 {
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--foreground);
  margin: 0;
}

.tp-panel-head p {
  font-size: .76rem;
  color: var(--muted-foreground);
  margin: 2px 0 0;
}

.tp-panel-body {
  padding: 22px;
}

@media (max-width: 480px) {
  .tp-panel-head { padding: 15px 17px; }
  .tp-panel-body { padding: 17px; }
}

/* ── The homepage widget, reused as a control panel ───────────────── */
/* A tool page's controls are the same component the homepage hero runs:
   .search-box.glass-search with its .search-tabs mode row and
   .search-panels, all styled by styles.css. Only the things that differ
   here — a two-mode row instead of five, and sitting above the
   workspace's glow — are declared. */
.tp-tool {
  position: relative;
  z-index: 1;
}

/* Full width, like the homepage's row. The tile content is centred inside
   its half rather than left in a corner of it. */
.tp-tabs-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* With only two tiles there is room to name them on a phone, where the
   homepage's five-tile row has to fall back to bare icons. */
@media (max-width: 767px) {
  .tp-tabs-2 .search-tab {
    flex-direction: row;
    gap: .5rem;
    padding: .625rem .5rem;
  }
  .tp-tabs-2 .search-tab-label { display: block; }
  .tp-tabs-2 .search-tab-sub   { display: none; }
}

/* ── Mode stage ───────────────────────────────────────────────────
   Both mode panels occupy the SAME grid cell, so the stage is always
   as tall as the taller of them and switching modes cannot move the
   switch, the button or anything below the widget. The inactive panel
   keeps its box (visibility, not display) but leaves the tab order. */
.tp-mode-stage {
  display: grid;
  align-items: center;
  min-height: var(--tp-stage-h);
}

.tp-tool .tp-mode-stage > .search-panel {
  grid-area: 1 / 1;
  display: block;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease;
}

.tp-tool .tp-mode-stage > .search-panel.active {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
}

/* A single row rather than a tall stack. The mode stage reserves room for
   whichever panel is taller, so every pixel the drop zone is taller than the
   URL field becomes dead space in URL mode. Laid out side by side, the two
   modes are within a few pixels of each other: no reserved gap, and still no
   jump when the mode changes. */
.tp-tool .drop-zone {
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  padding: 15px 18px;
  text-align: left;
}

.tp-tool .drop-zone-icon {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 13px;
}
.tp-tool .drop-zone-icon svg { width: 19px; height: 19px; }

.tp-tool .drop-zone-title { font-size: .92rem; }
.tp-tool .drop-zone-hint  { margin-top: 2px; }

/* The chosen file takes the zone's place in the same box — the homepage
   widget does exactly this, which is why its panel never resizes. */
.tp-tool .drop-zone.has-file { border-style: solid; }

.tp-tool .drop-zone .tp-file-text {
  display: block;
  min-width: 0;          /* lets the name actually shrink inside the flex row */
  overflow: hidden;
}

/* One line, always. A long name that wrapped would change the zone's height,
   which is the very thing this layout exists to prevent. */
.tp-tool .drop-zone.has-file .drop-zone-title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tp-file-clear {
  margin-left: auto;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border: 1px solid var(--tp-line);
  border-radius: 50%;
  background: var(--card);
  color: var(--muted-foreground);
  font-size: .8rem;
  line-height: 1;
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
.tp-file-clear:hover { color: var(--tp-err); border-color: var(--tp-err); background: var(--tp-err-bg); }

/* "Supports:" was sitting on the field's edge. */
.tp-tool .search-url-chips { margin-top: 1.75rem; }

/* The dashed zone reacts to a drag the same way it reacts to a hover. */
.tp-tool .drop-zone.dragover {
  border-color: var(--primary);
  box-shadow: var(--shadow-glow);
}

/* The switch and the inline error belong to the panel stack, not to a
   panel, so they carry their own spacing rather than a panel's. */
.tp-tool .tp-error { margin-top: 12px; }

/* ── Field label ──────────────────────────────────────────────────── */
.tp-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  margin-bottom: 9px;
}

.tp-label-hint {
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--light-text);
}

/* ── Text input ───────────────────────────────────────────────────── */
.tp-input-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--tp-panel-inset);
  border: 1.5px solid var(--tp-line);
  border-radius: 14px;
  padding: 0 14px;
  transition: border-color .18s, box-shadow .18s, background .18s;
}

.tp-input-row:focus-within {
  border-color: var(--primary);
  background: var(--tp-panel);
  box-shadow: 0 0 0 4px var(--primary-soft);
}

.tp-input-row.is-invalid {
  border-color: var(--tp-err);
  box-shadow: 0 0 0 4px var(--tp-err-bg);
}

.tp-input-icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  color: var(--muted-foreground);
}

.tp-input-icon svg {
  width: 17px;
  height: 17px;
}

.tp-input-row input {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  outline: none;
  padding: 14px 0;
  font-size: .9rem;
  color: var(--foreground);
}

.tp-input-row input::placeholder { color: var(--light-text); }

.tp-inline-btn {
  flex-shrink: 0;
  border: 1px solid var(--tp-line);
  background: var(--tp-panel);
  color: var(--muted-foreground);
  border-radius: 9px;
  padding: 5px 11px;
  font-size: .72rem;
  font-weight: 700;
  transition: color .15s, border-color .15s, background .15s;
}

.tp-inline-btn:hover {
  color: var(--primary);
  border-color: var(--primary);
  background: var(--primary-soft);
}

/* ── Dropzone ─────────────────────────────────────────────────────── */
.tp-drop {
  border: 2px dashed var(--tp-line);
  border-radius: 16px;
  background: var(--tp-panel-inset);
  padding: 40px 22px;
  text-align: center;
  cursor: pointer;
  transition: border-color .18s, background .18s, box-shadow .18s;
}

.tp-drop:hover,
.tp-drop.is-over {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: 0 0 0 4px var(--primary-soft);
}

.tp-drop.is-loaded {
  border-style: solid;
  border-color: var(--primary);
  background: var(--primary-soft);
  cursor: default;
}

.tp-drop-icon {
  width: 54px;
  height: 54px;
  margin: 0 auto 14px;
  display: grid;
  place-items: center;
  border-radius: 17px;
  background: var(--gradient-scanner);
  color: #fff;
  box-shadow: var(--shadow-soft);
}

.tp-drop-icon svg { width: 24px; height: 24px; }

.tp-drop-title {
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0 0 6px;
}

.tp-drop-sub {
  font-size: .79rem;
  color: var(--muted-foreground);
  margin: 0;
  line-height: 1.55;
}

.tp-drop-sub strong { color: var(--primary); font-weight: 700; }

/* Selected-file strip */
.tp-file {
  display: none;
  align-items: center;
  gap: 11px;
  background: var(--tp-panel-inset);
  border: 1px solid var(--tp-line);
  border-radius: 12px;
  padding: 11px 13px;
  margin-top: 12px;
}

.tp-file.show { display: flex; }

.tp-file-icon {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 9px;
  background: var(--primary-soft);
  color: var(--primary);
}

.tp-file-icon svg { width: 16px; height: 16px; }

.tp-file-text { flex: 1; min-width: 0; }

.tp-file-name {
  font-size: .82rem;
  font-weight: 700;
  color: var(--foreground);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tp-file-meta {
  font-size: .73rem;
  color: var(--muted-foreground);
  margin-top: 1px;
}

.tp-file-remove {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  color: var(--muted-foreground);
  font-size: .9rem;
  line-height: 1;
  transition: color .15s, background .15s;
}

.tp-file-remove:hover { color: var(--tp-err); background: var(--tp-err-bg); }

/* ── Switch ───────────────────────────────────────────────────────── */
.tp-switch {
  display: flex;
  align-items: center;
  gap: 11px;
  cursor: pointer;
  width: fit-content;
}

.tp-switch input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.tp-switch-track {
  position: relative;
  width: 40px;
  height: 23px;
  flex-shrink: 0;
  border-radius: 50px;
  background: var(--secondary);
  border: 1px solid var(--tp-line);
  transition: background .2s, border-color .2s;
}

/* The knob must read lighter than its track in BOTH themes — --card is
   darker than --secondary in dark, which would sink the knob into the
   track instead of lifting it off. */
.tp-switch-track::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--tp-knob);
  box-shadow: var(--shadow-sm);
  transition: transform .2s ease;
}

.tp-switch input:checked + .tp-switch-track {
  background: var(--gradient-primary);
  border-color: transparent;
}

.tp-switch input:checked + .tp-switch-track::after {
  transform: translateX(17px);
  background: #fff;
}

.tp-switch input:focus-visible + .tp-switch-track {
  box-shadow: 0 0 0 4px var(--primary-soft);
}

.tp-switch-text { font-size: .85rem; font-weight: 600; color: var(--foreground); }
.tp-switch-text small { display: block; font-size: .73rem; font-weight: 500; color: var(--muted-foreground); margin-top: 1px; }

/* ── Buttons ──────────────────────────────────────────────────────── */
.tp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border-radius: 13px;
  padding: 14px 24px;
  font-family: var(--font-display);
  font-size: .92rem;
  font-weight: 700;
  letter-spacing: -.01em;
  white-space: nowrap;
  transition: transform .16s ease, box-shadow .16s ease, background .16s, color .16s, border-color .16s;
}

.tp-btn svg { width: 17px; height: 17px; flex-shrink: 0; }

.tp-btn--primary {
  width: 100%;
  background: var(--gradient-primary);
  color: #fff;
  box-shadow: 0 8px 22px -10px rgba(37, 99, 235, .8);
}

.tp-btn--primary:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 14px 30px -12px rgba(37, 99, 235, .9);
}

.tp-btn--primary:disabled { opacity: .55; cursor: not-allowed; transform: none; }

.tp-btn--ghost {
  background: var(--tp-panel);
  border: 1px solid var(--tp-line);
  color: var(--muted-foreground);
  padding: 9px 16px;
  font-size: .81rem;
  border-radius: 50px;
}

.tp-btn--ghost:hover {
  color: var(--primary);
  border-color: var(--primary);
  background: var(--primary-soft);
}

.tp-btn--ghost.is-done { color: var(--tp-ok); border-color: var(--tp-ok); background: var(--tp-ok-bg); }

.tp-note {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-size: .74rem;
  color: var(--light-text);
  margin: 12px 0 0;
}

.tp-note svg { width: 13px; height: 13px; flex-shrink: 0; }

/* ── Field error ──────────────────────────────────────────────────── */
.tp-error {
  display: none;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: .8rem;
  color: var(--tp-err);
}

.tp-error.show { display: flex; }

/* ── Result panel furniture ───────────────────────────────────────── */
.tp-result-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--tp-line);
}

.tp-result-title {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0;
}

.tp-result-sub {
  font-size: .76rem;
  color: var(--muted-foreground);
  margin: 2px 0 0;
}

/* Separators are drawn as cell borders rather than as a 1px grid gap over a
   tinted backdrop: when the last row is partly filled, a gap-based grid
   paints the leftover cell as a solid block. Borders leave it empty. */
.tp-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  background: var(--tp-panel);
}

/* Each cell draws its own bottom rule rather than the container drawing
   one: when the grid wraps to two rows on a narrow panel, the container
   version leaves the rows visually merged. */
.tp-stat {
  padding: 13px 16px;
  border-right: 1px solid var(--tp-line);
  border-bottom: 1px solid var(--tp-line);
}

.tp-stat:last-child { border-right: none; }

.tp-stat-label {
  display: block;
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--light-text);
  margin-bottom: 4px;
}

.tp-stat-value {
  display: block;
  font-family: var(--font-display);
  font-size: .92rem;
  font-weight: 700;
  color: var(--foreground);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tp-banner {
  display: none;
  align-items: center;
  gap: 11px;
  margin: 16px 20px;
  padding: 13px 15px;
  border-radius: 12px;
  font-size: .84rem;
  line-height: 1.55;
  background: var(--tp-err-bg);
  border: 1px solid var(--tp-err-line);
  color: var(--tp-err);
}

.tp-banner.show { display: flex; }

.tp-empty {
  text-align: center;
  padding: 52px 26px;
}

.tp-empty-icon {
  width: 60px;
  height: 60px;
  margin: 0 auto 16px;
  display: grid;
  place-items: center;
  border-radius: 20px;
  background: var(--secondary);
  color: var(--muted-foreground);
}

.tp-empty-icon svg { width: 26px; height: 26px; }

.tp-empty h4 {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0 0 7px;
}

.tp-empty p {
  font-size: .85rem;
  line-height: 1.65;
  color: var(--muted-foreground);
  max-width: 360px;
  margin: 0 auto;
}

/* ═══════════════════════════════════════════════════════════════════
   3 · LOADER — a focused overlay, not an inline checklist that pushes
   the page around while it runs
   ═══════════════════════════════════════════════════════════════════ */
.tp-loader {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--tp-scrim);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.tp-loader.show { display: flex; }

.tp-loader-box {
  width: 100%;
  max-width: 420px;
  background: var(--tp-panel);
  border: 1px solid var(--tp-line);
  border-radius: 22px;
  box-shadow: 0 30px 70px -20px rgba(2, 6, 23, .5);
  padding: 30px 26px 24px;
  text-align: center;
  animation: tpRise .3s cubic-bezier(.16, 1, .3, 1) both;
}

@keyframes tpRise {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* Sweeping ring — the product's own scanner motif, drawn with a conic
   gradient (real CSS here, unlike the app's renderer). */
.tp-scanner {
  position: relative;
  width: 76px;
  height: 76px;
  margin: 0 auto 20px;
}

.tp-scanner::before,
.tp-scanner::after {
  content: '';
  position: absolute;
  border-radius: 50%;
}

.tp-scanner::before {
  inset: 0;
  background: conic-gradient(from 0deg, transparent 0deg, rgba(6, 182, 212, .12) 120deg, var(--cyan) 300deg, var(--purple) 355deg, transparent 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 5px));
  animation: tpSpin 1.5s linear infinite;
}

.tp-scanner::after {
  inset: 14px;
  background: var(--primary-soft);
  animation: tpPulse 2s ease-in-out infinite;
}

.tp-scanner-glyph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 1.4rem;
  z-index: 2;
}

@keyframes tpSpin { to { transform: rotate(360deg); } }
@keyframes tpPulse { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

.tp-loader-title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0 0 6px;
}

.tp-loader-step {
  font-size: .83rem;
  color: var(--muted-foreground);
  margin: 0 0 18px;
  min-height: 1.3em;
}

.tp-track {
  height: 6px;
  border-radius: 50px;
  background: var(--secondary);
  overflow: hidden;
}

.tp-track-fill {
  height: 100%;
  width: 0;
  border-radius: 50px;
  background: var(--gradient-scanner);
  transition: width .45s ease;
}

.tp-loader-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  font-size: .75rem;
  color: var(--light-text);
}

.tp-loader-cancel {
  font-size: .75rem;
  font-weight: 600;
  color: var(--muted-foreground);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.tp-loader-cancel:hover { color: var(--tp-err); }

/* ── Security check modal ─────────────────────────────────────────
   The tool page's own, so it does not depend on the homepage widget's
   overlay markup. Same job: hold the visitor while Turnstile renders. */
.tp-captcha {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: var(--tp-scrim);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: tp-fade .18s ease;
}

.tp-captcha[hidden] { display: none; }

.tp-captcha-box {
  width: 100%;
  max-width: 380px;
  padding: 26px 26px 20px;
  border: 1px solid var(--tp-line);
  border-radius: 18px;
  background: var(--card);
  box-shadow: var(--shadow-card);
  text-align: center;
}

.tp-captcha-title {
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 700;
  color: var(--foreground);
  margin: 0 0 4px;
}

.tp-captcha-sub {
  font-size: .78rem;
  line-height: 1.5;
  color: var(--muted-foreground);
  margin: 0 0 18px;
}

#vteCaptchaWidget {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 65px;
  margin-bottom: 12px;
}

@keyframes tp-fade { from { opacity: 0; } to { opacity: 1; } }

/* ═══════════════════════════════════════════════════════════════════
   4 · HOW IT WORKS — the scan track

   Not a row of numbered cards: one rail of stations driving a viewport
   that *performs* the step. Each stage's animations are keyed to
   `.is-active`, which the script re-applies on every switch so the
   sequence always plays from the top.
   ═══════════════════════════════════════════════════════════════════ */
.tp-section { padding: 72px 0; }
.tp-section--alt { background: var(--section-1); }

@media (max-width: 767px) { .tp-section { padding: 48px 0; } }

.tp-section-head {
  text-align: center;
  max-width: 620px;
  margin: 0 auto 40px;
}

.tp-section-head h2 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 800;
  letter-spacing: -.025em;
  color: var(--foreground);
  margin-bottom: 10px;
}

.tp-section-head p {
  font-size: .96rem;
  line-height: 1.7;
  color: var(--muted-foreground);
  margin: 0;
}

/* ── Layout ───────────────────────────────────────────────────────── */
.tp-flow {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  align-items: start;
  gap: 30px;
  max-width: 1080px;
  margin: 0 auto;
}

@media (max-width: 991px) {
  .tp-flow { grid-template-columns: 1fr; gap: 22px; }
}

/* ── The rail ─────────────────────────────────────────────────────── */
.tp-flow-rail {
  --tp-flow-gap: 6px;   /* also the distance a connector has to cross */
  --tp-flow-dot-y: 36px; /* station padding + half a dot = dot centre */
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--tp-flow-gap);
}

/* The connector is drawn per station rather than as one bar down the
   rail: a station's segment runs from its own dot centre into the gap
   above the next one, so it stays aligned however the copy wraps. The
   travelled part is a second segment that scales in when the station is
   behind us. */
.tp-flow-station::before,
.tp-flow-station::after {
  content: '';
  position: absolute;
  left: 38px;
  top: var(--tp-flow-dot-y);
  /* Runs all the way into the NEXT dot's centre; that dot is opaque and
     sits above, so the join reads as one continuous line. */
  bottom: calc(-1 * (var(--tp-flow-gap) + var(--tp-flow-dot-y)));
  width: 2px;
  border-radius: 2px;
}
.tp-flow-station::before { background: var(--tp-line); }
.tp-flow-station::after {
  background: var(--gradient-scanner);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform .45s cubic-bezier(.4, 0, .2, 1);
}
.tp-flow-station.is-done::after { transform: scaleY(1); }

.tp-flow-station:last-child::before,
.tp-flow-station:last-child::after { display: none; }

.tp-flow-station {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  width: 100%;
  text-align: left;
  padding: 14px 16px;
  border: 1px solid transparent;
  border-radius: 16px;
  background: transparent;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: background .25s ease, border-color .25s ease, box-shadow .25s ease;
}

.tp-flow-station:hover { background: var(--card); }

.tp-flow-station.is-active {
  background: var(--card);
  border-color: var(--tp-line);
  box-shadow: var(--shadow-card);
}

.tp-flow-station:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.tp-flow-dot {
  position: relative;
  z-index: 1;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  border: 1px solid var(--tp-line);
  background: var(--card);
  font-family: var(--font-display);
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .02em;
  color: var(--muted-foreground);
  transition: background .25s ease, color .25s ease, border-color .25s ease, box-shadow .25s ease;
}

.tp-flow-station.is-active .tp-flow-dot {
  background: var(--gradient-scanner);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 0 0 4px var(--primary-soft);
}

.tp-flow-station.is-done .tp-flow-dot {
  background: var(--primary-soft);
  border-color: transparent;
  color: var(--primary);
}

.tp-flow-tick { width: 17px; height: 17px; display: none; }
.tp-flow-station.is-done .tp-flow-tick { display: block; }
.tp-flow-station.is-done .tp-flow-idx { display: none; }

.tp-flow-text { display: block; padding-top: 2px; }

.tp-flow-title {
  display: block;
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 700;
  color: var(--foreground);
  margin-bottom: 5px;
}

.tp-flow-body {
  display: block;
  font-size: .84rem;
  line-height: 1.6;
  color: var(--muted-foreground);
}

/* ── The viewport ─────────────────────────────────────────────────── */
.tp-flow-screen {
  position: sticky;
  top: 96px;
  border: 1px solid var(--tp-line);
  border-radius: 20px;
  background: var(--card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

@media (max-width: 991px) {
  .tp-flow-screen { position: static; }
}

.tp-flow-chrome {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 14px;
  height: 40px;
  border-bottom: 1px solid var(--tp-line);
  background: var(--tp-panel-inset);
}

.tp-flow-lamps { display: inline-flex; gap: 6px; }
.tp-flow-lamps i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--tp-line);
}
.tp-flow-lamps i:first-child { background: var(--primary); opacity: .55; }

.tp-flow-chrome-label {
  flex: 1;
  min-width: 0;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tp-flow-live {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: .64rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--primary);
}
.tp-flow-live::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
  animation: tp-flow-pulse 1.6s ease-in-out infinite;
}

@keyframes tp-flow-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .35; transform: scale(.72); }
}

/* A faint instrument grid behind whatever the stage draws. */
.tp-flow-stages {
  position: relative;
  display: grid;
  align-content: center;   /* short stages sit centred rather than
                              hanging from the top of the viewport */
  min-height: 296px;
  padding: 24px;
  background-color: var(--tp-panel-inset);
  background-image:
      linear-gradient(var(--tp-flow-grid) 1px, transparent 1px),
      linear-gradient(90deg, var(--tp-flow-grid) 1px, transparent 1px);
  background-size: 26px 26px;
}

@media (max-width: 560px) {
  .tp-flow-stages { padding: 18px; min-height: 268px; }
}

.tp-flow-stage[hidden] { display: none; }

.tp-flow-stage.is-active { animation: tp-flow-in .4s ease both; }

@keyframes tp-flow-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ── Shared stage furniture ───────────────────────────────────────── */
.tv {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.tv-note {
  margin: 0;
  font-size: .76rem;
  line-height: 1.55;
  color: var(--muted-foreground);
}

.tv-kicker {
  font-size: .64rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}

/* ── 1 · a link typing itself in ──────────────────────────────────── */
.tv-field {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 13px 15px;
  border: 1px solid var(--tp-line);
  border-radius: 13px;
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
.tv-field svg { width: 17px; height: 17px; flex-shrink: 0; color: var(--muted-foreground); }

.tv-typed {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .82rem;
  color: var(--foreground);
}
.tp-flow-stage.is-active .tv-typed { animation: tv-type 2.1s steps(38) .25s both; }

@keyframes tv-type { to { max-width: 38ch; } }

.tv-caret {
  width: 2px;
  height: 17px;
  background: var(--primary);
  animation: tv-blink 1s steps(1) infinite;
}
@keyframes tv-blink { 50% { opacity: 0; } }

.tv-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.tv-chips span {
  padding: 5px 11px;
  border-radius: 50px;
  border: 1px solid var(--tp-line);
  background: var(--card);
  font-size: .72rem;
  font-weight: 600;
  color: var(--muted-foreground);
}

/* ── 2 · the caption track being swept ────────────────────────────── */
.tv-wave {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 92px;
  padding: 0 2px;
  border: 1px solid var(--tp-line);
  border-radius: 13px;
  background: var(--card);
  overflow: hidden;
}

.tv-wave i {
  flex: 1;
  height: var(--h);
  min-width: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--tp-line);
  transform-origin: bottom;
  transform: scaleY(.35);
}
.tp-flow-stage.is-active .tv-wave i {
  animation: tv-bar .5s ease both;
  animation-delay: calc(var(--i) * .035s);
}
@keyframes tv-bar {
  from { transform: scaleY(.15); }
  to   { transform: scaleY(1); background: var(--tp-wave-lit); }
}

.tv-sweep {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 44px;
  background: linear-gradient(90deg, transparent, var(--tp-sweep), transparent);
  border-right: 2px solid var(--cyan);
  opacity: 0;
}
.tp-flow-stage.is-active .tv-sweep { animation: tv-sweep 1.9s ease-in-out .2s both; }
@keyframes tv-sweep {
  0%   { left: -44px; opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}

.tv-tracks { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.tv-tracks li {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  border: 1px solid var(--tp-line);
  border-radius: 11px;
  background: var(--card);
  font-size: .78rem;
  color: var(--muted-foreground);
  opacity: 0;
}
.tp-flow-stage.is-active .tv-tracks li { animation: tv-fade .4s ease both; }
.tp-flow-stage.is-active .tv-tracks li:nth-child(1) { animation-delay: 1.5s; }
.tp-flow-stage.is-active .tv-tracks li:nth-child(2) { animation-delay: 1.7s; }
.tp-flow-stage.is-active .tv-tracks li:nth-child(3) { animation-delay: 1.9s; }

.tv-tracks li.is-hit { border-color: var(--primary); color: var(--foreground); }
.tv-tracks li em {
  margin-left: auto;
  font-style: normal;
  font-size: .68rem;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--primary);
}

.tv-cc {
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--primary-soft);
  font-size: .6rem;
  font-weight: 800;
  letter-spacing: .06em;
  color: var(--primary);
}

@keyframes tv-fade {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

/* ── 3 · transcript lines arriving ────────────────────────────────── */
.tv-lines { gap: 9px; }

.tv-lines p {
  display: flex;
  gap: 12px;
  margin: 0;
  padding: 10px 13px;
  border: 1px solid var(--tp-line);
  border-radius: 11px;
  background: var(--card);
  font-size: .8rem;
  line-height: 1.5;
  color: var(--foreground);
  opacity: 0;
}
.tp-flow-stage.is-active .tv-lines p {
  animation: tv-fade .4s ease both;
  animation-delay: calc(var(--i) * .28s + .15s);
}

.tv-lines time {
  flex-shrink: 0;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .74rem;
  color: var(--primary);
}

.tv-exports { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px; opacity: 0; }
.tp-flow-stage.is-active .tv-exports { animation: tv-fade .4s ease 1.35s both; }

.tv-ex {
  padding: 7px 13px;
  border-radius: 9px;
  border: 1px solid var(--tp-line);
  background: var(--card);
  font-size: .74rem;
  font-weight: 600;
  color: var(--muted-foreground);
}
.tv-ex--on {
  background: var(--gradient-primary);
  border-color: transparent;
  color: #fff;
}

/* ── 1 · the clip arriving ────────────────────────────────────────── */
.tv-file {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--tp-line);
  border-radius: 12px;
  background: var(--card);
}
.tv-file-name { font-size: .84rem; font-weight: 700; color: var(--foreground); }
.tv-file-meta { font-size: .74rem; color: var(--muted-foreground); }

/* Frames read as footage, so they stay on a dark plate in both themes. */
.tv-strip {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 7px;
}
.tv-strip i {
  height: 54px;
  border-radius: 8px;
  background:
      linear-gradient(135deg, rgba(255,255,255,.09), transparent 60%),
      linear-gradient(160deg, #1E293B, #0F172A);
  border: 1px solid rgba(148, 163, 184, .18);
  opacity: 0;
}
.tp-flow-stage.is-active .tv-strip i {
  animation: tv-frame .45s ease both;
  animation-delay: calc(var(--i) * .12s + .1s);
}
@keyframes tv-frame {
  from { opacity: 0; transform: translateX(14px) scale(.94); }
  to   { opacity: 1; transform: none; }
}

.tv-bar {
  height: 6px;
  border-radius: 6px;
  background: var(--tp-line);
  overflow: hidden;
}
.tv-bar i { display: block; height: 100%; width: 0; background: var(--gradient-scanner); }
.tp-flow-stage.is-active .tv-bar i { animation: tv-grow 1.7s ease-out .2s both; }
@keyframes tv-grow { to { width: 100%; } }

/* ── 2 · a frame reduced to 64 bits ───────────────────────────────── */
.tv-hash {
  display: grid;
  grid-template-columns: 176px minmax(0, 1fr);
  gap: 18px;
  align-items: center;
}
@media (max-width: 560px) {
  .tv-hash { grid-template-columns: 128px minmax(0, 1fr); gap: 14px; }
}

.tv-hash-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 3px;
  padding: 9px;
  border-radius: 12px;
  border: 1px solid rgba(148, 163, 184, .18);
  background: linear-gradient(160deg, #1E293B, #0F172A);
}
.tv-hash-grid i {
  aspect-ratio: 1;
  border-radius: 3px;
  background: rgba(148, 163, 184, .16);
  opacity: 0;
}
.tv-hash-grid i.on { background: var(--cyan); }
.tp-flow-stage.is-active .tv-hash-grid i {
  animation: tv-bit .3s ease both;
  animation-delay: calc(var(--i) * .016s + .1s);
}
@keyframes tv-bit {
  from { opacity: 0; transform: scale(.4); }
  to   { opacity: 1; transform: none; }
}

.tv-hash-side { display: grid; gap: 8px; }

.tv-hex {
  display: block;
  padding: 9px 11px;
  border-radius: 9px;
  border: 1px solid var(--tp-line);
  background: var(--card);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .76rem;
  letter-spacing: .04em;
  color: var(--foreground);
  overflow-x: auto;
  white-space: nowrap;
}

/* ── 3 · the sweep across platforms ───────────────────────────────── */
.tv-radar { align-items: center; gap: 16px; }

.tv-scope {
  position: relative;
  width: 118px;
  height: 118px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--tp-line);
  background: var(--card);
  overflow: hidden;
}
.tv-scope-ring {
  position: absolute;
  inset: 22px;
  border-radius: 50%;
  border: 1px solid var(--tp-line);
}
.tv-scope-ring--2 { inset: 44px; }

.tv-scope-sweep {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, var(--tp-sweep) 44deg, var(--cyan) 60deg, transparent 62deg);
}
.tp-flow-stage.is-active .tv-scope-sweep { animation: tv-spin 2.6s linear infinite; }
@keyframes tv-spin { to { transform: rotate(360deg); } }

.tv-plats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 7px;
}
.tv-plats span {
  padding: 6px 12px;
  border-radius: 50px;
  border: 1px solid var(--tp-line);
  background: var(--card);
  font-size: .74rem;
  font-weight: 600;
  color: var(--muted-foreground);
  opacity: 0;
}
.tp-flow-stage.is-active .tv-plats span {
  animation: tv-ping .5s ease both;
  animation-delay: calc(var(--i) * .13s + .2s);
}
@keyframes tv-ping {
  0%   { opacity: 0; transform: scale(.9); }
  55%  { opacity: 1; border-color: var(--primary); color: var(--primary); }
  100% { opacity: 1; transform: none; }
}

/* ── 4 · results, ordered ─────────────────────────────────────────── */
.tv-rank { gap: 10px; }

.tv-row {
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--tp-line);
  border-radius: 12px;
  background: var(--card);
  opacity: 0;
}
.tp-flow-stage.is-active .tv-row {
  animation: tv-fade .42s ease both;
  animation-delay: calc(var(--i) * .16s + .12s);
}

.tv-thumb {
  height: 36px;
  border-radius: 7px;
  background:
      linear-gradient(135deg, rgba(255,255,255,.09), transparent 60%),
      linear-gradient(160deg, #1E293B, #0F172A);
  border: 1px solid rgba(148, 163, 184, .18);
}

.tv-row-main { display: grid; gap: 7px; min-width: 0; }

.tv-row-label {
  font-size: .78rem;
  font-weight: 600;
  color: var(--foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Match strength is cyan at every tier — green would read as a verdict
   that a similarity number does not make. */
.tv-meter {
  display: block;
  height: 5px;
  border-radius: 5px;
  background: var(--tp-line);
  overflow: hidden;
}
.tv-meter i { display: block; height: 100%; width: 0; background: var(--gradient-scanner); }
.tp-flow-stage.is-active .tv-meter i {
  animation: tv-meter .8s cubic-bezier(.4, 0, .2, 1) both;
  animation-delay: calc(var(--i) * .16s + .3s);
}
@keyframes tv-meter { to { width: var(--w); } }

.tv-pct {
  font-family: var(--font-display);
  font-size: .82rem;
  font-weight: 800;
  color: var(--tp-match);
}


/* ═══════════════════════════════════════════════════════════════════
   5 · FAQ — the site's accordion

   Same component the homepage FAQ is: a stack of cards, the question with
   a round +/− on the right that fills with the primary gradient when the
   card is open, one open at a time. Written here in the tool pages' own
   classes so the two can be changed independently.
   ═══════════════════════════════════════════════════════════════════ */
.tp-kicker {
  display: block;
  margin-bottom: 8px;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--primary);
}

.tp-faq {
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tp-faq-item {
  background: var(--card);
  border: 1px solid var(--tp-line);
  border-radius: 24px;
  transition: border-color .2s ease, box-shadow .2s ease;
}

.tp-faq-item.open {
  border-color: var(--primary);
  box-shadow: var(--shadow-card);
}

.tp-faq-q {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 24px;
  text-align: left;
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
  color: var(--foreground);
}

.tp-faq-q:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: -4px;
  border-radius: 24px;
}

/* The circle carries the state: grey and a plus while closed, the primary
   gradient and a minus while open. */
.tp-faq-ico {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--secondary);
  color: var(--muted-foreground);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
  transition: background .2s ease, color .2s ease;
}

.tp-faq-item.open .tp-faq-ico {
  background: var(--gradient-primary);
  color: #fff;
}

.tp-faq-minus { display: none; }
.tp-faq-item.open .tp-faq-plus  { display: none; }
.tp-faq-item.open .tp-faq-minus { display: block; }

/* Animated on grid rows rather than max-height: an answer of any length
   opens fully instead of being clipped at a guessed height. */
.tp-faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s ease;
}

.tp-faq-a > div { overflow: hidden; }

.tp-faq-item.open .tp-faq-a { grid-template-rows: 1fr; }

.tp-faq-a-body {
  padding: 0 24px 24px;
  font-size: .9rem;
  line-height: 1.75;
  color: var(--muted-foreground);
}

.tp-faq-a-body > :first-child { margin-top: 0; }
.tp-faq-a-body > :last-child  { margin-bottom: 0; }

.tp-faq-a a { color: var(--primary); text-decoration: underline; text-underline-offset: 3px; }

/* Admin-authored rich text inside an answer — a compact version of the
   article (.tp-prose) styling, which in turn matches the blog body.
   list-style is re-declared because styles.css resets it. */
.tp-faq-a-body p { margin: 0 0 12px; }
.tp-faq-a-body strong, .tp-faq-a-body b { font-weight: 700; color: var(--foreground); }
.tp-faq-a-body em, .tp-faq-a-body i { font-style: italic; }
.tp-faq-a-body ul, .tp-faq-a-body ol { margin: 0 0 12px; padding-left: 0; list-style: none; }
.tp-faq-a-body ul > li, .tp-faq-a-body ol > li { position: relative; padding-left: 20px; margin-bottom: 6px; }
.tp-faq-a-body ul > li::before {
  content: ''; position: absolute; left: 3px; top: 9px;
  width: 6px; height: 6px; border-radius: 50%;
  background: linear-gradient(135deg, var(--primary), var(--cyan));
}
.tp-faq-a-body ul > li:only-child,
.tp-faq-a-body ol > li:only-child { padding-left: 0; }
.tp-faq-a-body ul > li:only-child::before,
.tp-faq-a-body ol > li:only-child::before { display: none; }
.tp-faq-a-body ol { counter-reset: tp-faq-ol; }
.tp-faq-a-body ol > li { counter-increment: tp-faq-ol; }
.tp-faq-a-body ol > li::before {
  content: counter(tp-faq-ol) '.';
  position: absolute; left: 0; top: 0;
  font-size: .78rem; font-weight: 800; color: var(--primary);
}
.tp-faq-a-body :not(pre) > code {
  background: color-mix(in srgb, var(--primary) 8%, var(--muted));
  border: 1px solid color-mix(in srgb, var(--primary) 18%, transparent);
  border-radius: 5px; padding: 1px 5px;
  font-size: .86em; color: var(--primary);
  font-family: 'Fira Code', Consolas, ui-monospace, monospace;
}

@media (max-width: 560px) {
  .tp-faq-q { padding: 18px; font-size: .94rem; }
  .tp-faq-a-body { padding: 0 18px 18px; }
}


/* ═══════════════════════════════════════════════════════════════════
   6 · MORE TOOLS + CLOSING CTA
   ═══════════════════════════════════════════════════════════════════ */
.tp-more {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: 14px;
}

.tp-more-card {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 17px 18px;
  border-radius: 16px;
  background: var(--card);
  border: 1px solid var(--tp-line);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}

.tp-more-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card);
  border-color: var(--primary);
}

.tp-more-icon {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--primary-soft);
  font-size: 1.05rem;
}

.tp-more-text { min-width: 0; }

.tp-more-text strong {
  display: block;
  font-family: var(--font-display);
  font-size: .89rem;
  font-weight: 700;
  color: var(--foreground);
}

.tp-more-text span {
  display: block;
  font-size: .77rem;
  color: var(--muted-foreground);
  margin-top: 2px;
}

.tp-cta {
  position: relative;
  overflow: hidden;
  border-radius: 26px;
  padding: 52px 40px;
  text-align: center;
  background: var(--gradient-primary);
  color: #fff;
}

.tp-cta::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
      radial-gradient(ellipse 60% 70% at 15% 10%, rgba(6, 182, 212, .35) 0%, transparent 60%),
      radial-gradient(ellipse 50% 60% at 90% 90%, rgba(139, 92, 246, .3) 0%, transparent 60%);
  pointer-events: none;
}

.tp-cta > * { position: relative; z-index: 1; }

.tp-cta h2 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 800;
  letter-spacing: -.025em;
  margin-bottom: 12px;
  color: #fff;
}

.tp-cta p {
  font-size: .98rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, .82);
  max-width: 520px;
  margin: 0 auto 26px;
}

.tp-cta-btns {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.tp-cta-btns .tp-btn { width: auto; }

.tp-btn--light {
  background: #fff;
  color: var(--primary);
  box-shadow: 0 10px 26px -12px rgba(2, 6, 23, .6);
}

.tp-btn--light:hover { transform: translateY(-2px); }

.tp-btn--outline {
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .35);
  color: #fff;
}

.tp-btn--outline:hover { background: rgba(255, 255, 255, .2); }

@media (max-width: 600px) {
  .tp-cta { padding: 38px 22px; border-radius: 20px; }
  .tp-cta-btns .tp-btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .tp-scanner::before,
  .tp-scanner::after { animation: none; }
  .tp-loader-box { animation: none; }
  .tp-flow-station:hover,
  .tp-more-card:hover,
  .tp-btn:hover { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════
   7 · ARTICLE — the tool's long-form content block

   Admin-authored rich text, so the styling has to cover whatever a
   rich-text editor emits: headings, paragraphs, lists, links, quotes,
   inline code and tables. Measured in a reading column, not the full
   page width.
   ═══════════════════════════════════════════════════════════════════ */
/* Matches the blog article body (.post-body in blog/show.blade.php) so an
   admin-authored tool article reads exactly like a blog post: accent-bar
   headings, gradient bullet lists, soft quotes, code, tables and images.
   Scoped to .tp-prose; list-style is re-declared because styles.css resets it. */
.tp-prose {
  max-width: 820px;
  margin: 0 auto;
  font-size: 1.0625rem;
  line-height: 1.875;
  color: var(--foreground);
  word-break: break-word;
}

.tp-prose > :first-child { margin-top: 0; }
.tp-prose > :last-child  { margin-bottom: 0; }

/* Headings — gradient accent bar on the left, like the blog */
.tp-prose h1,
.tp-prose h2,
.tp-prose h3 {
  position: relative;
  font-family: var(--font-display);
  color: var(--foreground);
  scroll-margin-top: 100px;
}
.tp-prose h1::before,
.tp-prose h2::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 2px;
  background: var(--gradient-scanner);
}
.tp-prose h1 {
  font-size: 1.875rem; font-weight: 800; line-height: 1.2;
  letter-spacing: -.02em; margin: 52px 0 16px; padding-left: 18px;
}
.tp-prose h1::before { width: 5px; }
.tp-prose h2 {
  font-size: 1.5rem; font-weight: 800; line-height: 1.25;
  letter-spacing: -.015em; margin: 48px 0 14px; padding-left: 16px;
}
.tp-prose h2::before { width: 4px; }
/* Small headings stay plain — the accent bar is for section headings only. */
.tp-prose h3 {
  font-size: 1.175rem; font-weight: 700; line-height: 1.3;
  margin: 32px 0 10px;
}
.tp-prose h4 {
  font-family: var(--font-display);
  font-size: 1rem; font-weight: 700;
  color: var(--foreground); margin: 26px 0 8px;
}
.tp-prose h5 {
  font-size: .9375rem; font-weight: 700;
  color: var(--muted-foreground); margin: 20px 0 6px;
  text-transform: uppercase; letter-spacing: .04em;
}
.tp-prose h6 {
  font-size: .875rem; font-weight: 600; font-style: italic;
  color: var(--muted-foreground); margin: 16px 0 6px;
}

/* Paragraphs */
.tp-prose p { margin: 0 0 20px; }

/* Links */
.tp-prose a {
  color: var(--primary); font-weight: 500;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--primary) 30%, transparent);
  text-underline-offset: 3px;
  transition: color .15s;
}
.tp-prose a:hover { color: var(--cyan); }

/* Inline */
.tp-prose strong, .tp-prose b { font-weight: 700; color: var(--foreground); }
.tp-prose em, .tp-prose i { font-style: italic; }
.tp-prose mark {
  background: color-mix(in srgb, var(--cyan) 18%, transparent);
  color: var(--foreground); padding: 1px 4px; border-radius: 3px;
}
.tp-prose small { font-size: .85em; color: var(--muted-foreground); }

/* Lists — gradient dots and bold numbers, like the blog */
.tp-prose ul, .tp-prose ol { margin: 0 0 20px; padding-left: 0; list-style: none; }
.tp-prose ul > li, .tp-prose ol > li { position: relative; padding-left: 24px; margin-bottom: 8px; line-height: 1.75; }
.tp-prose ul > li::before {
  content: ''; position: absolute; left: 4px; top: 10px;
  width: 8px; height: 8px; border-radius: 50%;
  background: linear-gradient(135deg, var(--primary), var(--cyan));
}
.tp-prose ol { counter-reset: tp-ol; }
.tp-prose ol > li { counter-increment: tp-ol; }
.tp-prose ol > li::before {
  content: counter(tp-ol) '.';
  position: absolute; left: 0; top: 0;
  font-size: .8rem; font-weight: 800; color: var(--primary);
  min-width: 18px;
}
.tp-prose ul ul, .tp-prose ol ol,
.tp-prose ul ol, .tp-prose ol ul { margin: 6px 0 6px 12px; }
.tp-prose ul ul > li::before { width: 5px; height: 5px; left: 5px; top: 12px; background: var(--muted-foreground); }

/* A one-item list is just a sentence: no dot, no number, no indent. */
.tp-prose ul > li:only-child,
.tp-prose ol > li:only-child { padding-left: 0; }
.tp-prose ul > li:only-child::before,
.tp-prose ol > li:only-child::before { display: none; }

/* Blockquote */
.tp-prose blockquote {
  margin: 32px 0;
  padding: 20px 24px 20px 20px;
  border-left: 4px solid var(--primary);
  background: var(--primary-soft);
  border-radius: 0 12px 12px 0;
  font-style: italic;
  color: var(--foreground);
  line-height: 1.8;
}
.tp-prose blockquote p { margin-bottom: 0; }

/* Code */
.tp-prose :not(pre) > code {
  background: color-mix(in srgb, var(--primary) 8%, var(--muted));
  border: 1px solid color-mix(in srgb, var(--primary) 18%, transparent);
  border-radius: 5px; padding: 2px 6px;
  font-size: .875em; color: var(--primary);
  font-family: 'Fira Code', Consolas, ui-monospace, monospace; font-weight: 500;
}
.tp-prose pre {
  background: #0d1117; border: 1px solid #21262d;
  border-radius: 14px; padding: 16px 20px;
  overflow-x: auto; margin: 24px 0;
}
.tp-prose pre code { background: none; border: none; padding: 0; color: #e6edf3; font-size: .875rem; line-height: 1.75; }

/* Images */
.tp-prose img {
  display: block;
  max-width: min(100%, 860px);
  height: auto;
  margin: 24px auto;
  border-radius: 12px;
}

/* Tables — a wide table scrolls inside itself, never widens the page */
.tp-prose table {
  display: block;
  width: 100%;
  overflow-x: auto;
  border-collapse: separate;
  border-spacing: 0;
  margin: 24px 0;
  font-size: .92rem;
  border: 1px solid var(--border);
  border-radius: 14px;
}
.tp-prose th {
  padding: 14px 18px; text-align: left;
  font-family: var(--font-display, inherit);
  font-weight: 700; font-size: .76rem;
  text-transform: uppercase; letter-spacing: .09em;
  color: #fff; white-space: nowrap;
  background: var(--gradient-primary);
}
.tp-prose td {
  padding: 13px 18px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  color: var(--foreground); vertical-align: top; line-height: 1.65;
}
.tp-prose tbody tr:last-child td { border-bottom: none; }
.tp-prose tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--muted) 45%, transparent); }

/* Horizontal rule */
.tp-prose hr {
  border: none; height: 1px; margin: 40px 0;
  background: linear-gradient(90deg, transparent, var(--border), transparent);
}

@media (max-width: 640px) {
  .tp-prose { font-size: 1rem; line-height: 1.8; }
  .tp-prose h2 { font-size: 1.3rem; margin-top: 36px; }
  .tp-prose h3 { font-size: 1.1rem; }
}

