Elastic lucene lp (#2013)

This commit is contained in:
trean
2025-12-02 20:59:21 +01:00
committed by GitHub
parent 2eb4cc3d79
commit 370bebd6a2
50 changed files with 1425 additions and 2 deletions
@@ -0,0 +1,13 @@
---
title: "Building production vector search shouldn’t be so hard."
description: "We asked our users building vector search why they moved to Qdrant
from Elastic, Opensearch or another Lucene-based search engine."
url: /lp/lucene
build:
render: always
cascade:
- build:
list: local
publishResources: false
render: never
---
@@ -0,0 +1,9 @@
---
title: Worried you'll <b>collapse</b> under real production load?
description: <p>Qdrant is the AI retrieval engine built to handle dense, hybrid, and AI-native workloads at a size and performance that legacy systems were never built for.</p><p>No JVM garbage-collection pauses, no 3 a.m. reindex job.</p>
image:
src: /img/elastic-lucene/callout.png
alt: Preview
sitemapExclude: true
---
@@ -0,0 +1,30 @@
---
title: Check Out Our Most Powerful Features
features:
- id: 0
icon:
src: /icons/outline/search-blue.svg
alt: Hybrid Search icon
description: Build a search system by combining different search methods to improve retrieval quality
link:
text: Read about Hybrid Search
url: /articles/hybrid-search/
- id: 1
icon:
src: /icons/outline/slow-blue.svg
alt: Multivector Support icon
description: Avoid RAM overhead, slow inserts, and wasted compute by effectively using multivector representations.
link:
text: Read about Multivector Support
url: /documentation/advanced-tutorials/using-multivector-representations/
- id: 2
icon:
src: /icons/outline/multitenancy-blue.svg
alt: Multitenancy icon
description: Properly use a multitenant architecture to scale your product.
link:
text: Read about Multitenancy
url: /articles/multitenancy/
sitemapExclude: true
---
@@ -0,0 +1,14 @@
---
title: We'll Help You Benchmark
content: <p>If you have a production use case, run a side-by-side benchmark on your own index to measure latency, RAM footprint, and throughput before you decide.</p><p>Our team of Solution Architects will help you test feasibility, latency, and cost.</p><p>No strings attached, no commitment. Performance that speaks for itself.</p>
image:
src: /img/elastic-lucene/astronaut-holding-cube.png
form:
fallback:
text: "There is a form here, but unfortunately it is blocked on your side. Please check your browser settings, or try with a different browser."
# browsers also block external forms, so check if content is available
# on the fallback page before showing the button
# link: /
# buttonText: Click Here
sitemapExclude: true
---
@@ -0,0 +1,15 @@
---
title: Build with Qdrant Cloud
description: |
Spin up a managed cluster in minutes, optimized for vector-heavy, real-time AI workloads.
No more overprovisioning. No more reindexing. No more latency surprises.
button:
url: https://cloud.qdrant.io/
text: Try Now
target: blank
image:
src: /img/database.svg
alt: Qdrant Cloud
sitemapExclude: true
---
@@ -0,0 +1,21 @@
---
title: Building production vector search shouldn’t be so hard.
description: "We asked our users building vector search why they moved to Qdrant from Elastic, Opensearch or another Lucene-based search engine. Here’s what they tell us:"
quotes:
- Unacceptably slow queries with vector search
- Endless indexing jobs
- Overspending on over-provisioned memory
- Brittle hybrid search
closingText: Lucene-based architectures just aren't built for scaling vector search.
startFree:
text: Get Started
url: https://cloud.qdrant.io/signup
learnMore:
text: Contact Us
url: /contact-us/
image:
src: /img/elastic-lucene/astronaut-broken-elastic.png
alt: Retrieval Augmented Generation
sitemapExclude: true
---
@@ -0,0 +1,30 @@
---
title: "Learn How To Use Top Features with<br> Hands-On Lessons"
lessons:
- title: Out of the Box Hybrid Search
description: Meet every searcher's needs with hybrid search in Qdrant. Combine dense and sparse vectors, apply Reciprocal Rank Fusion (RRF), and build complex multi-stage pipelines, all in a single call with the Universal Query API.
link:
text: Learn how to fuse precision and meaning in your search
url: /course/essentials/day-3/hybrid-search/
imageLeft:
src: /img/elastic-lucene/preview-empty-part.png
imageMiddle:
src: /img/elastic-lucene/hybrid-search-preview.png
alt: Hybrid Search Course
imageRight:
src: /img/elastic-lucene/preview-day4-part.png
- title: Multivector Mastery
description: Qdrant supports token-level precision with multivector fields for ColBERT-style late interaction. Compare query and document tokens via MaxSim scoring for sharper relevance, ideal for complex text and visual documents with ColPali.
link:
text: Learn how to use multivectors in your next Qdrant collection
url: /course/essentials/day-5/colbert-multivectors/
imageLeft:
src: /img/elastic-lucene/preview-empty-part.png
imageMiddle:
src: /img/elastic-lucene/multivector-preview.png
alt: Hybrid Search Course
imageRight:
src: /img/elastic-lucene/preview-day6-part.png
sitemapExclude: true
---
@@ -0,0 +1,17 @@
---
title: Move Beyond Elastic Without Rebuilding
headerTitle: |
Ready to Build
Vector Search the Right Way?
subtitle: Seamlessly Bring Your Data to Qdrant with our Migration Tool.
description: Migrating from Elastic's Lucene-based stack doesn't have to mean starting over. Our Migration Tool lets you stream your existing vector data directly into Qdrant, live, fast, and with zero downtime. It works even while data is being inserted, supports reconfiguration, and eliminates the headaches of reindexing or overprovisioning.
descriptionSecond: Modernize your retrieval layer in hours, not weeks.
image:
src: /img/elastic-lucene/migration-tool-illustration.png
alt: Migration Tool Illustration
button:
text: Migrate Now
url: /documentation/database-tutorials/migration/
sitemapExclude: true
---
@@ -0,0 +1,30 @@
---
title: Qdrant Can Optimize
features:
- id: 0
icon:
src: /icons/outline/rocket-blue.svg
alt: Rocket
title: Latency
description: Build lightning fast, massive AI applications on our Rust powered, native vector search engine.
- id: 1
icon:
src: /icons/outline/time-blue.svg
alt: Stopwatch
title: Ingestion Speed
description: Qdrant ingests millions of vectors/minute while staying queryable.
- id: 2
icon:
src: /icons/outline/server-rack-blue.svg
alt: Server rack
title: Memory Provisioning
description: Stop over provisioning RAM to avoid failed index merges. Using Rust, Qdrant gives you more control over memory.
- id: 3
icon:
src: /icons/outline/scale-blue.svg
alt: Scale
title: Scaling
description: Continue to meet your search KPIs at scale for speed, accuracy and cost with our vector-first features (e.g. native multi-vector).
sitemapExclude: true
---
@@ -0,0 +1,15 @@
---
title: Why Teams Build Qdrant Alongside Elastic
description: You don't have to rip anything out.
descriptionSecond: Most teams start by adding Qdrant next to their existing stack to handle new dense or hybrid workloads … the ones Elastic can't keep up with.
testimonial:
logo:
src: /img/elastic-lucene/sprinklr.svg
alt: Sprinklr Logo
text: Using Qdrant, Sprinklr achieved 90% faster write time, 80% faster latency, 2.5x higher RPS than with Elastic.
link:
text: Read More
url: /blog/case-study-sprinklr/
sitemapExclude: true
---
@@ -6,4 +6,8 @@
pointer-events: none;
}
.grey-bg {
background-color: $neutral-94;
}
// add more utility classes here
@@ -64,6 +64,7 @@
@import 'partials/use-cases-vector-cases';
@import 'partials/use-cases-vector-integrations';
@import 'partials/case-study';
@import 'partials/callout';
@import 'partials/advanced-search-use-cases';
@import 'partials/recommendations-api';
@import 'partials/retrieval-augmented-generation-guide';
@@ -137,3 +138,4 @@
@import 'partials/edge-beta-form';
@import 'partials/edge-beta-faq';
@import 'partials/edge-beta-get-started';
@import 'partials/elastic-lucene/index';
@@ -0,0 +1,106 @@
@use '../helpers/functions' as *;
.callout {
display: flex;
padding: pxToRem(80);
background-color: $neutral-10;
border-radius: $spacer;
overflow: hidden;
position: relative;
background-image: url('/img/texture.png');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
&__lights-overlay {
position: absolute;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: pxToRem(376);
background-image: url('/img/blurred/blurred-light-24.png'),
url('/img/blurred/blurred-light-25.png'),
url('/img/blurred/blurred-light-26.png');
background-position: top left, bottom left, bottom right;
background-size: contain, contain, contain;
background-repeat: no-repeat;
z-index: 1;
}
&__square-grid-overlay {
position: absolute;
left: 0;
top: 0;
right: -20%;
bottom: -9px;
display: flex;
background-image: linear-gradient(270deg, rgba(11, 15, 25, 0.00) 26.48%, #0B0F19 87.55%), url('/img/square-grid-black.svg');
background-size: cover, contain;
background-position: center right, center right;
background-repeat: no-repeat, no-repeat;
z-index: 0;
}
&__illustration {
display: none;
position: absolute;
right: -20%;
top: pxToRem(34);
bottom: pxToRem(17);
width: 100%;
background-size: contain;
background-position: center right;
background-repeat: no-repeat;
@include media-breakpoint-up(lg) {
display: block;
}
@include media-breakpoint-up(xl) {
right: 0;
}
}
&__content {
position: relative;
padding: 0;
max-width: 100%;
z-index: 2;
display: flex;
flex-direction: column;
gap: pxToRem(32);
@include media-breakpoint-up(lg) {
max-width: pxToRem(560);
}
}
&__title {
font-size: pxToRem(40);
line-height: pxToRem(50);
font-weight: 700;
color: $neutral-98;
margin-bottom: 0;
b {
color: $primary-50;
}
}
&__description {
font-size: pxToRem(20);
line-height: pxToRem(30);
font-weight: 500;
color: $neutral-70;
margin-bottom: 0;
b {
color: $neutral-98;
}
p {
margin-bottom: pxToRem(32);
}
p:last-of-type {
margin-bottom: 0;
}
}
}
@@ -24,7 +24,7 @@
padding-left: pxToRem(20);
padding-right: pxToRem(20);
background: linear-gradient(180deg, #090d19, rgba(9, 13, 25, 0));
z-index: 1;
z-index: 10;
&__trigger {
outline: none;
@@ -0,0 +1,82 @@
.elastic-lucene-form {
padding-top: pxToRem(96);
padding-bottom: pxToRem(340);
background-color: $neutral-10;
overflow: hidden;
position: relative;
@include media-breakpoint-up(lg) {
padding-bottom: pxToRem(96);
}
&__overlay-bottom {
background-image: url('/img/blurred/blurred-light-4.png');
transform: scale(-1, -1);
background-position: bottom right;
background-size: contain;
background-repeat: no-repeat;
width: 63rem;
height: 17rem;
}
&__illustration {
position: absolute;
height: pxToRem(300);
left: 0;
width: 100%;
bottom: 0;
background-size: contain;
background-repeat: no-repeat;
background-position: center bottom;
@include media-breakpoint-up(lg) {
height: 100%;
max-height: pxToRem(600);
width: 48%;
background-position: right bottom;
}
}
&__content {
display: flex;
flex-direction: column;
gap: $spacer * 2.5;
}
&__title {
font-size: $h4-font-size;
line-height: pxToRem(50);
font-weight: 700;
color: $neutral-98;
margin-bottom: 0;
}
&__description p {
font-size: $font-size-md;
line-height: pxToRem(24);
font-weight: 500;
color: $neutral-70;
margin-bottom: $spacer * 0.5;
&:last-of-type {
margin-bottom: 0;
}
}
}
.luceneForm {
label {
color: $neutral-98;
}
select[name='country'] {
width: 100% !important;
margin-right: 0;
}
.hs-form-checkbox {
list-style: none;
}
.hs-error-msg {
color: $error-50;
}
}
@@ -0,0 +1,121 @@
.elastic-lucene-hero {
background-color: $neutral-10;
padding: pxToRem(80) 0 pxToRem(440);
position: relative;
overflow: hidden;
@include media-breakpoint-up(md) {
padding-bottom: pxToRem(120);
}
&__illustration {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: pxToRem(400);
background-image: var(--bg-image), url('/img/elastic-lucene/astronaut-light.png');
background-position:
bottom center,
bottom center;
background-repeat: no-repeat, no-repeat;
background-size: contain, contain;
z-index: 1;
@include media-breakpoint-up(md) {
display: block;
left: 50%;
right: pxToRem(-144);
background-position:
bottom left,
bottom left;
height: pxToRem(532);
}
}
&__content {
display: flex;
flex-direction: column;
gap: $spacer * 2;
z-index: 4;
}
&__title {
font-size: $h3-font-size;
line-height: pxToRem(58);
font-weight: 700;
color: $neutral-98;
margin-bottom: 0;
}
&__description {
font-size: $font-size-l;
line-height: pxToRem(27);
font-weight: 500;
color: $neutral-70;
margin-bottom: 0;
@include media-breakpoint-up(md) {
padding-right: pxToRem(144);
}
@include media-breakpoint-up(lg) {
padding-right: 0;
}
}
&__quotes {
position: relative;
padding-left: $spacer * 2;
&-line {
position: absolute;
left: 0;
top: 0;
height: pxToRem(85);
width: pxToRem(1);
}
&-list {
font-size: $font-size-s;
line-height: pxToRem(21);
font-weight: 400;
color: $neutral-70;
p {
margin-bottom: 0;
}
}
}
&__closing {
font-size: $font-size-l;
line-height: pxToRem(27);
font-weight: 500;
color: $neutral-70;
margin-bottom: 0;
@include media-breakpoint-up(md) {
padding-right: pxToRem(160);
}
@include media-breakpoint-up(lg) {
padding-right: 0;
}
}
&__overlay {
position: absolute;
right: 0;
left: 0;
bottom: -6px;
width: 100%;
height: 300px;
background-image: url('/img/elastic-lucene/lights.svg');
background-repeat: repeat-x;
background-position: center;
background-size: cover;
filter: blur(6px);
z-index: 3;
}
}
@@ -0,0 +1,6 @@
@use '../../helpers/functions' as *;
@use '../../mixins/get-started-small' as get-started-small;
@import 'hero';
@import 'outlined-card-group';
@import 'split-section';
@import 'form';
@@ -0,0 +1,195 @@
.outlined-card-group {
&__cards {
border: 1px solid $neutral-90;
border-radius: pxToRem(32);
padding: pxToRem(32);
gap: $spacer;
}
&__header-card {
padding: $spacer * 2.5;
border-radius: pxToRem(16);
text-align: center;
}
&__header-title {
font-size: pxToRem(40);
line-height: pxToRem(50);
font-weight: 700;
}
&__card {
padding: pxToRem(24);
border-radius: pxToRem(16);
display: flex;
flex-direction: column;
max-width: 100%;
min-height: auto;
overflow: hidden;
&--jumbo {
padding: $spacer * 2.5;
}
}
&__cards .row > [class*='col-'] > &__card {
height: 100%;
}
&__content {
display: flex;
flex-direction: column;
gap: $spacer * 1.5;
padding-left: $spacer * 1.5;
padding-right: $spacer * 1.5;
&--jumbo {
gap: $spacer * 2;
margin-top: 0;
padding-left: 0;
padding-right: 0;
@include media-breakpoint-up(lg) {
flex-direction: row;
align-items: flex-end;
gap: $spacer * 4;
}
}
}
&__content--jumbo &__text {
@include media-breakpoint-up(lg) {
flex: 1 1 auto;
max-width: pxToRem(468);
}
}
&__text {
display: flex;
flex-direction: column;
gap: $spacer;
}
&__icon {
width: pxToRem(24);
height: pxToRem(24);
}
&__title {
font-size: pxToRem(24);
line-height: pxToRem(34);
font-weight: 700;
color: $neutral-20;
margin-bottom: 0;
&--small {
font-size: pxToRem(20);
}
&--large {
font-size: pxToRem(40);
line-height: pxToRem(50);
}
}
&__subtitle {
font-size: pxToRem(16);
line-height: pxToRem(24);
font-weight: 700;
color: $neutral-20;
margin-bottom: 0;
}
&__description {
font-size: pxToRem(16);
line-height: pxToRem(24);
font-weight: 500;
color: $neutral-20;
margin-bottom: 0;
&--small {
font-size: pxToRem(14);
line-height: pxToRem(21);
font-weight: 400;
}
}
&__illustration {
width: 100%;
align-self: center;
img {
width: 100%;
height: auto;
display: block;
}
@include media-breakpoint-up(lg) {
flex: 0 0 auto;
width: auto;
max-width: 50%;
}
}
&__button {
align-self: flex-start;
margin-top: $spacer * 0.5;
}
&__link {
width: auto;
align-self: flex-start;
font-size: pxToRem(16);
}
}
.og-card {
&__images-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
margin-top: pxToRem(32);
margin-left: -$spacer * 1.5;
margin-right: -$spacer * 1.5;
margin-bottom: pxToRem(40);
img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
transition: transform 0.3s ease;
}
& > div:first-child {
width: 16.9%;
}
& > div:nth-child(2) {
width: 60%;
aspect-ratio: 103/58;
overflow: hidden;
border-radius: pxToRem(8);
a {
display: block;
width: 100%;
height: 100%;
transition:
transform 0.3s ease,
opacity 0.3s ease;
&:hover {
opacity: 0.9;
img {
transform: scale(1.02);
}
}
}
}
& > div:last-child {
width: 16.9%;
}
}
}
@@ -0,0 +1,73 @@
.split-section {
&__content {
display: flex;
flex-direction: column;
gap: $spacer;
}
&__title {
font-size: pxToRem(40);
line-height: pxToRem(50);
font-weight: 700;
color: $neutral-20;
margin-bottom: 0;
}
&__description {
display: flex;
flex-direction: column;
gap: $spacer;
}
&__description > p {
font-size: pxToRem(16);
line-height: pxToRem(24);
font-weight: 500;
color: $neutral-30;
margin-bottom: 0;
}
&__testimonial-card {
display: flex;
flex-direction: column;
gap: $spacer * 1.5;
padding: $spacer * 2.5;
background-color: $neutral-98;
border: 1px solid $neutral-90;
border-radius: $spacer;
}
&__logo-container {
display: flex;
align-items: center;
justify-content: center;
padding: pxToRem(18) pxToRem(20);
background-color: $neutral-98;
border: 1px solid $neutral-90;
border-radius: pxToRem(12);
width: pxToRem(160);
height: pxToRem(64);
}
&__logo {
width: pxToRem(120);
}
&__testimonial-text {
margin-bottom: 0;
font-weight: 700;
font-size: pxToRem(18);
line-height: pxToRem(27);
color: $neutral-20;
}
&__link-wrapper {
display: flex;
align-items: center;
gap: pxToRem(2);
}
&__link {
color: $primary-50;
}
}
@@ -0,0 +1,35 @@
{{ define "main" }}
{{ partial "site-header" . }}
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-hero") }}
{{ partial "elastic-lucene/hero" . }}
{{ end }}
{{ $class := "rag-use-cases" }}
<section class="grey-bg pt-6 pb-5">
<div class="container">
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-callout.md") }}
{{ partial "callout" . }}
{{ end }}
</div>
</section>
{{ partial "elastic-lucene/optimization" . }}
{{ partial "elastic-lucene/features" . }}
{{ partial "elastic-lucene/why" . }}
{{ partial "elastic-lucene/migration" . }}
{{ partial "elastic-lucene/form" . }}
{{ partial "elastic-lucene/lessons" . }}
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-get-started") }}
{{ partial "get-started-small" (dict "context" . "class" "get-started-small-database") }}
{{ end }}
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-form") }}
{{ partial "elastic-lucene/form-script" . }}
{{ end }}
{{ end }}
@@ -0,0 +1 @@
{{ define "main" }}{{ end }}
@@ -0,0 +1,9 @@
<div class="callout">
<div class="callout__square-grid-overlay"></div>
<div class="callout__illustration" style="background-image: url('{{ .Params.image.src }}');"></div>
<div class="callout__lights-overlay"></div>
<div class="callout__content">
<h5 class="callout__title">{{ .Params.title | safeHTML }}</h5>
<div class="callout__description">{{ .Params.description | safeHTML }}</div>
</div>
</div>
@@ -0,0 +1,20 @@
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-features") }}
<section class="grey-bg py-5">
<div class="container">
<h3 class="text-center mb-5">{{ .Params.title }}</h3>
<div class="row g-4">
{{ range $index, $feature := .Params.features }}
<div class="col-12 {{ if eq $index 0 }}col-md-12{{ else }}col-md-6{{ end }} col-xl-4">
<a href="{{ $feature.link.url }}" class="card d-flex flex-column gap-3">
<img src="{{ $feature.icon.src }}" alt="{{ $feature.icon.alt }}" width="24" height="24" />
<p class="mb-0 text-dark">{{ $feature.description }}</p>
<p class="m-0">
<span class="link link_md">{{ $feature.link.text }}</span>
</p>
</a>
</div>
{{ end }}
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,184 @@
<script>
hbspt.forms.create({
portalId: '139603372',
formId: '814b303f-2f24-460a-8a81-367146d98786',
region: 'eu1',
sfdcCampaignId: '701fI00000M2FnuQAF',
target: '#qdrant-contact-form',
cssClass: 'luceneForm',
submitButtonClass: 'button button_contained button_lg',
onFormReady: function ($form) {
// Normalize to a plain DOM element
var formEl;
if ($form && $form.nodeType === 1) {
formEl = $form;
} else if ($form && $form[0] && $form[0].nodeType === 1) {
formEl = $form[0];
}
if (!formEl) return;
/* ──────────────────────────────
Hidden field: last_conversion_campaign_name
───────────────────────────────*/
var hidden = document.createElement('input');
hidden.type = 'hidden';
hidden.name = 'last_conversion_campaign_name';
hidden.value = '2025.Q4_Website_Contact Us Form_Elastic_LP';
formEl.appendChild(hidden);
/* ──────────────────────────────
Progressive steps logic
───────────────────────────────*/
// Helper: get the .hs-form-field wrapper for a given input/select/textarea
function wrapperForField(selector) {
var field = formEl.querySelector(selector);
return field && field.closest('.hs-form-field');
}
// Step 0: email (only visible on load)
var step0 = [wrapperForField('input[name="email"]')];
// Step 1: first/last/company/jobtitle
var step1 = [
wrapperForField('input[name="firstname"]'),
wrapperForField('input[name="lastname"]'),
wrapperForField('input[name="company"]'),
wrapperForField('input[name="jobtitle"]'),
];
// Step 2: number_of_vectors + message
var step2 = [wrapperForField('input[name="number_of_vectors"]'), wrapperForField('textarea[name="message"]')];
// Step 3: country
var step3 = [wrapperForField('select[name="country"]')];
// Clean out any null entries
var steps = [step0, step1, step2, step3].map(function (group) {
return group.filter(function (el) {
return !!el;
});
});
// Submit button wrapper (HubSpot’s markup varies a bit, so be lenient)
var submitGroup = formEl.querySelector('.hs-submit, .hs_submit, .actions');
if (submitGroup) submitGroup.style.display = 'none';
// Hide all steps except the first (email)
steps.forEach(function (group, index) {
if (index === 0) return; // keep email visible
group.forEach(function (el) {
el.style.display = 'none';
});
});
// REQUIRED fields that gate each step
// 0: email
// 1: firstname, lastname, company (jobtitle optional)
// 2: message (number_of_vectors optional)
// 3: no additional requirement – we only show it when step 2 is done
var requiredSelectorsByStep = [
['input[name="email"]'],
['input[name="firstname"]', 'input[name="lastname"]', 'input[name="company"]'],
['textarea[name="message"]'],
[],
];
function isStepFilled(stepIndex) {
var selectors = requiredSelectorsByStep[stepIndex] || [];
for (var i = 0; i < selectors.length; i++) {
var field = formEl.querySelector(selectors[i]);
if (!field) continue; // don’t block if missing
var val = field.value;
if (!val || !val.trim()) {
return false;
}
}
return true;
}
function showGroup(group) {
group.forEach(function (el) {
el.style.display = '';
});
}
function maybeShowNext(stepIndex) {
if (!isStepFilled(stepIndex)) return;
var nextIndex = stepIndex + 1;
var nextStep = steps[nextIndex];
if (nextStep) {
// Reveal the next step
showGroup(nextStep);
// If this is the last step (country), also reveal the submit button
if (nextIndex === steps.length - 1 && submitGroup) {
submitGroup.style.display = '';
}
}
}
function attach(stepIndex, selectors) {
selectors.forEach(function (sel) {
var field = formEl.querySelector(sel);
if (!field) return;
['input', 'change', 'blur'].forEach(function (evt) {
field.addEventListener(evt, function () {
maybeShowNext(stepIndex);
});
});
});
}
// Attach listeners:
// After email → show first/last/company/jobtitle
attach(0, ['input[name="email"]']);
// After first/last/company → show message + vectors
attach(1, [
'input[name="firstname"]',
'input[name="lastname"]',
'input[name="company"]',
'input[name="jobtitle"]',
]);
// After message (vectors optional) → show country + submit
attach(2, ['input[name="number_of_vectors"]', 'textarea[name="message"]']);
// Step 3 (country) doesn’t gate anything right now, but we could attach here if needed:
// attach(3, ['select[name="country"]']);
},
});
</script>
<script>
// shows a fallback content if HubSpot forms library is not loaded
// what can happen if the user has trackers blocking policy turned on
document.addEventListener('DOMContentLoaded', function () {
if (typeof hbspt === 'undefined' || !hbspt.forms) {
const fallbackButtonContainer = document.createElement('div');
fallbackButtonContainer.className = 'd-flex flex-column align-content-center px-5 py-5';
const fallbackText = document.createElement('p');
fallbackText.className = 'text-white text-center mb-4';
fallbackText.innerHTML = {{- .Params.form.fallback.text -}};
fallbackButtonContainer.appendChild(fallbackText);
// Create a fallback button only if the link is provided
// warning: check if content via the link is not blocked as well
{{ if .Params.form.fallback.link }}
const fallbackButton = document.createElement('a');
fallbackButton.href = {{- .Params.form.fallback.link -}};
fallbackButton.target = '_blank';
fallbackButton.className = 'button button_contained button_lg';
fallbackButton.textContent = {{- .Params.form.fallback.buttonText -}};
fallbackButtonContainer.appendChild(fallbackButton);
{{ end }}
document.getElementsByClassName("elastic-lucene-form__content")[0].appendChild(fallbackButtonContainer);
}
});
</script>
@@ -0,0 +1,17 @@
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-form") }}
<section class="elastic-lucene-form">
<div class="elastic-lucene-form__illustration" style="background-image: url('{{ .Params.image.src }}');"></div>
<div class="container">
<div class="row position-relative">
<div class="col-12 col-lg-6 offset-0 offset-lg-6 elastic-lucene-form__content">
<h2 class="elastic-lucene-form__title text-white mb-4">{{ .Params.title }}</h2>
<div class="elastic-lucene-form__description">
{{ .Params.content | safeHTML }}
</div>
<div id="qdrant-contact-form"></div>
</div>
</div>
</div>
{{ partial "top-and-bottom-overlay" (dict "context" . "class" "elastic-lucene-form") }}
</section>
{{ end }}
@@ -0,0 +1,30 @@
<section class="elastic-lucene-hero" style="--bg-image: url('{{ .Params.image.src }}');">
<div class="elastic-lucene-hero__illustration"></div>
<div class="container">
<div class="row align-items-lg-center">
<div class="elastic-lucene-hero__content col-12 col-lg-8">
<h1 class="elastic-lucene-hero__title">{{ .Params.title }}</h1>
<p class="elastic-lucene-hero__description">{{ .Params.description }}</p>
<div class="elastic-lucene-hero__quotes">
<svg
xmlns="http://www.w3.org/2000/svg"
width="1"
height="85"
viewBox="0 0 1 85"
fill="none"
class="elastic-lucene-hero__quotes-line"
>
<path d="M0.5 0.5V84.5" stroke="#8F98B3" stroke-linecap="round" />
</svg>
<div class="elastic-lucene-hero__quotes-list">
{{ range .Params.quotes }}
<p>{{ . }}</p>
{{ end }}
</div>
</div>
<p class="elastic-lucene-hero__closing">{{ .Params.closingText }}</p>
</div>
</div>
</div>
<div class="elastic-lucene-hero__overlay"></div>
</section>
@@ -0,0 +1,44 @@
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-lessons") }}
<section class="outlined-card-group grey-bg pt-6">
<div class="container">
<div class="outlined-card-group__cards row gy-0">
<div class="col-12 p-0">
<div class="card outlined-card-group__header-card">
<h4 class="outlined-card-group__header-title text-center mb-0">
{{ .Params.title | safeHTML }}
</h4>
</div>
</div>
<div class="col-12 p-0 d-flex flex-column flex-lg-row justify-content-between gap-3">
{{ range .Params.lessons }}
<div class="card outlined-card-group__card">
<div class="og-card__images-row">
<div>
<img src="{{ .imageLeft.src }}" width="100%" alt="{{ .imageLeft.alt }}" />
</div>
<div>
<a href="{{ .link.url }}">
<img src="{{ .imageMiddle.src }}" width="100%" alt="{{ .imageMiddle.alt }}" />
</a>
</div>
<div>
<img src="{{ .imageRight.src }}" width="100%" alt="{{ .imageRight.alt }}" />
</div>
</div>
<div class="outlined-card-group__content px-0">
<div class="outlined-card-group__text">
<h6 class="outlined-card-group__title">{{ .title | safeHTML }}</h6>
<p class="outlined-card-group__description">{{ .description | safeHTML }}</p>
</div>
<a href="{{ .link.url }}" class="link outlined-card-group__link">
{{ .link.text }}
</a>
</div>
</div>
{{ end }}
</div>
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,40 @@
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-migration") }}
<section class="outlined-card-group grey-bg pt-5 pb-6">
<div class="container">
<div class="outlined-card-group__cards row gy-0">
<div class="col-12 p-0">
<div class="card outlined-card-group__header-card">
<h4 class="outlined-card-group__header-title text-center mb-0">
{{ .Params.headerTitle | safeHTML }}
</h4>
</div>
</div>
<div class="col-12 p-0">
<div class="card outlined-card-group__card outlined-card-group__card--jumbo">
<div class="outlined-card-group__content outlined-card-group__content--jumbo">
<div class="outlined-card-group__illustration">
<img src="{{ .Params.image.src }}" alt="{{ .Params.image.alt }}" />
</div>
<div class="outlined-card-group__text">
<h3 class="outlined-card-group__title outlined-card-group__title--large">{{ .Params.title }}</h3>
<p class="outlined-card-group__subtitle">{{ .Params.subtitle }}</p>
<p class="outlined-card-group__description outlined-card-group__description--small">
{{ .Params.description }}
</p>
<p class="outlined-card-group__description outlined-card-group__description--small">
{{ .Params.descriptionSecond }}
</p>
<a
href="{{ .Params.button.url }}"
class="button button_contained button_lg outlined-card-group__button"
>
{{ .Params.button.text }}
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,24 @@
{{ with (.Site.GetPage "/elastic-lucene/elastic-lucene-optimization") }}
<section class="outlined-card-group grey-bg py-5">
<div class="container">
<div class="row">
<h3 class="text-center col-12 mb-5">{{ .Params.title }}</h3>
</div>
<div class="outlined-card-group__cards">
<div class="row g-3">
{{ range .Params.features }}
<div class="col-12 col-md-6 col-xl-3 d-flex">
<div class="card outlined-card-group__card w-100">
<div class="d-flex flex-column gap-3">
<img class="outlined-card-group__icon" src="{{ .icon.src }}" alt="{{ .icon.alt }}" />
<h6 class="outlined-card-group__title outlined-card-group__title--small">{{ .title }}</h6>
<p class="outlined-card-group__description">{{ .description }}</p>
</div>
</div>
</div>
{{ end }}
</div>
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,32 @@
{{ with (.Site.GetPage "/elastic-lucene/why-qdrant") }}
<section class="py-5 grey-bg">
<div class="container">
<div class="row align-items-center">
<div class="col-12 col-lg-6 mb-4 mb-lg-0">
<div class="split-section__content">
<h3 class="split-section__title">{{ .Params.title }}</h3>
<div class="split-section__description">
<p>{{ .Params.description }}</p>
<p>{{ .Params.descriptionSecond }}</p>
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="card split-section__testimonial-card width-auto">
<div class="split-section__logo-container">
<img
class="split-section__logo"
src="{{ .Params.testimonial.logo.src }}"
alt="{{ .Params.testimonial.logo.alt }}"
/>
</div>
<p class="split-section__testimonial-text">{{ .Params.testimonial.text }}</p>
<div class="split-section__link-wrapper">
<a class="link link_md" href="{{ .Params.testimonial.link.url }}">{{ .Params.testimonial.link.text }}</a>
</div>
</div>
</div>
</div>
</div>
</section>
{{ end }}
@@ -1,6 +1,6 @@
{{ $section := .Section }}
{{ with (.Site.GetPage "/headless/menu") }}
<div class="main-menu z-2">
<div class="main-menu">
<a href="/">
{{ partial "logo.html" . }}
</a>
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 1C14.9706 1 19 5.02944 19 10C19 12.125 18.2619 14.0766 17.0303 15.6162L22.707 21.293C23.0973 21.6835 23.0975 22.3166 22.707 22.707C22.3166 23.0975 21.6835 23.0973 21.293 22.707L15.6162 17.0303C14.0766 18.2619 12.125 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1ZM10 3C6.13401 3 3 6.13401 3 10C3 13.866 6.13401 17 10 17C13.866 17 17 13.866 17 10C17 6.13401 13.866 3 10 3Z" fill="#2F6FF0"/>
</svg>

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 KiB

@@ -0,0 +1,45 @@
<svg width="1440" height="235" viewBox="0 0 1440 235" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_11925_32774)">
<path d="M239.462 205.569C406.202 341.569 528.508 156.273 568.938 205.569C664.075 321.569 925.84 212.069 1020.09 212.069C1079.73 212.069 1197.25 291.565 1277.84 270.412C1391.43 240.598 1397.16 149.445 1447.71 212.069C1492.16 267.149 1616.41 397.899 1378.8 397.899H131.576C-108.853 397.899 -118.807 101.45 -24.6279 167.497C12.984 193.874 15.0255 223.839 47.4234 255.029C80.8588 287.218 201.776 174.831 239.462 205.569Z" fill="url(#paint0_linear_11925_32774)"/>
</g>
<g filter="url(#filter1_f_11925_32774)">
<path d="M24.0992 405.047C-16.6013 373.364 -48.6497 370.16 -97.2976 353.022C-191.204 319.94 -254.743 338.085 -346.605 299.69C-534.045 221.349 71.8446 129.467 173.57 305.317C237.518 415.862 239.336 730.648 158.259 631.976C125.88 592.571 131.181 556.556 105.386 512.558C78.7648 467.151 65.6341 437.379 24.0992 405.047Z" fill="url(#paint1_linear_11925_32774)"/>
</g>
<g filter="url(#filter2_f_11925_32774)">
<path d="M1472.84 338.041C1423.45 323.181 1392.4 331.759 1340.85 333.332C1241.33 336.368 1188.62 376.221 1089.09 373.566C886.014 368.147 1417.91 63.8019 1576.25 191.09C1675.78 271.108 1791.08 564.025 1679.85 501.262C1635.44 476.197 1627.38 440.696 1587.45 408.972C1546.23 376.232 1523.24 353.205 1472.84 338.041Z" fill="url(#paint2_linear_11925_32774)"/>
</g>
<defs>
<filter id="filter0_f_11925_32774" x="-200" y="37.899" width="1840" height="480" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="60" result="effect1_foregroundBlur_11925_32774"/>
</filter>
<filter id="filter1_f_11925_32774" x="-542.348" y="44.5892" width="922.764" height="766.27" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_11925_32774"/>
</filter>
<filter id="filter2_f_11925_32774" x="883.504" y="-3.05176e-05" width="1001.87" height="670.007" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_11925_32774"/>
</filter>
<linearGradient id="paint0_linear_11925_32774" x1="-91.0087" y1="272.449" x2="1531.88" y2="274.748" gradientUnits="userSpaceOnUse">
<stop offset="0.0775907" stop-color="#DC244C"/>
<stop offset="0.293353" stop-color="#2567EB"/>
<stop offset="0.486232" stop-color="#F54C71"/>
<stop offset="0.687211" stop-color="#7335F0"/>
<stop offset="1" stop-color="#BB3987"/>
</linearGradient>
<linearGradient id="paint1_linear_11925_32774" x1="-33.177" y1="309.807" x2="33.0143" y2="261.64" gradientUnits="userSpaceOnUse">
<stop stop-color="#DC244C"/>
<stop offset="0.446034" stop-color="#F54C71"/>
<stop offset="1" stop-color="#4A16B1"/>
</linearGradient>
<linearGradient id="paint2_linear_11925_32774" x1="1385.05" y1="269.889" x2="1429.4" y2="201.081" gradientUnits="userSpaceOnUse">
<stop stop-color="#DC244C"/>
<stop offset="0.446034" stop-color="#F54C71"/>
<stop offset="1" stop-color="#4A16B1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="119.999"
height="26.108679"
viewBox="0 0 119.999 26.108679"
fill="none"
version="1.1"
id="svg85"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<g
clip-path="url(#clip0_11990_33135)"
id="g75"
transform="translate(-20.001996,-19.000046)">
<path
d="m 59.1136,35.7456 c 0.7527,0.4956 2.1073,1.0895 3.5127,1.0895 1.204,0 2.057,-0.5442 2.057,-1.5841 0,-2.3271 -6.2721,-1.5846 -6.2721,-5.5958 0,-2.278 2.0069,-3.4664 4.4154,-3.4664 1.7061,0 2.6094,0.5448 3.7637,1.2879 l -0.954,1.4359 c -1.1538,-0.4955 -1.7558,-0.842 -2.9101,-0.842 -1.1538,0 -2.0571,0.4951 -2.0571,1.5349 0,2.3769 6.2721,1.5349 6.2721,5.5953 0,2.03 -1.7563,3.5157 -4.3651,3.5157 -2.0074,0 -3.5127,-0.8415 -4.4159,-1.5349 z m 10.788,9.2601 V 26.4865 h 2.1575 v 1.3863 c 0,0.3464 -0.0502,0.6437 -0.0502,0.6437 h 0.0502 c 0,0 1.0539,-2.2775 4.0644,-2.2775 3.2616,0 5.3192,2.5747 5.3192,6.2887 0,3.8124 -2.3087,6.2882 -5.52,6.2882 -2.7595,0 -3.7632,-2.1289 -3.7632,-2.1289 h -0.0502 c 0,0 0.0502,0.4454 0.0502,1.0394 v 7.3782 h -2.2579 z m 5.6701,-8.2198 c 1.9064,0 3.5121,-1.5349 3.5121,-4.2582 0,-2.6244 -1.4048,-4.308 -3.4117,-4.308 -1.8065,0 -3.5126,1.2377 -3.5126,4.308 0,2.1289 1.204,4.2582 3.4122,4.2582 z m 15.2546,-8.17 c -2.3584,0 -4.4661,2.5747 -4.4661,4.9019 v 5.0009 H 84.052 V 26.487 h 2.2585 v 2.1289 c 0,0.4956 -0.0503,0.8917 -0.0503,0.8917 h 0.0503 c 0.5517,-1.5846 2.7092,-3.1692 4.566,-3.1692 v 2.278 z m 2.4085,9.9525 V 26.487 h 2.3086 v 12.0327 h -2.3086 v 0.0492 z m 14.3012,0 v -7.2292 c 0,-1.6835 -0.352,-3.0205 -2.258,-3.0205 -2.359,0 -4.064,1.931 -4.064,4.4068 v 5.7937 H 98.9049 V 26.4865 h 2.2581 v 1.8322 c 0,0.3464 -0.05,0.6928 -0.05,0.6928 h 0.05 c 0.502,-1.0393 1.957,-2.8217 4.617,-2.8217 2.859,0 4.164,1.5349 4.164,4.6047 v 7.7247 h -2.408 z m 13.749,0 -3.664,-5.6943 h -1.806 v 5.6943 h -2.308 V 20 h 2.308 v 10.8442 h 1.756 l 3.412,-4.3577 h 2.459 l -3.914,5.2489 v 0.0492 l 4.366,6.7346 z m 9.082,0 c -1.907,0 -4.064,-0.3465 -4.064,-3.3174 V 20 h 2.308 v 14.9041 c 0,1.4857 1.254,1.5354 1.756,1.5354 z m 9.584,-10.0519 c -2.358,0 -4.466,2.5752 -4.466,4.9024 v 5.0009 h -2.308 V 26.3876 h 2.258 v 2.1289 c 0,0.4956 -0.051,0.8917 -0.051,0.8917 h 0.051 c 0.552,-1.5846 2.709,-3.1692 4.566,-3.1692 v 2.2775 z m -45.5619,-4.555 c 0.8034,0 1.4551,-0.6427 1.4551,-1.436 0,-0.7933 -0.6512,-1.436 -1.4551,-1.436 -0.8033,0 -1.455,0.6427 -1.455,1.436 0,0.7933 0.6512,1.436 1.455,1.436 z"
id="path63"
fill="#2e3841" />
<g
clip-path="url(#clip1_11990_33135)"
id="g73">
<path
d="m 22.3117,23.5062 c 0.1004,-1.5188 1.3526,-2.8348 3.0065,-2.7334 0.4509,0.0502 1.0022,0.0502 1.8542,0.7085 3.7075,3.2902 5.9127,9.0617 5.2609,14.0726 -0.0502,0.2531 -0.3007,0.2531 -0.4011,0 -1.0519,-3.594 -4.5098,-7.694 -7.5666,-8.9598 -1.453,-0.5568 -2.2544,-1.6198 -2.1539,-3.0879 z"
fill="#faa21b"
id="path65" />
<path
d="m 31.8832,41.173 c -0.9519,-3.1381 -5.6616,-8.3523 -9.12,-8.3523 -0.3747,-0.0062 -0.7467,0.0652 -1.0924,0.2097 -0.3458,0.1446 -0.658,0.3591 -0.9168,0.6301 -0.2589,0.271 -0.4589,0.5927 -0.5874,0.9447 -0.1285,0.3521 -0.1827,0.727 -0.1593,1.101 0.1004,1.7212 1.5534,2.5818 2.8564,2.5818 2.9563,0 6.5141,1.2652 8.7193,3.0878 0.1501,0.101 0.3504,0 0.3002,-0.2028 z"
fill="#70bf54"
id="path67" />
<path
d="m 36.143,44.9189 c -0.0502,0.2531 -0.3012,0.2531 -0.4012,0 -3.9087,-12.3012 3.107,-25.817 8.3182,-25.9179 2.7565,-0.0513 4.6604,1.9742 4.6604,4.2517 0,1.569 -0.5011,2.8348 -2.3046,3.847 -4.5605,2.5818 -9.6718,9.2636 -10.2728,17.8187 z"
fill="#00bae9"
id="path69" />
<path
d="m 40.5508,41.3251 c -0.1506,0.1009 -0.3509,0 -0.3007,-0.2029 0.9519,-3.1381 5.6626,-8.3523 9.12,-8.3523 0.3747,-0.0063 0.7468,0.0651 1.0926,0.2096 0.3459,0.1445 0.6581,0.359 0.917,0.63 0.2589,0.2711 0.4589,0.5928 0.5874,0.9449 0.1286,0.3521 0.1829,0.7269 0.1595,1.101 -0.1005,1.7212 -1.554,2.5818 -2.857,2.5818 -2.9061,0 -6.4639,1.3667 -8.7188,3.0879 z"
fill="#128acb"
id="path71" />
</g>
</g>
<defs
id="defs83" />
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@@ -0,0 +1,114 @@
<svg width="781" height="454" viewBox="0 0 781 454" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="463" width="58.2039" height="58.2039" transform="rotate(-90 0.5 463)" stroke="#161E33"/>
<rect x="0.5" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 0.5 404.796)" stroke="#161E33"/>
<rect x="0.5" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 0.5 346.592)" stroke="#161E33"/>
<rect x="0.5" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 0.5 288.388)" stroke="#161E33"/>
<rect x="0.5" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 0.5 230.184)" stroke="#161E33"/>
<rect x="0.5" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 0.5 171.98)" stroke="#161E33"/>
<rect x="0.5" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 0.5 113.776)" stroke="#161E33"/>
<rect x="0.5" y="55.5723" width="58.2039" height="58.2039" transform="rotate(-90 0.5 55.5723)" stroke="#161E33"/>
<rect x="58.7031" y="463" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 463)" stroke="#161E33"/>
<rect x="58.7031" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 404.796)" stroke="#161E33"/>
<rect x="58.7031" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 346.592)" stroke="#161E33"/>
<rect x="58.7031" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 288.388)" stroke="#161E33"/>
<rect x="58.7031" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 230.184)" stroke="#161E33"/>
<rect x="58.7031" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 171.98)" stroke="#161E33"/>
<rect x="58.7031" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 113.776)" stroke="#161E33"/>
<rect x="58.7031" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 58.7031 55.5724)" stroke="#161E33"/>
<rect x="116.908" y="463" width="58.2039" height="58.2039" transform="rotate(-90 116.908 463)" stroke="#161E33"/>
<rect x="116.908" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 116.908 404.796)" stroke="#161E33"/>
<rect x="116.908" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 116.908 346.592)" stroke="#161E33"/>
<rect x="116.908" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 116.908 288.388)" stroke="#161E33"/>
<rect x="116.908" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 116.908 230.184)" stroke="#161E33"/>
<rect x="116.908" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 116.908 171.98)" stroke="#161E33"/>
<rect x="116.908" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 116.908 113.776)" stroke="#161E33"/>
<rect x="116.908" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 116.908 55.5724)" stroke="#161E33"/>
<rect x="175.111" y="463" width="58.2039" height="58.2039" transform="rotate(-90 175.111 463)" stroke="#161E33"/>
<rect x="175.111" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 175.111 404.796)" stroke="#161E33"/>
<rect x="175.111" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 175.111 346.592)" stroke="#161E33"/>
<rect x="175.111" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 175.111 288.388)" stroke="#161E33"/>
<rect x="175.111" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 175.111 230.184)" stroke="#161E33"/>
<rect x="175.111" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 175.111 171.98)" stroke="#161E33"/>
<rect x="175.111" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 175.111 113.776)" stroke="#161E33"/>
<rect x="175.111" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 175.111 55.5724)" stroke="#161E33"/>
<rect x="233.316" y="463" width="58.2039" height="58.2039" transform="rotate(-90 233.316 463)" stroke="#161E33"/>
<rect x="233.316" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 233.316 404.796)" stroke="#161E33"/>
<rect x="233.316" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 233.316 346.592)" stroke="#161E33"/>
<rect x="233.316" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 233.316 288.388)" stroke="#161E33"/>
<rect x="233.316" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 233.316 230.184)" stroke="#161E33"/>
<rect x="233.316" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 233.316 171.98)" stroke="#161E33"/>
<rect x="233.316" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 233.316 113.776)" stroke="#161E33"/>
<rect x="233.316" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 233.316 55.5724)" stroke="#161E33"/>
<rect x="291.52" y="463" width="58.2039" height="58.2039" transform="rotate(-90 291.52 463)" stroke="#161E33"/>
<rect x="291.52" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 291.52 404.796)" stroke="#161E33"/>
<rect x="291.52" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 291.52 346.592)" stroke="#161E33"/>
<rect x="291.52" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 291.52 288.388)" stroke="#161E33"/>
<rect x="291.52" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 291.52 230.184)" stroke="#161E33"/>
<rect x="291.52" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 291.52 171.98)" stroke="#161E33"/>
<rect x="291.52" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 291.52 113.776)" stroke="#161E33"/>
<rect x="291.52" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 291.52 55.5724)" stroke="#161E33"/>
<rect x="349.725" y="463" width="58.2039" height="58.2039" transform="rotate(-90 349.725 463)" stroke="#161E33"/>
<rect x="349.725" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 349.725 404.796)" stroke="#161E33"/>
<rect x="349.725" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 349.725 346.592)" stroke="#161E33"/>
<rect x="349.725" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 349.725 288.388)" stroke="#161E33"/>
<rect x="349.725" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 349.725 230.184)" stroke="#161E33"/>
<rect x="349.725" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 349.725 171.98)" stroke="#161E33"/>
<rect x="349.725" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 349.725 113.776)" stroke="#161E33"/>
<rect x="349.725" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 349.725 55.5724)" stroke="#161E33"/>
<rect x="407.928" y="463" width="58.2039" height="58.2039" transform="rotate(-90 407.928 463)" stroke="#161E33"/>
<rect x="407.928" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 407.928 404.796)" stroke="#161E33"/>
<rect x="407.928" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 407.928 346.592)" stroke="#161E33"/>
<rect x="407.928" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 407.928 288.388)" stroke="#161E33"/>
<rect x="407.928" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 407.928 230.184)" stroke="#161E33"/>
<rect x="407.928" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 407.928 171.98)" stroke="#161E33"/>
<rect x="407.928" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 407.928 113.776)" stroke="#161E33"/>
<rect x="407.928" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 407.928 55.5724)" stroke="#161E33"/>
<rect x="466.131" y="463" width="58.2039" height="58.2039" transform="rotate(-90 466.131 463)" stroke="#161E33"/>
<rect x="466.131" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 466.131 404.796)" stroke="#161E33"/>
<rect x="466.131" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 466.131 346.592)" stroke="#161E33"/>
<rect x="466.131" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 466.131 288.388)" stroke="#161E33"/>
<rect x="466.131" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 466.131 230.184)" stroke="#161E33"/>
<rect x="466.131" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 466.131 171.98)" stroke="#161E33"/>
<rect x="466.131" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 466.131 113.776)" stroke="#161E33"/>
<rect x="466.131" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 466.131 55.5724)" stroke="#161E33"/>
<rect x="524.336" y="463" width="58.2039" height="58.2039" transform="rotate(-90 524.336 463)" stroke="#161E33"/>
<rect x="524.336" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 524.336 404.796)" stroke="#161E33"/>
<rect x="524.336" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 524.336 346.592)" stroke="#161E33"/>
<rect x="524.336" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 524.336 288.388)" stroke="#161E33"/>
<rect x="524.336" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 524.336 230.184)" stroke="#161E33"/>
<rect x="524.336" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 524.336 171.98)" stroke="#161E33"/>
<rect x="524.336" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 524.336 113.776)" stroke="#161E33"/>
<rect x="524.336" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 524.336 55.5724)" stroke="#161E33"/>
<rect x="582.539" y="463" width="58.2039" height="58.2039" transform="rotate(-90 582.539 463)" stroke="#161E33"/>
<rect x="582.539" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 582.539 404.796)" stroke="#161E33"/>
<rect x="582.539" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 582.539 346.592)" stroke="#161E33"/>
<rect x="582.539" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 582.539 288.388)" stroke="#161E33"/>
<rect x="582.539" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 582.539 230.184)" stroke="#161E33"/>
<rect x="582.539" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 582.539 171.98)" stroke="#161E33"/>
<rect x="582.539" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 582.539 113.776)" stroke="#161E33"/>
<rect x="582.539" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 582.539 55.5724)" stroke="#161E33"/>
<rect x="640.744" y="463" width="58.2039" height="58.2039" transform="rotate(-90 640.744 463)" stroke="#161E33"/>
<rect x="640.744" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 640.744 404.796)" stroke="#161E33"/>
<rect x="640.744" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 640.744 346.592)" stroke="#161E33"/>
<rect x="640.744" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 640.744 288.388)" stroke="#161E33"/>
<rect x="640.744" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 640.744 230.184)" stroke="#161E33"/>
<rect x="640.744" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 640.744 171.98)" stroke="#161E33"/>
<rect x="640.744" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 640.744 113.776)" stroke="#161E33"/>
<rect x="640.744" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 640.744 55.5724)" stroke="#161E33"/>
<rect x="698.947" y="463" width="58.2039" height="58.2039" transform="rotate(-90 698.947 463)" stroke="#161E33"/>
<rect x="698.947" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 698.947 404.796)" stroke="#161E33"/>
<rect x="698.947" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 698.947 346.592)" stroke="#161E33"/>
<rect x="698.947" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 698.947 288.388)" stroke="#161E33"/>
<rect x="698.947" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 698.947 230.184)" stroke="#161E33"/>
<rect x="698.947" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 698.947 171.98)" stroke="#161E33"/>
<rect x="698.947" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 698.947 113.776)" stroke="#161E33"/>
<rect x="698.947" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 698.947 55.5724)" stroke="#161E33"/>
<rect x="757.15" y="463" width="58.2039" height="58.2039" transform="rotate(-90 757.15 463)" stroke="#161E33"/>
<rect x="757.15" y="404.796" width="58.2039" height="58.2039" transform="rotate(-90 757.15 404.796)" stroke="#161E33"/>
<rect x="757.15" y="346.592" width="58.2039" height="58.2039" transform="rotate(-90 757.15 346.592)" stroke="#161E33"/>
<rect x="757.15" y="288.388" width="58.2039" height="58.2039" transform="rotate(-90 757.15 288.388)" stroke="#161E33"/>
<rect x="757.15" y="230.184" width="58.2039" height="58.2039" transform="rotate(-90 757.15 230.184)" stroke="#161E33"/>
<rect x="757.15" y="171.98" width="58.2039" height="58.2039" transform="rotate(-90 757.15 171.98)" stroke="#161E33"/>
<rect x="757.15" y="113.776" width="58.2039" height="58.2039" transform="rotate(-90 757.15 113.776)" stroke="#161E33"/>
<rect x="757.15" y="55.5724" width="58.2039" height="58.2039" transform="rotate(-90 757.15 55.5724)" stroke="#161E33"/>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB