/* === Theme Variables === */
html {
  --radius: 10px;
  --default-spacing: 20px;
  --main: #5D4037;
  --additional: #ffe082ff;
  --font-family: 'Livvic', sans-serif;
  --heading-font-family: 'Josefin Sans', sans-serif;
  --bg-color: #FFFCF8;
  --text-color: #212121;
  --heading-weight: 600;
  --heading-letter-spacing: 0.6px;
  --body-letter-spacing: 0.6px;
}

/* === Common App Styles === */
/* Layout System Custom CSS - ls- prefix */

/* === FLEXBOX === */
.ls-flex {
  display: flex;
}

.ls-inline-flex {
  display: inline-flex;
}

/* Flex Direction */

.ls-flex-column {
  flex-direction: column;
}

.ls-flex-column-reverse {
  flex-direction: column-reverse;
}

/* Flex Wrap */

.ls-wrap {
  flex-wrap: wrap;
}

.ls-no-wrap {
  flex-wrap: nowrap;
}

/* Justify Content */
.ls-justify-start {
  justify-content: flex-start;
}

.ls-justify-end {
  justify-content: flex-end;
}

.ls-justify-center {
  justify-content: center;
}

/* Align Items */
.ls-items-start {
  align-items: flex-start;
}

.ls-items-end {
  align-items: flex-end;
}

.ls-items-center {
  align-items: center;
}

.ls-gap {
  gap: 14px;
}

.ls-gap-sm {
  gap: 8px;
}

/* === POSITION === */
.ls-relative {
  position: relative;
}

/* === WIDTH & HEIGHT === */
.ls-full-width {
  width: 100%;
}

.ls-full-height {
  height: 100%;
}

/* === TEXT ALIGNMENT === */
.ls-text-left {
  text-align: left;
}

.ls-text-start {
  text-align: left;
}

.ls-text-center {
  text-align: center;
}

.ls-text-right {
  text-align: right;
}

.ls-text-end {
  text-align: right;
}

.ls-text-justify {
  text-align: justify;
}

/* === OVERFLOW === */
.ls-overflow-x-auto {
  overflow-x: auto;
}

/* === SHADOWS === */
.ls-shadow-1 {
  box-shadow: 0 1px 3px rgba(0,0,0,0.2), 0 1px 1px rgba(0,0,0,0.14), 0 2px 1px -1px rgba(0,0,0,0.12);
}

.ls-shadow-2 {
  box-shadow: 0 1px 5px rgba(0,0,0,0.2), 0 2px 2px rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12);
}

.ls-shadow-3 {
  box-shadow: 0 1px 8px rgba(0,0,0,0.2), 0 3px 4px rgba(0,0,0,0.14), 0 3px 3px -2px rgba(0,0,0,0.12);
}

/* === CURSOR === */
.ls-cursor-pointer {
  cursor: pointer;
}

/* === COLUMNS === */
.ls-column-image {
  padding: 16px;
}

@media (max-width: 599px) {
  .ls-column-image {
    width: 100% !important;
  }
}

.ls-column-wrapper {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* Allow column to expand when it contains a menu */
.ls-column-wrapper:has(.ls-menu-view) {
  min-width: fit-content;
  flex-shrink: 0;
}

/* hideOnMobile: hides the column below the md breakpoint (matches Quasar's .gt-sm cutoff) */
@media (max-width: 1023.98px) {
  .ls-hide-mobile {
    display: none !important;
  }
}

.ls-column-content {
  width: fit-content;
  max-width: 100%;
  padding: 6px;
}

nav .ls-column-content {
  padding: 2px;
}

.ls-column-elevated {
  margin: 8px;
  padding: 16px;
}

@media (max-width: 768px) {
  .ls-column-content {
    margin: 0;
  }
}

.ls-column-bordered {
  padding: 16px;
}

/* Flat tint card: no border, no shadow — definition comes purely from the column's own
   backgroundColor (already rendered generically in getColumnContentStyles), this class only
   adds the card-like padding so the fill doesn't bleed edge-to-edge like a BLANK column would. */
.ls-column-filled {
  padding: 16px;
}

/* Soft, brand-tinted glow instead of a generic grey drop-shadow — always tied to var(--main)
   so it re-themes automatically with the page, no per-column color picker needed. */
.ls-column-glow {
  padding: 16px;
  box-shadow: 0 8px 28px rgb(from var(--main) r g b / 0.18);
}

/* Remove max-width constraint for menu content */
.ls-column-content:has(.ls-menu-view) {
  max-width: none;
}

/* Excludes .ls-column-wrapper--no-min-width (ColumnInterface.disableMinWidth, the "Fit" column
   width mode — see ColumnBuilder.vue / getColumnMinWidth()): that mode's whole point is letting
   the column shrink to whatever its content actually needs, at every breakpoint, not just
   desktop. Forcing the content div to width:100% here would fight that — it stretches the
   content to fill the (already fit-content-sized) wrapper instead of letting the content's own
   intrinsic size (or its contentWidthPercent, if set) drive the wrapper's size as intended.
   Excluding it lets the plain `.ls-column-content { width: fit-content }` base rule — or an
   explicit contentWidthPercent inline style, which wins by specificity either way — apply on
   mobile same as desktop. */
@media (max-width: 768px) {
  .ls-column-wrapper:not(.ls-column-wrapper--no-min-width) > .ls-column-content {
    width: 100% !important;
  }
}

.ls-column-height-strict {
  overflow: hidden;
}

@media (max-width: 768px) {
  .ls-column-height-strict {
    overflow: visible !important;
  }
}

/* === CONTENT OVERFLOW RING (ColumnInterface.contentOverflowSide) ===
   Pushes .ls-column-content ~50px beyond one edge of its column box, overlaying the
   neighboring column/section. Uses `transform`, not position:absolute — the box stays in
   normal flow, so sizing and the existing align-items/justify-content alignment on
   .ls-column-wrapper are untouched; this only shifts the rendered pixels.
   Deliberately NOT supported (silently clipped) when the column or its section has an image
   background with hover-zoom/darken (.ls-column-hover-bg / .ls-section-hover-bg): those rely
   on their own `overflow: hidden` to contain the zooming ::after layer, which would otherwise
   bleed past the box on hover if relaxed here. */
.ls-column-content--overflow-top {
  transform: translateY(-50px);
}

.ls-column-content--overflow-bottom {
  transform: translateY(50px);
}

.ls-column-content--overflow-left {
  transform: translateX(-50px);
}

.ls-column-content--overflow-right {
  transform: translateX(50px);
}

/* Below this breakpoint, default (non-halfOfMaxWidth) columns are full-width and stacked
   alone — there's no real neighbor to overlay, so a sideways push would just blow out of the
   page. Only halfOfMaxWidth columns (which sit two-by-two on mobile — see
   `.ls-column-wrapper--half-width` in columnStylesUtils.ts) keep the left/right push; every
   other column's push is inert here (same silent-degradation pattern as carousel/hover-bg).
   Top/bottom need no such handling. */
@media (max-width: 768px) {
  .ls-column-content--overflow-left,
  .ls-column-content--overflow-right {
    transform: none;
  }

  .ls-column-wrapper--half-width .ls-column-content--overflow-left {
    transform: translateX(-50px);
  }

  .ls-column-wrapper--half-width .ls-column-content--overflow-right {
    transform: translateX(50px);
  }
}

/* Bumps this column's own stacking priority so the overflowing content paints above sibling
   columns (same section, including wrapped rows) regardless of DOM order, and stays correct
   even if the column itself is isolated (.ls-column-hover-bg).
   Selector is doubled up (.ls-column-wrapper.ls-column-wrapper--overflow-active) purely for
   specificity: every animated column also carries .ls-animate-item, which sets z-index: 1
   further down this file (see SCROLL-TRIGGERED ANIMATIONS). At equal specificity the later
   rule wins the cascade regardless of which is "more specific-sounding", so a plain single
   class here got silently overridden back down to 1 - tying both columns' z-index and letting
   DOM order (not overflow direction) decide who paints on top. Two classes = higher
   specificity = wins outright, independent of rule order in the file. */
.ls-column-wrapper.ls-column-wrapper--overflow-active {
  z-index: 2;
}

/* .ls-column-height-strict's overflow:hidden is just a content-clipping bound (no animated
   pseudo-layer to contain), safe to relax when the ring is active. */
.ls-column-wrapper--overflow-active.ls-column-height-strict {
  overflow: visible;
}

/* Same relaxation for a scroll-reveal section wrapping a column that uses the ring — the only
   downside is a brief cosmetic overlap during the <1s entrance transition. */
.ls-animate-section:has(.ls-column-wrapper--overflow-active) {
  overflow: visible;
}

/* Bumps the whole <section> onto its own stacking context so a top/bottom ring reliably paints
   over the previous/next section (robust even if this section itself is isolated via
   .ls-section-hover-bg) — set by sectionHasOverflowColumn() in sectionStylesUtils.ts. Sections
   have no `position` otherwise, so z-index needs it set here to take effect. */
.ls-section-has-overflow-column {
  position: relative;
  z-index: 2;
}

.ls-columns {
  display: flex;
  flex-wrap: wrap;
}

/* === HOVER BACKGROUND (SECTION/COLUMN IMAGE BACKGROUNDS) ===
   The composited background (image + tint) is moved onto a pseudo-layer via CSS custom
   properties (set inline by sectionStylesUtils.ts/columnStylesUtils.ts) instead of directly
   on the element, so transform/filter can animate on hover without affecting the text/content
   nested inside. This uses `::after`, NOT `::before` - the builder (SectionBuilder.vue/
   ColumnBuilder.vue) puts its own `edit-hover-section`/`edit-hover-column` class on this exact
   same element for its "hover to edit" highlight (see `.edit-hover-section::before` in
   app.scss), which already owns `::before`. An element only has one `::before` box, so reusing
   it here merged both rules' declarations - the builder's `opacity: 0` (meant only for its own
   highlight tint) ended up hiding this background layer too, since it's the same pseudo-box.
   The pseudo-layer sits at z-index -1, which is only guaranteed to paint just behind the
   container's own content (instead of escaping to whatever distant ancestor happens to
   establish the nearest real stacking context - e.g. rendering behind the entire page) if the
   container itself establishes its own stacking context. `position: relative` alone does NOT
   do that (z-index must be non-auto), so `isolation: isolate` is required here. */
.ls-section-hover-bg {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.ls-section-hover-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--ls-bg-image, none);
  background-size: cover;
  background-position: var(--ls-bg-position, center);
  background-repeat: no-repeat;
  background-attachment: var(--ls-bg-attachment, scroll);
  backdrop-filter: var(--ls-bg-backdrop-filter, none);
  transition: transform 0.8s ease, filter 0.8s ease;
}

.ls-section-hover-zoom:hover::after {
  transform: scale(1.08);
}

.ls-section-hover-darken:hover::after {
  filter: brightness(0.7);
}

.ls-column-hover-bg {
  /* .ls-column-wrapper already has position: relative via the ls-relative class, but that
     alone doesn't establish a stacking context - isolation: isolate is needed so the ::after's
     z-index: -1 stays local instead of escaping to a distant ancestor (see comment above). */
  isolation: isolate;
  overflow: hidden;
}

.ls-column-hover-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--ls-bg-image, none);
  background-size: cover;
  background-position: var(--ls-bg-position, center);
  background-repeat: no-repeat;
  transition: transform 0.8s ease, filter 0.8s ease;
}

.ls-column-hover-zoom:hover::after {
  transform: scale(1.08);
}

.ls-column-hover-darken:hover::after {
  filter: brightness(0.7);
}

/* === SCROLL-TRIGGERED ANIMATIONS === */

.ls-animate-section {
  overflow: hidden;
}

/* Animation class added to ls-column-wrapper */
.ls-animate-item {
  z-index: 1;
}

.ls-animate-hidden {
  opacity: 0;
}

/* Visible state with animation */
.ls-animate-visible {
  transition: opacity var(--ls-animate-duration, 0.6s) ease-out, transform var(--ls-animate-duration, 0.6s) ease-out;
}

/* Fade in animation */
.ls-animate-fade-in {
  opacity: 1;
}

/* Slide from left animation */
.ls-animate-hidden[data-animation="slide-left"],
.ls-animate-hidden[data-animation="fade-in"] {
  opacity: 0;
}

.ls-animate-hidden[data-animation="slide-left"] {
  transform: translateX(-60px);
}

.ls-animate-slide-left {
  opacity: 1;
  transform: translateX(0);
}

/* Slide from right animation (for slide-sides) */
.ls-animate-hidden[data-animation="slide-right"] {
  transform: translateX(60px);
}

.ls-animate-slide-right {
  opacity: 1;
  transform: translateX(0);
}

/* Slide from bottom animation */
.ls-animate-hidden[data-animation="slide-bottom"] {
  transform: translateY(60px);
}

.ls-animate-slide-bottom {
  opacity: 1;
  transform: translateY(0);
}

/* === ELEMENT === */
.ls-element {
  width: 100%;
}

/* === ACCORDION === */
.ls-accordion {
  border-radius: 4px;
  margin-bottom: 8px;
}

.ls-accordion-summary {
  cursor: pointer;
  padding: 10px;
  user-select: none;
  list-style: revert;
  display: list-item;
}

.ls-accordion-header {
  margin: 0;
  display: inline;
  padding: 0 10px;
}

.ls-accordion-content {
  padding: 16px;
}

/* === AVATAR === */
.ls-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 500;
  overflow: hidden;
}

.ls-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* === RATING === */
.ls-rating {
  display: inline-flex;
  gap: 4px;
}

/* === TABLE === */
.ls-table {
  width: 100%;
  border-collapse: collapse;
}

/* === TIMELINE === */
.ls-timeline {
  display: flex;
  gap: 16px;
  position: relative;
}

.ls-timeline-line {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}

.ls-timeline-circle {
  display: flex;
  align-items: center;
  justify-content: center;
}

.ls-timeline-connector {
  width: 3px;
  flex: 1;
  min-height: 40px;
  margin-top: 8px;
}

.ls-timeline-content {
  flex: 1;
  padding-top: 8px;
  padding-bottom: 16px;
}

.ls-timeline-header {
  margin: 0 0 16px 0;
}

/* === IMAGE === */
.ls-image-wrapper {
  position: relative;
  display: block;
  width: fit-content;
  max-width: 100%;
}

.ls-image-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.ls-image {
  display: block;
  margin: 12px 0;
}

.ls-image-error {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  flex-direction: column;
  background-color: #f5f5f5;
  color: #9e9e9e;
}

.ls-image-error-icon {
  width: 48px;
  height: 48px;
  fill: currentColor;
}

.ls-image-error-text {
  margin-top: 8px;
  font-size: 12px;
}

.ls-image-lightbox-trigger {
  cursor: pointer;
}

.ls-image-lightbox-trigger:hover img {
  opacity: 0.85;
}

.ls-image-hover-zoom {
  overflow: hidden;
}

/* Combined into one rule (rather than a separate `transition` per effect) so that when any
   combination of lightbox/hover-zoom/hover-darken is enabled together, none of their transitions
   get silently dropped - `transition` is a shorthand, so two separate same-specificity rules
   each setting it to a different subset of properties would have the later one in source order
   overwrite the earlier one entirely, leaving that property to snap instantly instead of
   animating (this is exactly what happens on the gallery/portfolio/products sections, which
   combine `openFullImage` with `hoverZoom` by default). */
.ls-image-lightbox-trigger img,
.ls-image-hover-zoom .ls-image,
.ls-image-hover-darken .ls-image {
  transition: opacity 0.2s ease, transform 0.7s ease, filter 0.7s ease;
}

.ls-image-hover-zoom:hover .ls-image {
  transform: scale(1.1);
}

.ls-image-hover-darken:hover .ls-image {
  filter: brightness(0.6);
}

/* === SEPARATOR === */
.ls-separator-wrapper {
  margin: 16px 0;
}

.ls-separator-mobile {
  display: block;
}

.ls-separator-desktop {
  display: none;
}

@media (min-width: 600px) {
  .ls-separator-mobile {
    display: none;
  }

  .ls-separator-desktop {
    display: block;
  }
}

/* "Ornament" style (SeparatorPropsInterface.style) — SeparatorView.vue renders the line itself
   with a gap in the middle (inline background gradient); this ::after fills that gap with a
   small rotated-square diamond, since inline :style can't target pseudo-elements. Sized off
   --ls-separator-ornament-size (width*3.5, set inline) so it scales with the "Grubość" slider
   like every other style. Deliberately allowed to overflow the thin line's own box (no
   overflow:hidden anywhere above) — that's what makes it read as a mark sitting on the line
   rather than being squashed into it. */
.ls-separator-mobile[data-style="ornament"],
.ls-separator-desktop[data-style="ornament"] {
  position: relative;
}

.ls-separator-mobile[data-style="ornament"]::after,
.ls-separator-desktop[data-style="ornament"]::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--ls-separator-ornament-size, 8px);
  height: var(--ls-separator-ornament-size, 8px);
  background: var(--ls-separator-color, currentColor);
  transform: translate(-50%, -50%) rotate(45deg);
}

/* === BACKGROUND GRADIENT (mobile fallback) === */
/* Gradient section/column backgrounds are desktop-only. Inline styles can't contain
   @media queries, so `.ls-bg-gradient` + this override collapses the gradient into a
   fully opaque solid fill of Color 1 below the phone breakpoint. `!important` beats the
   non-!important inline background-image/background-color set by sectionStylesUtils.ts
   and columnStylesUtils.ts. */
@media (max-width: 599.98px) {
  .ls-bg-gradient {
    background-image: var(--ls-bg-mobile-image, none) !important;
    background-color: var(--ls-bg-mobile-color, transparent) !important;
    backdrop-filter: none !important;
  }
}

/* === LINK LIST === */
.ls-link-list {
  width: 100%;
}

.ls-link-list-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ls-link-item {
  width: 100%;
  transition: opacity 0.2s;
  color: inherit;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 8px;
}

.ls-link-item:hover {
  opacity: 0.7;
}

/* === BUTTON === */
.ls-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 500;
  text-transform: none;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.25s ease;
  position: relative;
  overflow: hidden;
}

/* Ripple layer */
.ls-button::after {
  content: '';
  position: absolute;
  inset: 0;
  background: currentColor;
  opacity: 0;
  transition: opacity 0.2s ease;
  border-radius: inherit;
}

.ls-button:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15) !important;
}

.ls-button:hover::after {
  opacity: 0.08;
}

.ls-button:active {
  transform: translateY(0px) scale(0.97);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.1s ease;
}

.ls-button:active::after {
  opacity: 0.15;
}

/* === HEADINGS === */
h1 {
  letter-spacing: 0.00735em;
  margin: 0;
  padding: 8px 0;
}

h2 {
  letter-spacing: normal;
  margin: 0;
  padding: 7px 0;
}

h3 {
  letter-spacing: normal;
  margin: 0;
  padding: 6px 0;
}

h4 {
  letter-spacing: normal;
  margin: 0;
  padding: 5px 0;
}

h5 {
  letter-spacing: normal;
  margin: 0;
  padding: 4px 0;
}

h6 {
  letter-spacing: normal;
  margin: 0;
  padding: 2px 0;
}

/* === HEADER DECORATION ===
   HeaderPropsInterface.decoration is applied as data-decoration on the .ls-header element
   (the h1-h6 tag itself — HeaderView.vue is shared by the editor canvas and the published site,
   there's no separate string renderer like Form's renderForm.ts). 'none' (the default, and what
   pre-existing saved headers fall back to since they predate this field) matches no rule below,
   so it renders identically to a plain heading. decorationColor is carried as the
   --ls-header-decoration-color inline var (set in HeaderView.vue); every rule below falls back
   to the site's --main accent if that var is unset. Mirrors the .ls-form[data-field-style]
   convention above.

   All sizing below (width/height/margin/border/padding/border-radius) uses em, not px, so it
   scales with the header's own font-size — which HeaderView.vue sets inline per
   HeaderPropsInterface.size (see getHeaderSizeConfig in SizeTypeEnum.ts). ::before/::after
   inherit font-size from their host element, so no extra data-size wiring is needed: a bigger
   header size just means a bigger decoration. Values are tuned against the LG size's 2rem
   (32px) font-size — LG is createDefaultHeaderProps()'s default — so 1em here === 32px there. */
.ls-header[data-decoration]:not([data-decoration="none"]) {
  position: relative;
}

.ls-header[data-decoration="underline"]::after {
  content: '';
  display: block;
  width: 1.875em;
  height: 0.125em;
  margin: 0.3125em auto 0;
  border-radius: 0.0625em;
  background: var(--ls-header-decoration-color, var(--main));
}

.ls-header[data-decoration="quote"] {
  /* Makes room on the right so the corner glyph doesn't sit on top of the last letter. */
  padding-right: 0.5em;
}

.ls-header[data-decoration="quote"]::before {
  content: '„';
  position: absolute;
  top: -0.3em;
  right: 0;
  font-size: 1.6em;
  line-height: 1;
  font-family: Georgia, 'Times New Roman', serif;
  color: var(--ls-header-decoration-color, var(--main));
  pointer-events: none;
}

.ls-header[data-decoration="frame"]::before,
.ls-header[data-decoration="frame"]::after {
  content: '';
  display: block;
  height: 0.09375em;
  background: var(--ls-header-decoration-color, var(--main));
}

.ls-header[data-decoration="frame"]::before {
  margin-bottom: 0.375em;
}

.ls-header[data-decoration="frame"]::after {
  margin-top: 0.375em;
}

.ls-header[data-decoration="sideBar"] {
  padding-left: 0.5em;
}

.ls-header[data-decoration="sideBar"]::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.1em;
  bottom: 0.1em;
  width: 0.125em;
  border-radius: 0.0625em;
  background: var(--ls-header-decoration-color, var(--main));
}

.ls-header[data-decoration="highlight"] {
  display: inline-block;
  padding-left: 0.4em;
  padding-right: 0.4em;
  border-radius: 0.125em;
  background: color-mix(in srgb, var(--ls-header-decoration-color, var(--main)) 25%, transparent);
}

.ls-header[data-decoration="corners"] {
  padding: 0.325em 0.4125em;
}

.ls-header[data-decoration="corners"]::before,
.ls-header[data-decoration="corners"]::after {
  content: '';
  position: absolute;
  width: 0.875em;
  height: 0.875em;
  border: 0.09375em solid var(--ls-header-decoration-color, var(--main));
}

.ls-header[data-decoration="corners"]::before {
  top: 0;
  left: 0;
  border-right: none;
  border-bottom: none;
}

.ls-header[data-decoration="corners"]::after {
  bottom: 0;
  right: 0;
  border-left: none;
  border-top: none;
}

.ls-header[data-decoration="dot"]::after {
  content: '';
  display: block;
  width: 0.25em;
  height: 0.25em;
  margin: 0.375em auto 0;
  border-radius: 50%;
  background: var(--ls-header-decoration-color, var(--main));
}

/* Repeating wavy line via a masked shape (not a static-color background image) so it follows
   --ls-header-decoration-color like every other decoration here. */
.ls-header[data-decoration="wavy"]::after {
  content: '';
  display: block;
  width: 2.8125em;
  height: 0.375em;
  margin: 0.3125em auto 0;
  background-color: var(--ls-header-decoration-color, var(--main));
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 10'%3E%3Cpath d='M0 5 Q3.5 0 7 5 T14 5' fill='none' stroke='black' stroke-width='3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 10'%3E%3Cpath d='M0 5 Q3.5 0 7 5 T14 5' fill='none' stroke='black' stroke-width='3'/%3E%3C/svg%3E");
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  -webkit-mask-size: 0.5625em 0.375em;
  mask-size: 0.5625em 0.375em;
}

/* === TEXT SIZE CLASSES === */
.ls-text-subtitle1 {
  font-size: 1rem;
  line-height: 1.75rem;
  font-weight: 400;
  letter-spacing: 0.00937em;
}

.ls-text-body1 {
  font-size: 1rem;
  line-height: 1.5rem;
}

.ls-text-body2 {
  font-size: 0.875rem;
  line-height: 1.25rem;
}

/* === CONTAINER === */
.ls-container {
  margin: 0 auto;
  max-width: 1232px;
}

.ls-container--full-width {
  max-width: none;
}

/* === CAROUSEL === */
.ls-infinite-carousel-wrapper {
  width: 100%;
  overflow: hidden;
}

.ls-infinite-carousel-wrapper .ls-column-wrapper {
  padding-top: 3px;
  padding-bottom: 3px;
  margin-bottom: 10px;
}

.ls-infinite-carousel-container {
  width: 100%;
  overflow: hidden;
  position: relative;
}

.ls-infinite-carousel-track {
  display: flex;
  will-change: transform;
  transition: none;
}

/* === LIST === */
.ls-list-item {
  transition: all .2s;
  margin-bottom: 5px;
}

.ls-list-item:hover {
  font-weight: bold;
  cursor: pointer;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.ls-element ul,
.q-editor__content ul {
  list-style: disc;
  padding-left: 1.5em;
}

.ls-element ol,
.q-editor__content ol {
  list-style: decimal;
  padding-left: 1.5em;
}

.ls-menu-view ul,
.ls-link-list ul {
  list-style: none;
  padding-left: 0;
}

/* === GOOGLE MAP === */
.ls-google-map {
  max-width: 100%;
  border-radius: var(--radius);
  overflow: hidden;
  display: inline-block;
}

.ls-google-map-container {
  border-radius: var(--radius);
}

.ls-google-map-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  flex-direction: column;
  background-color: #f5f5f5;
  color: #9e9e9e;
  min-height: 400px;
  border-radius: var(--radius);
}

.ls-google-map-icon {
  width: 64px;
  height: 64px;
  fill: currentColor;
  margin-bottom: 16px;
}

.ls-google-map-fallback-text {
  font-size: 14px;
  margin-top: 8px;
}

.ls-google-map-address {
  font-size: 16px;
  font-weight: 500;
  margin-top: 12px;
  color: #666;
}

/* === YOUTUBE === */
.ls-youtube {
  max-width: 100%;
  border-radius: var(--radius);
  overflow: hidden;
  display: inline-block;
}

.ls-youtube-iframe {
  border-radius: var(--radius);
  display: block;
}

.ls-youtube-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  flex-direction: column;
  background-color: #f5f5f5;
  color: #9e9e9e;
  min-height: 400px;
  border-radius: var(--radius);
}

.ls-youtube-icon {
  width: 64px;
  height: 64px;
  fill: currentColor;
  margin-bottom: 16px;
}

.ls-youtube-fallback-text {
  font-size: 14px;
  margin-top: 8px;
}

/* === UTILITIES === */
.ls-radius {
  border-radius: var(--radius);
}

.ls-nav-bar {
  width: 100%;
  z-index: 1000;
}

.ls-element {
  margin: var(--default-spacing) 0;
  padding: 0 calc(var(--default-spacing) / 2);
}

.ls-default-space {
  margin-top: calc(var(--default-spacing) / 2);
  margin-bottom: calc(var(--default-spacing) / 2);
}

.ls-nav-bar .ls-element {
  margin: 4px 0 !important;
}

/* Countdown Timer Sizes */
.ls-countdown-size-xs { font-size: 1.5rem; line-height: 1.6rem; }
.ls-countdown-size-sm { font-size: 2rem; line-height: 2.2rem; }
.ls-countdown-size-md { font-size: 2.8rem; line-height: 3rem; }
.ls-countdown-size-lg { font-size: 3.5rem; line-height: 3.8rem; }
.ls-countdown-size-xl { font-size: 5rem; line-height: 5rem; }

.ls-countdown-label-xs { font-size: 0.875rem; line-height: 1.25rem; }
.ls-countdown-label-sm { font-size: 1rem; line-height: 1.5rem; }
.ls-countdown-label-md { font-size: 1.2rem; line-height: 1.6rem; }
.ls-countdown-label-lg { font-size: 1.5rem; line-height: 1.8rem; }
.ls-countdown-label-xl { font-size: 1.8rem; line-height: 2rem; }

/* Countdown Timer */
.ls-countdown-container {
  text-align: center;
}

.ls-countdown-label {
  margin-bottom: 8px;
  opacity: 0.8;
}

.ls-countdown-timer {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 4px;
  font-weight: bold;
  font-variant-numeric: tabular-nums;
}

.ls-countdown-unit {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.ls-countdown-value {
  line-height: 1;
}

.ls-countdown-suffix {
  font-size: 0.35em;
  font-weight: normal;
  opacity: 0.7;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.ls-countdown-separator {
  line-height: 1;
  opacity: 0.5;
}

/* ===========================
   Hero Image Carousel (Slideshow)
   =========================== */

.ls-slideshow {
  position: relative;
  overflow: hidden;
  width: 100%;
}

.ls-slideshow-track {
  display: flex;
  transition: transform 0.6s ease-in-out;
  will-change: transform;
}

/* Each column becomes a full-width slide */
.ls-slideshow-track > .ls-column-wrapper {
  min-width: 100% !important;
  flex: 0 0 100% !important;
  width: 100%;
}

.ls-slideshow-dots {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  z-index: 10;
}

.ls-slideshow-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  border: 2px solid rgba(255, 255, 255, 0.85);
  cursor: pointer;
  transition: background 0.3s;
  padding: 0;
}

.ls-slideshow-dot.active {
  background: rgba(255, 255, 255, 1);
}

/* === LOGO === */
.ls-logo-view {
  display: inline-flex;
  align-items: center;
}

/* Allow element containing menu to expand beyond column width */
.ls-element:has(.ls-menu-view) {
  width: fit-content;
  min-width: 100%;
}

.ls-menu-view {
  display: flex;
  align-items: center;
  min-width: 100%;
  width: fit-content;
}

/* Menu alignment based on column alignment */
.ls-items-start .ls-menu-view {
  justify-content: flex-start;
}

.ls-items-end .ls-menu-view {
  justify-content: flex-end;
}

.ls-items-center .ls-menu-view {
  justify-content: center;
}

.ls-nav-menu {
  display: none;
  align-items: center;
}

.ls-nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

@media (min-width: 600px) {
  .ls-nav-menu {
    display: flex;
  }
}

.ls-nav-parent {
  position: relative;
  cursor: pointer;
  transition: opacity 0.2s;
  flex-shrink: 0;
}

.ls-nav-parent-text {
  display: block;
  padding: 10px 18px;
  white-space: nowrap;
  font-weight: 900;
  text-decoration: none;
  color: inherit;
}

.ls-nav-dropdown {
  list-style: none;
  margin: 0;
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  padding: 8px 0;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 1001;
  font-size: 14px;
}

.ls-nav-parent:hover .ls-nav-dropdown {
  display: flex;
  flex-direction: column;
}

.ls-nav-child {
  text-decoration: none;
  white-space: nowrap;
  position: relative;
  display: block;
  text-align: start;
}

.ls-nav-child a {
  display: block;
  padding: 10px 16px;
  text-decoration: none;
  color: inherit;
  font-weight: 600;
}

.ls-nav-menu .ls-nav-list {
  position: relative;
  z-index: 10;
}

.ls-nav-parent {
  position: relative;
}

/* Mobile menu styles */
.ls-mobile-menu {
  position: relative;
}

@media (min-width: 600px) {
  .ls-mobile-menu {
    display: none;
  }
}

/* Border is meant to separate desktop nav items; hide it once the mobile menu button takes over */
@media (max-width: 599.98px) {
  .ls-menu-view {
    border: none !important;
  }
}

.ls-mobile-menu-button {
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ls-mobile-menu-dropdown {
  list-style: none;
  margin: 0;
  position: fixed;
  left: 0;
  right: 0;
  width: 100vw;
  text-align: center;
  padding: 12px;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  z-index: 1000;
}

.ls-mobile-menu-item {
  margin-bottom: 8px;
}

.ls-mobile-parent-text {
  display: block;
  padding: 8px 16px;
  text-decoration: none;
  font-weight: 900;
}

.ls-mobile-children {
  list-style: none;
  margin: 0;
  padding: 0;
  padding-left: 12px;
}

.ls-mobile-child-text {
  display: block;
  padding: 10px 16px;
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}

/* === MENU HOVER EFFECTS === */
/* Applied to both top-level items and dropdown/mobile children via [data-hover-effect] on .ls-menu-view */

.ls-menu-view[data-hover-effect] .ls-nav-parent-text,
.ls-menu-view[data-hover-effect] .ls-nav-child-text,
.ls-menu-view[data-hover-effect] .ls-mobile-parent-text,
.ls-menu-view[data-hover-effect] .ls-mobile-child-text {
  position: relative;
}


/* Underline slide: accent line grows in under the text, flashes thicker on click */
.ls-menu-view[data-hover-effect="underline"] .ls-nav-parent-text::after,
.ls-menu-view[data-hover-effect="underline"] .ls-nav-child-text::after,
.ls-menu-view[data-hover-effect="underline"] .ls-mobile-parent-text::after,
.ls-menu-view[data-hover-effect="underline"] .ls-mobile-child-text::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 2px;
  background: currentColor;
  opacity: 0.85;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease, height 0.15s ease, opacity 0.15s ease;
}

@media (hover: hover) {
  .ls-menu-view[data-hover-effect="underline"] .ls-nav-parent-text:hover::after,
  .ls-menu-view[data-hover-effect="underline"] .ls-nav-child-text:hover::after,
  .ls-menu-view[data-hover-effect="underline"] .ls-mobile-parent-text:hover::after,
  .ls-menu-view[data-hover-effect="underline"] .ls-mobile-child-text:hover::after {
    transform: scaleX(1);
  }
}

.ls-menu-view[data-hover-effect="underline"] .ls-nav-parent-text:active::after,
.ls-menu-view[data-hover-effect="underline"] .ls-nav-child-text:active::after,
.ls-menu-view[data-hover-effect="underline"] .ls-mobile-parent-text:active::after,
.ls-menu-view[data-hover-effect="underline"] .ls-mobile-child-text:active::after {
  transform: scaleX(1);
  height: 3px;
  opacity: 1;
}

/* Background fill: full-rectangle highlight fades in behind the text, compresses on click */
.ls-menu-view[data-hover-effect="pill"] .ls-nav-parent-text,
.ls-menu-view[data-hover-effect="pill"] .ls-nav-child-text,
.ls-menu-view[data-hover-effect="pill"] .ls-mobile-parent-text,
.ls-menu-view[data-hover-effect="pill"] .ls-mobile-child-text {
  transition: background-color 0.2s ease, transform 0.12s ease;
}

@media (hover: hover) {
  .ls-menu-view[data-hover-effect="pill"] .ls-nav-parent-text:hover,
  .ls-menu-view[data-hover-effect="pill"] .ls-nav-child-text:hover,
  .ls-menu-view[data-hover-effect="pill"] .ls-mobile-parent-text:hover,
  .ls-menu-view[data-hover-effect="pill"] .ls-mobile-child-text:hover {
    background-color: color-mix(in srgb, currentColor 15%, transparent);
  }
}

.ls-menu-view[data-hover-effect="pill"] .ls-nav-parent-text:active,
.ls-menu-view[data-hover-effect="pill"] .ls-nav-child-text:active,
.ls-menu-view[data-hover-effect="pill"] .ls-mobile-parent-text:active,
.ls-menu-view[data-hover-effect="pill"] .ls-mobile-child-text:active {
  background-color: color-mix(in srgb, currentColor 25%, transparent);
  transform: scale(0.95);
}

/* Lift & scale: text lifts and grows on hover, compresses on click */
.ls-menu-view[data-hover-effect="lift"] .ls-nav-parent-text,
.ls-menu-view[data-hover-effect="lift"] .ls-nav-child-text,
.ls-menu-view[data-hover-effect="lift"] .ls-mobile-parent-text,
.ls-menu-view[data-hover-effect="lift"] .ls-mobile-child-text {
  transition: transform 0.2s ease;
}

@media (hover: hover) {
  .ls-menu-view[data-hover-effect="lift"] .ls-nav-parent-text:hover,
  .ls-menu-view[data-hover-effect="lift"] .ls-nav-child-text:hover,
  .ls-menu-view[data-hover-effect="lift"] .ls-mobile-parent-text:hover,
  .ls-menu-view[data-hover-effect="lift"] .ls-mobile-child-text:hover {
    transform: translateY(-2px) scale(1.05);
  }
}

.ls-menu-view[data-hover-effect="lift"] .ls-nav-parent-text:active,
.ls-menu-view[data-hover-effect="lift"] .ls-nav-child-text:active,
.ls-menu-view[data-hover-effect="lift"] .ls-mobile-parent-text:active,
.ls-menu-view[data-hover-effect="lift"] .ls-mobile-child-text:active {
  transform: translateY(0) scale(0.95);
  transition: transform 0.08s ease;
}

/* Spotlight: hovered item stays full brightness, siblings within the same list dim */
.ls-menu-view[data-hover-effect="spotlight"] .ls-nav-parent-text,
.ls-menu-view[data-hover-effect="spotlight"] .ls-nav-child-text,
.ls-menu-view[data-hover-effect="spotlight"] .ls-mobile-parent-text,
.ls-menu-view[data-hover-effect="spotlight"] .ls-mobile-child-text {
  transition: opacity 0.2s ease, filter 0.15s ease;
}

@media (hover: hover) {
  .ls-menu-view[data-hover-effect="spotlight"] .ls-nav-list:hover .ls-nav-parent-text,
  .ls-menu-view[data-hover-effect="spotlight"] .ls-nav-dropdown:hover .ls-nav-child-text {
    opacity: 0.5;
  }

  .ls-menu-view[data-hover-effect="spotlight"] .ls-nav-list .ls-nav-parent-text:hover,
  .ls-menu-view[data-hover-effect="spotlight"] .ls-nav-dropdown .ls-nav-child-text:hover {
    opacity: 1;
  }
}

.ls-menu-view[data-hover-effect="spotlight"] .ls-nav-parent-text:active,
.ls-menu-view[data-hover-effect="spotlight"] .ls-nav-child-text:active,
.ls-menu-view[data-hover-effect="spotlight"] .ls-mobile-parent-text:active,
.ls-menu-view[data-hover-effect="spotlight"] .ls-mobile-child-text:active {
  opacity: 1;
  filter: brightness(1.3);
}

.ls-link-list button {
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
}

/* === FORM === */
.ls-form {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.ls-form-field {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.ls-form-required {
  color: #d32f2f;
  margin-left: 2px;
}

.ls-form-input,
.ls-form-select,
.ls-form-textarea {
  outline: none;
  width: 100%;
  padding: 10px 14px;
  font-size: 15px;
  font-family: var(--font-family, sans-serif);
  box-sizing: border-box;
  transition: border-color 0.2s, border-width 0.2s, background-color 0.2s, box-shadow 0.2s, padding 0.2s;
}

.ls-form-select {
  cursor: pointer;
}

.ls-form-textarea {
  resize: vertical;
  min-height: 90px;
}

.ls-form-input::placeholder,
.ls-form-textarea::placeholder {
  color: var(--ls-form-text-color, inherit);
}

/* === FORM FIELD STYLE VARIANTS ===
   FormPropsInterface.fieldStyle ('bordered' | 'underline' | 'filled') is applied as
   data-field-style on the <form class="ls-form"> element - by the Vue components
   (FormEditor.vue/FormView.vue) AND by the static-site renderer (site-renderer/src/
   renderForm.ts), which share this same CSS. Only the accent color is dynamic (set inline
   as --ls-form-border-color by useFormFieldStyle.ts / renderForm.ts) - the structural look
   and its click/focus effect are plain CSS, same convention as .ls-menu-view[data-hover-effect]
   below. */
.ls-form[data-field-style="bordered"] .ls-form-input,
.ls-form[data-field-style="bordered"] .ls-form-select,
.ls-form[data-field-style="bordered"] .ls-form-textarea {
  border: 1px solid var(--ls-form-border-color, rgba(128, 128, 128, 0.5));
  background: transparent;
}

.ls-form[data-field-style="bordered"] .ls-form-input:focus,
.ls-form[data-field-style="bordered"] .ls-form-select:focus,
.ls-form[data-field-style="bordered"] .ls-form-textarea:focus {
  box-shadow: 0 0 0 2px var(--ls-form-border-color, rgba(128, 128, 128, 0.5));
}

.ls-form[data-field-style="underline"] .ls-form-input,
.ls-form[data-field-style="underline"] .ls-form-select,
.ls-form[data-field-style="underline"] .ls-form-textarea {
  border: none;
  border-bottom: 2px solid var(--ls-form-border-color, rgba(128, 128, 128, 0.5));
  border-radius: 0;
  background: transparent;
  padding-left: 2px;
  padding-right: 2px;
}

.ls-form[data-field-style="underline"] .ls-form-input:focus,
.ls-form[data-field-style="underline"] .ls-form-select:focus,
.ls-form[data-field-style="underline"] .ls-form-textarea:focus {
  border-bottom-width: 4px;
}

.ls-form[data-field-style="filled"] .ls-form-input,
.ls-form[data-field-style="filled"] .ls-form-select,
.ls-form[data-field-style="filled"] .ls-form-textarea {
  border: 1px solid transparent;
  background: color-mix(in srgb, var(--ls-form-border-color, rgba(128, 128, 128, 0.5)) 12%, transparent);
}

.ls-form[data-field-style="filled"] .ls-form-input:focus,
.ls-form[data-field-style="filled"] .ls-form-select:focus,
.ls-form[data-field-style="filled"] .ls-form-textarea:focus {
  background: color-mix(in srgb, var(--ls-form-border-color, rgba(128, 128, 128, 0.5)) 22%, transparent);
}

/* === FORM COLUMN LAYOUT ===
   FormPropsInterface.columns (1-4) is applied as data-columns on the same <form class="ls-form">
   element as data-field-style above, by the same three consumers (FormEditor.vue/FormView.vue/
   renderForm.ts). 1 column (the default) keeps the original flex column layout untouched - no
   rule needed. .ls-form-field-full (set per-field via FormFieldInterface.fullWidth, applied to
   .ls-form-field in the *View.vue components and to .form-editor-field in FormEditor.vue) makes
   that field span the full row regardless of column count; the submit button always spans the
   full row. */
.ls-form:is([data-columns="2"], [data-columns="3"], [data-columns="4"]) {
  display: grid;
  column-gap: var(--default-spacing);
}

.ls-form[data-columns="2"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.ls-form[data-columns="3"] {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.ls-form[data-columns="4"] {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.ls-form:is([data-columns="2"], [data-columns="3"], [data-columns="4"]) > :is(.ls-form-submit, .ls-form-field-full) {
  grid-column: 1 / -1;
}

@media (max-width: 768px) {
  .ls-form:is([data-columns="2"], [data-columns="3"], [data-columns="4"]) {
    display: flex;
    flex-direction: column;
  }
}

.ls-form-radio-group,
.ls-form-checkbox-group {
  display: flex;
  flex-direction: column;
  gap: var(--default-spacing);
}

.ls-form-radio-group.ls-form-options-horizontal,
.ls-form-checkbox-group.ls-form-options-horizontal {
  flex-direction: row;
  flex-wrap: wrap;
}

.ls-form-radio-option,
.ls-form-checkbox-option {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ls-form-radio-option:has(input:disabled),
.ls-form-checkbox-option:has(input:disabled) {
  cursor: not-allowed;
}

.ls-form-radio-option.ls-form-option-stacked,
.ls-form-checkbox-option.ls-form-option-stacked {
  flex-direction: column;
  align-items: flex-start;
}

.ls-form-option-control-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ls-form-radio-box {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
  border: 2px solid #555;
  border-radius: 50%;
  background: transparent;
  position: relative;
}

.ls-form-radio-box:disabled {
  cursor: not-allowed;
}

.ls-form-radio-box:checked {
  border-color: #1565c0;
}

.ls-form-radio-box:checked::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #1565c0;
  transform: translate(-50%, -50%);
}

.ls-form-checkbox-box {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
  border: 2px solid #555;
  border-radius: 4px;
  background: transparent;
  position: relative;
}

.ls-form-checkbox-box:disabled {
  cursor: not-allowed;
}

.ls-form-checkbox-box:checked {
  background: #1565c0;
  border-color: #1565c0;
}

.ls-form-checkbox-box:checked::after {
  content: '';
  position: absolute;
  top: 45%;
  left: 50%;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: translate(-50%, -60%) rotate(45deg);
}

.ls-form-option-image {
  width: 32px;
  height: 32px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
}

.ls-form-submit {
  transition: opacity 0.2s;
}

.ls-form-submit:hover {
  opacity: 0.85;
}

.ls-form-acceptance-option {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.ls-form-acceptance-option:has(input:disabled) {
  cursor: not-allowed;
}

/* === BLOG === */
.ls-blog-view {
  width: 100%;
}

.ls-blog-list {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.ls-blog-list .ls-blog-card {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.ls-blog-list .ls-blog-thumbnail,
.ls-blog-list .ls-blog-thumbnail-placeholder {
  width: 200px;
  height: 150px;
  flex-shrink: 0;
  border-radius: var(--radius, 4px);
  object-fit: cover;
}

.ls-blog-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 32px;
}

.ls-blog-grid-2 .ls-blog-thumbnail,
.ls-blog-grid-2 .ls-blog-thumbnail-placeholder {
  width: 100%;
  height: 160px;
  border-radius: 4px 4px 0 0;
}

.ls-blog-cards-large {
  display: flex;
  flex-direction: column;
  gap: 48px;
}

.ls-blog-cards-large .ls-blog-thumbnail,
.ls-blog-cards-large .ls-blog-thumbnail-placeholder {
  width: 100%;
  height: 240px;
  border-radius: 4px 4px 0 0;
}

.ls-blog-thumbnail-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #424242;
  color: #757575;
}

.ls-blog-placeholder-icon {
  width: 32px;
  height: 32px;
}

.ls-blog-card-body {
  padding: 8px;
}

.ls-blog-title {
  text-decoration: none;
  color: inherit;
  display: block;
  font-weight: 500;
}

.ls-blog-title:hover {
  text-decoration: underline;
}

.ls-blog-title-xs { font-size: 1.5rem; line-height: 1.167; }
.ls-blog-title-sm { font-size: 2.125rem; line-height: 1.235; }
.ls-blog-title-md { font-size: 3rem; line-height: 1.167; }
.ls-blog-title-lg { font-size: 3.75rem; line-height: 1.2; }
.ls-blog-title-xl { font-size: 6rem; line-height: 1.167; }

.ls-blog-date {
  font-size: 0.75rem;
  color: #9e9e9e;
  margin-top: 4px;
}

.ls-blog-summary {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 10px 0;
}

.ls-blog-read-more {
  margin-top: 8px;
}

/* === CHIPS ELEMENT (ElementTypeEnum.CHIPS — src/spa/builder/elements/chips) === */
/* Structural only — color/padding/font-size are per-instance (size + colors are configurable
   per element) and applied inline by ChipsView.vue, same convention as ls-button/ButtonView.vue.
   justify-content/max-width/margin stay here (not left to the column's align controls) because
   this is a block-level flex-wrap container — the column's horizontalAlign/textAlign only center
   inline-level content (see ls-inline-flex/Buttons), so they have no effect on how wrapped chip
   rows position themselves inside this full-width box. */
.ls-chip-cloud {
  max-width: 960px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  align-items: center;
}

.ls-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 999px;
  font-weight: 700;
  white-space: nowrap;
}


/* === Public Export Styles === */
/* === Base Reset === */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  overflow-x: hidden;
}

body {
  font-family: var(--font-family, 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
  background-color: var(--bg-color, #ffffff);
  color: var(--text-color, #000000);
  min-width: 100px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  line-height: 1.5;
  font-size: 16px;
  letter-spacing: var(--body-letter-spacing, .6px);
}

.ls-nav-bar--standard {
  position: relative;
}

.ls-nav-bar--sticky {
  position: sticky;
  top: 0;
}

.ls-nav-bar--compress {
  position: sticky;
  top: 0;
}

.ls-nav-bar--compress.ls-nav-bar--overlapping {
  top: 0;
  width: 100%;
  z-index: 100;
}

.ls-page--home .ls-nav-bar--compress.ls-nav-bar--overlapping {
  position: fixed;
}


.ls-nav-bar--compress section.section {
  transition: background-color 0.4s ease;
}

.ls-nav-bar--compress .ls-container {
  padding-block: 6px;
  transition: padding-block 0.4s ease;
}

.ls-nav-bar--compress.ls-nav-bar--scrolled .ls-container {
  padding-block: 0;
}

main {
  flex: 1;
  overflow-x: hidden;
}

a {
  text-decoration: none;
  color: inherit;
}

p { margin: 8px 0; }

/* === Cookie Consent === */
.ls-cc-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: #1a1a2e;
  color: #fff;
  padding: 16px 24px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
  z-index: 9999;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.3);
  transform: translateY(100%);
  transition: transform 0.3s ease-out;
}

.ls-cc-banner.ls-cc-visible {
  transform: translateY(0);
}

.ls-cc-banner.ls-cc-hidden {
  display: none;
}

.ls-cc-text {
  flex: 1;
  min-width: 260px;
  font-size: 14px;
  line-height: 1.5;
}

.ls-cc-link {
  color: var(--main, #027be3);
  text-decoration: underline;
  margin-left: 4px;
}

.ls-cc-link:hover {
  opacity: 0.8;
}

.ls-cc-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.ls-cc-btn {
  padding: 9px 20px;
  border-radius: var(--radius, 8px);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.2s;
  white-space: nowrap;
  background: var(--main, #027be3);
  color: #fff;
  border: 2px solid var(--main, #027be3);
}

.ls-cc-btn:hover {
  opacity: 0.88;
}

.ls-cc-panel {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 10000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.ls-cc-panel-hidden {
  display: none;
}

.ls-cc-panel-inner {
  background: #1a1a2e;
  color: #fff;
  width: 100%;
  max-width: 600px;
  max-height: 90vh;
  overflow-y: auto;
  border-radius: 12px 12px 0 0;
  padding: 24px;
}

.ls-cc-panel-title {
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 20px;
}

.ls-cc-category {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.ls-cc-category-info {
  flex: 1;
}

.ls-cc-category-name {
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 4px;
}

.ls-cc-category-desc {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.65);
  line-height: 1.4;
}

.ls-cc-always-on {
  font-size: 12px;
  color: var(--main, #027be3);
  white-space: nowrap;
  padding-top: 2px;
  font-weight: 600;
}

.ls-cc-toggle {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 24px;
  flex-shrink: 0;
  cursor: pointer;
}

.ls-cc-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
}

.ls-cc-toggle-track {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 24px;
  transition: 0.2s;
}

.ls-cc-toggle input:checked + .ls-cc-toggle-track {
  background: var(--main, #027be3);
}

.ls-cc-toggle-track::before {
  content: '';
  position: absolute;
  width: 18px;
  height: 18px;
  left: 3px;
  bottom: 3px;
  background: #fff;
  border-radius: 50%;
  transition: 0.2s;
}

.ls-cc-toggle input:checked + .ls-cc-toggle-track::before {
  transform: translateX(20px);
}

.ls-cc-panel-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: 16px;
}

.ls-cc-cookie-details {
  margin-top: 8px;
}

.ls-cc-cookie-summary {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.45);
  cursor: pointer;
  list-style: none;
  padding: 2px 0;
  user-select: none;
}

.ls-cc-cookie-summary::-webkit-details-marker {
  display: none;
}

.ls-cc-cookie-summary::marker {
  display: none;
}

.ls-cc-cookie-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 6px;
  font-size: 11px;
}

.ls-cc-cookie-table th {
  text-align: left;
  color: rgba(255, 255, 255, 0.4);
  font-weight: 500;
  padding: 3px 6px 3px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.ls-cc-cookie-table td {
  padding: 5px 6px 5px 0;
  color: rgba(255, 255, 255, 0.7);
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  vertical-align: top;
  line-height: 1.3;
}

.ls-cc-cookie-table tr:last-child td {
  border-bottom: none;
}

.ls-cc-no-cookies {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.4);
  margin: 6px 0 0;
}

@media (max-width: 600px) {
  .ls-cc-banner {
    flex-direction: column;
    text-align: center;
    padding: 16px;
  }
  .ls-cc-text {
    min-width: auto;
  }
  .ls-cc-actions {
    width: 100%;
    justify-content: center;
  }
  .ls-cc-btn {
    width: 100%;
  }
  .ls-cc-panel-inner {
    border-radius: 0;
    max-height: 100vh;
  }
}
