/* Public styles for project pages */

/* WCAG 2.1 AA: a guaranteed, high-contrast keyboard focus indicator on every interactive element
   (Bootstrap's is theme-dependent and can vanish on custom palettes). :focus-visible = keyboard only,
   so it never shows on mouse click. The paired light/dark outline stays visible on any background. */
:focus-visible {
    outline: 2px solid #1a73e8;
    outline-offset: 2px;
    box-shadow: 0 0 0 4px rgba(255, 255, 255, .85);
    border-radius: 2px;
}

body {
    flex-grow: 1;
    width: 100%;
    /*min-height: 100%;*/
    display: flex;
    flex-direction: column;
}

.r-block { margin-bottom: 0; }

/* ─────────────────────────────────────────────────────────────────────────────
   MODERN BASE - typography scale + soft depth. Lives here (not in the per-project
   theme CSS) because public.css loads AFTER Bootstrap on published pages AND is
   @imported by the builder's canvas.css, so published output and the editor canvas
   stay in sync (true WYSIWYG). Static, theme-independent.
   ───────────────────────────────────────────────────────────────────────────── */

/* Fluid type scale: confident heading sizes with tighter leading + tracking. No !important, so any
   explicit per-component size (inline styles / .fs-* / .display-* utilities) still wins - this only
   refines headings that don't set their own. */
h1 { font-size: clamp(2rem, 1.35rem + 2.2vw, 2.85rem); line-height: 1.14; letter-spacing: -0.018em; }
h2 { font-size: clamp(1.55rem, 1.2rem + 1.4vw, 2.1rem); line-height: 1.2; letter-spacing: -0.014em; }
h3 { font-size: clamp(1.3rem, 1.12rem + 0.6vw, 1.55rem); line-height: 1.26; letter-spacing: -0.01em; }
h4, h5, h6 { line-height: 1.32; letter-spacing: -0.006em; }
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 { line-height: 1.06; letter-spacing: -0.02em; }
p { line-height: 1.65; }
.lead { line-height: 1.6; }

/* ─────────────────────────────────────────────────────────────────────────────
   THE NAMED TYPE SCALE.

   The element rules above size h1/h2/h3. They do nothing for a section that sets
   its own size, which is most of them: a section author reaches for clamp() and
   invents a curve, so the catalogue carries dozens of unrelated ones and no two
   bands share a rhythm. Four named steps, as custom properties AND as classes,
   so a section can ask for "display" instead of guessing three numbers.

   Sizes are the same curve the element rules use, extended at the top for hero
   type. Nothing here is !important: an explicit inline size still wins, which is
   what lets an owner resize a heading in the builder.
   ───────────────────────────────────────────────────────────────────────────── */
:root {
    --wk-text-display: clamp(2.6rem, 1.6rem + 3.6vw, 4.5rem);
    --wk-text-title:   clamp(1.9rem, 1.4rem + 1.9vw, 2.9rem);
    --wk-text-heading: clamp(1.3rem, 1.12rem + 0.6vw, 1.55rem);
    --wk-text-body:    clamp(1rem, 0.97rem + 0.15vw, 1.125rem);
    --wk-text-label:   .78rem;
}

.wk-display { font-size: var(--wk-text-display); line-height: 1.02; letter-spacing: -.03em; }
.wk-title   { font-size: var(--wk-text-title);   line-height: 1.1;  letter-spacing: -.02em; }
.wk-heading { font-size: var(--wk-text-heading); line-height: 1.26; letter-spacing: -.01em; }
.wk-body    { font-size: var(--wk-text-body);    line-height: 1.65; }
/* The tracked-out micro-label above a band. Uppercase is applied here rather than
   typed in, so the words stay readable in the builder and in a screen reader. */
.wk-label {
    font-size: var(--wk-text-label);
    letter-spacing: .18em;
    text-transform: uppercase;
    font-weight: 700;
}

/* ─────────────────────────────────────────────────────────────────────────────
   BOUNDED MEDIA.

   A section that sets an aspect ratio for the photograph it shipped, and then
   receives a different one, grows to fit: a 4/5 portrait block drawn for a
   workshop scene took a product cut out on white, rendered 875px tall at desktop
   width, and left the paragraph beside it floating in 393px of empty page. The
   block has to bound the picture, not the other way round.

   `cover` crops to fill and is right for a scene. `contain` fits the whole thing
   in and is right for a cutout, whose edges are the subject - cropping a floor
   grinder through its own base is worse than the letterboxing.
   ───────────────────────────────────────────────────────────────────────────── */
.wk-media { display: block; width: 100%; overflow: hidden; }
.wk-media > img, .wk-media > video { display: block; width: 100%; height: 100%; }

.wk-media-21x9 { aspect-ratio: 21 / 9; }
.wk-media-16x9 { aspect-ratio: 16 / 9; }
.wk-media-3x2  { aspect-ratio: 3 / 2; }
.wk-media-4x3  { aspect-ratio: 4 / 3; }
.wk-media-1x1  { aspect-ratio: 1 / 1; }
.wk-media-4x5  { aspect-ratio: 4 / 5; }

.wk-media-cover > img, .wk-media-cover > video { object-fit: cover; object-position: center; }
.wk-media-contain > img, .wk-media-contain > video { object-fit: contain; }
/* A cutout was shot on white, so it needs a white plate under it whatever the band behind is. */
.wk-media-plate { background: #fff; }
.wk-media-plate > img { padding: 6%; }

/* ─────────────────────────────────────────────────────────────────────────────
   INTERACTIVE DEFAULTS.

   The focus ring at the top of this file is the accessibility floor. This is the
   other half: a press that answers the finger, and an optional lift on something
   clickable. Both are transform-only so they never reflow, and both stand down
   under prefers-reduced-motion - an animation that answers a person's own action
   is the kind worth keeping, but it is still theirs to switch off.

   Press is global on .btn because it is the one interaction every page has and
   the feedback is currently missing everywhere. Lift is opt-in (.wk-lift) rather
   than applied to every .card, because plenty of designs already animate their
   own and two transforms fighting reads as a fault.
   ───────────────────────────────────────────────────────────────────────────── */
.btn { transition: transform .12s ease, box-shadow .16s ease, background-color .16s ease, border-color .16s ease; }
.btn:active:not(:disabled):not(.disabled) { transform: scale(.97); }

.wk-lift { transition: transform .2s ease, box-shadow .2s ease; }
.wk-lift:hover, .wk-lift:focus-within { transform: translateY(-3px); box-shadow: 0 14px 34px rgba(16,24,40,.10), 0 4px 8px rgba(16,24,40,.06); }
.wk-lift > .wk-media > img { transition: transform .35s ease; }
.wk-lift:hover > .wk-media > img { transform: scale(1.04); }

@media (prefers-reduced-motion: reduce) {
    .btn, .wk-lift, .wk-lift > .wk-media > img { transition: none; }
    .btn:active:not(:disabled):not(.disabled),
    .wk-lift:hover, .wk-lift:focus-within,
    .wk-lift:hover > .wk-media > img { transform: none; }
}

/* Consistent rounding on form controls (matches buttons/cards via the theme radius). */
.form-control, .form-select, .input-group-text { border-radius: var(--theme-radius, 8px); }

/* Modern soft shadow scale - layered, low-alpha depth instead of Bootstrap's harder defaults. */
.shadow-sm { box-shadow: 0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06) !important; }
.shadow    { box-shadow: 0 4px 12px rgba(16,24,40,.06), 0 2px 4px rgba(16,24,40,.05) !important; }
.shadow-lg { box-shadow: 0 14px 34px rgba(16,24,40,.10), 0 4px 8px rgba(16,24,40,.06) !important; }

/* Global <main> body frame (header → main → footer skeleton). Baseline height so an empty/sparse
   page keeps a generous, droppable body area in the builder and the footer never rides up under the
   header. Bounded vh so it fills most of the viewport without being absurd on tall/short screens.
   A user-set min-height (property panel → inline style) overrides this. */
.r-main { min-height: 240px; }

/* Base Component Styles */
.image-overlay-layer { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.shape-divider-top, .shape-divider-bottom { position: absolute; left: 0; width: 100%; overflow: hidden; line-height: 0; z-index: 5; pointer-events: none; }
.shape-divider-top { top: 0; transform: translateY(-99%); }
.shape-divider-bottom { bottom: 0; transform: translateY(99%); }

/* Text / Paragraph Styles */
p.has-drop-cap::first-letter { float: left; font-size: 3.5em; line-height: 0.8; font-weight: 700; margin-right: 0.1em; color: var(--bs-primary, #4f46e5); }
p.text-cols-2 { column-count: 2; column-gap: 2rem; }
p.text-cols-3 { column-count: 3; column-gap: 2rem; }

/* Blockquote Styles */
blockquote.bq-border-left { border-left: 4px solid var(--bs-primary, #4f46e5); padding: 1rem 1.5rem; border-radius: 0 8px 8px 0; background: rgba(var(--bs-primary-rgb, 79,70,229), 0.04); }
blockquote.bq-border-top { border-top: 4px solid var(--bs-primary, #4f46e5); padding: 1.25rem 1.5rem; border-radius: 0 0 8px 8px; background: rgba(var(--bs-primary-rgb, 79,70,229), 0.04); }
blockquote.bq-card { padding: 1.5rem; border-radius: 12px; background: var(--bs-tertiary-bg, #f8f9fa); border: 1px solid var(--bs-border-color, #dee2e6); box-shadow: 0 2px 8px rgba(0,0,0,0.04); }
blockquote.bq-large { padding: 2rem 1.5rem; font-size: 1.25em; font-style: italic; text-align: center; }
blockquote.bq-minimal { padding: 0.75rem 0; border: none; background: none; }
blockquote.bq-has-icon { position: relative; padding-top: 2.5rem; }
blockquote.bq-has-icon::before { content: "\201C"; position: absolute; top: 0; left: 0.5rem; font-family: Georgia, serif; font-weight: 700; color: var(--bs-primary, #4f46e5); opacity: 0.2; line-height: 1; }
blockquote.bq-has-icon.bq-icon-sm::before { font-size: 3rem; }
blockquote.bq-has-icon.bq-icon-md::before { font-size: 4.5rem; }
blockquote.bq-has-icon.bq-icon-lg::before { font-size: 6rem; }
blockquote.bq-large.bq-has-icon::before { left: 50%; transform: translateX(-50%); }

/* Component Specific Logic Styles */
.pricing-featured-badge { position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%); background: var(--bs-primary); color: white; padding: 4px 15px; border-radius: 50px; font-size: 0.7rem; font-weight: 800; letter-spacing: 1px; box-shadow: 0 4px 10px rgba(var(--bs-primary-rgb), 0.3); }
.pricing-cycle-toggle:checked { background-color: var(--bs-success); border-color: var(--bs-success); }
.pricing-plans-row .card { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.pricing-plans-row .card.border-primary { transform: scale(1.03); z-index: 2; }
.quote-item-container { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.team-member-container { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.team-member-container:hover { transform: translateY(-5px); }
.team-member-container:hover .team-photo { transform: scale(1.1); }
.team-photo { transition: transform 0.5s ease, border-radius 0.3s ease; }
.team-photo-wrapper { overflow: hidden; border-radius: 1rem; }
.tab-slide { display: none; transform: translateX(20px); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; }
.tab-slide.active { display: block; transform: translateX(0); opacity: 1; }

/* Carousel Cinematic Enhancements */
.carousel-progress-bar { position: absolute; bottom: 0; left: 0; width: 100%; height: 4px; background: rgba(255,255,255,0.2); z-index: 10; }
.progress-fill { height: 100%; background: var(--bs-primary); width: 0; }
.carousel-item.active ~ .carousel-progress-bar .progress-fill { animation: carouselProgress linear forwards; }
@keyframes carouselProgress { 0% { width: 0; } 100% { width: 100%; } }
.ken-burns-img { animation: kenburns 10s ease-in-out infinite alternate; }
@keyframes kenburns { 0% { transform: scale(1); } 100% { transform: scale(1.2); } }
@keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } }

/* Scroll-reveal entrance animation. Add `.reveal-up` to any element (sections, cards, etc.); it fades
   and slides in when scrolled into view. The hidden start-state is gated behind `body.reveal-enabled`,
   which website-runtime.js sets only once it runs - so if JS is absent the content stays visible. */
body.reveal-enabled .reveal-up { opacity: 0; transform: translateY(28px); transition: opacity .6s ease, transform .6s ease; will-change: opacity, transform; }
body.reveal-enabled .reveal-up.is-visible { opacity: 1; transform: none; }

/* Staggered reveal: the section itself stays put; its grid columns rise in sequence as it enters
   view (a more crafted feel for card grids - features, services, team, stats). If the element has no
   `.row > col` structure, nothing animates - a safe no-op, never a broken layout. */
body.reveal-enabled .reveal-stagger .row > [class*="col-"] { opacity: 0; transform: translateY(22px); transition: opacity .5s ease, transform .5s ease; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"] { opacity: 1; transform: none; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(1) { transition-delay: .05s; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(2) { transition-delay: .12s; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(3) { transition-delay: .19s; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(4) { transition-delay: .26s; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(5) { transition-delay: .33s; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(6) { transition-delay: .40s; }
body.reveal-enabled .reveal-stagger.is-visible .row > [class*="col-"]:nth-child(n+7) { transition-delay: .46s; }

@media (prefers-reduced-motion: reduce) {
    body.reveal-enabled .reveal-up,
    body.reveal-enabled .reveal-stagger .row > [class*="col-"] { opacity: 1; transform: none; transition: none; }
}

.anim-slide-up .carousel-title-anim { animation: fadeInUp 0.8s ease both; }
.anim-slide-up .carousel-desc-anim { animation: fadeInUp 0.8s ease 0.2s both; }
.anim-slide-up .carousel-btn-anim { animation: fadeInUp 0.8s ease 0.4s both; }

/* Carousel property classes - mirrored from the builder's canvas.css so the Caption Animation /
   Arrow Style / Hide Indicators options render identically on PUBLISHED sites (they previously
   only existed in canvas.css, so these options silently did nothing live). */
.carousel-indicators-hidden .carousel-indicators { display: none; }
.carousel-dark .carousel-control-prev, .carousel-dark .carousel-control-next { filter: none; }
.anim-fade .carousel-title-anim { animation: fadeIn 1s ease both; }
.anim-fade .carousel-desc-anim { animation: fadeIn 1s ease 0.3s both; }
.anim-fade .carousel-btn-anim { animation: fadeIn 1s ease 0.6s both; }
.anim-slide-left .carousel-title-anim { animation: fadeInRight 0.8s ease both; }
.anim-slide-left .carousel-desc-anim { animation: fadeInRight 0.8s ease 0.2s both; }
.anim-slide-left .carousel-btn-anim { animation: fadeInRight 0.8s ease 0.4s both; }
.anim-zoom .carousel-title-anim { animation: zoomIn 0.8s ease both; }
.anim-zoom .carousel-desc-anim { animation: zoomIn 0.8s ease 0.2s both; }
.anim-zoom .carousel-btn-anim { animation: zoomIn 0.8s ease 0.4s both; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeInRight { from { opacity: 0; transform: translateX(30px); } to { opacity: 1; transform: translateX(0); } }
@keyframes zoomIn { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: scale(1); } }
.arrows-minimal .carousel-control-prev, .arrows-minimal .carousel-control-next { top: auto; bottom: 20px; width: 40px; height: 40px; background: rgba(0,0,0,0.5); border-radius: 5px; }
.arrows-minimal .carousel-control-prev { left: auto; right: 70px; }
.arrows-minimal .carousel-control-next { right: 20px; }
.arrows-floating .carousel-control-prev, .arrows-floating .carousel-control-next { width: 60px; height: 60px; background: #fff; color: #000; border-radius: 50%; top: 50%; transform: translateY(-50%); opacity: 0; transition: opacity 0.3s ease; margin: 0 20px; }
.arrows-floating .carousel-control-prev-icon, .arrows-floating .carousel-control-next-icon { filter: invert(1); }
.carousel:hover .arrows-floating .carousel-control-prev, .carousel:hover .arrows-floating .carousel-control-next { opacity: 1; }
.arrows-clean .carousel-control-prev-icon, .arrows-clean .carousel-control-next-icon { background-image: none; font-family: "bootstrap-icons"; font-size: 2rem; }
.arrows-clean .carousel-control-prev-icon::before { content: "\F284"; }
.arrows-clean .carousel-control-next-icon::before { content: "\F285"; }
.r-carousel-pause:hover { opacity: 1 !important; }
@media (prefers-reduced-motion: reduce) { .carousel .carousel-item { transition: none !important; } }

/* Gallery (responsive grid / masonry + hover + lightbox) - mirrored from canvas.css for published sites. */
.r-gallery-item { display: block; position: relative; }
.r-gallery-item img { transition: transform .45s ease; }
.r-gallery-item:hover img { transform: scale(1.06); }
.r-gallery-item::after { content: ""; position: absolute; inset: 0; background: rgba(0,0,0,0); transition: background .3s ease; pointer-events: none; }
.r-gallery-item:hover::after { background: rgba(0,0,0,.14); }
a.r-gallery-item[data-lb] { cursor: zoom-in; }
.r-gallery-fig { display: block; }
.r-gallery-masonry { column-gap: 1rem; }
.r-gallery-masonry .r-gallery-mcell { break-inside: avoid; margin-bottom: 1rem; }
.r-gallery-cap-over { position: absolute; left: 0; right: 0; bottom: 0; padding: .7rem .85rem; color: #fff; font-size: .9rem; line-height: 1.3; background: linear-gradient(transparent, rgba(0,0,0,.72)); opacity: 0; transform: translateY(10px); transition: opacity .25s ease, transform .25s ease; pointer-events: none; z-index: 2; }
.r-gallery-item:hover .r-gallery-cap-over { opacity: 1; transform: none; }
.r-gallery-cap-below { padding: .55rem .15rem; font-size: .9rem; color: var(--bs-secondary-color, #6c757d); }
.r-gallery-zoom { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%) scale(.8); width: 46px; height: 46px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(255,255,255,.92); color: #111; opacity: 0; transition: opacity .25s ease, transform .25s ease; pointer-events: none; z-index: 2; }
.r-gallery-item:hover .r-gallery-zoom { opacity: 1; transform: translate(-50%,-50%) scale(1); }
.r-gallery-masonry-2 { column-count: 2; }
.r-gallery-masonry-3 { column-count: 3; }
.r-gallery-masonry-4 { column-count: 4; }
@media (max-width: 991.98px) { .r-gallery-masonry-3, .r-gallery-masonry-4 { column-count: 2; } }
@media (max-width: 575.98px) { .r-gallery-masonry-2, .r-gallery-masonry-3, .r-gallery-masonry-4 { column-count: 1; } }
/* Menu dish photo - opens the same lightbox as the gallery, so it needs to look clickable. Subtler than
   the gallery's hover: a 72px thumbnail in a text list, not a tile in a grid of pictures. */
.r-menu-photo { position: relative; overflow: hidden; border-radius: .5rem; cursor: zoom-in; }
.r-menu-photo img { transition: transform .35s ease; }
.r-menu-photo:hover img, .r-menu-photo:focus-visible img { transform: scale(1.08); }
.r-menu-photo::after { content: "\F8B0"; font-family: "bootstrap-icons"; position: absolute; inset: 0; display: flex;
    align-items: center; justify-content: center; color: #fff; font-size: .95rem; background: rgba(0,0,0,0);
    opacity: 0; transition: opacity .25s ease, background .25s ease; pointer-events: none; }
.r-menu-photo:hover::after, .r-menu-photo:focus-visible::after { opacity: 1; background: rgba(0,0,0,.35); }
@media (prefers-reduced-motion: reduce) { .r-menu-photo img { transition: none; } }

/* Menu rules - see Core\Support\MenuBlock. Both are currentColor so they inherit whatever the band
   around them is set in: the same markup sits on a white menu page and inside a dark brand band, and a
   fixed rule colour is invisible in one of the two. */
.r-menu-rule { flex: 1 1 auto; height: 1px; background: currentColor; opacity: .16; }
/* The leader between a dish and its price. align-self centres it against a baseline-aligned row, where
   an empty span has no baseline of its own to sit on. */
.r-menu-leader { flex: 1 1 auto; align-self: center; border-bottom: 1px dotted currentColor;
    opacity: .34; margin: 0 .15rem; min-width: 1.5rem; }

.r-gallery-lightbox { position: fixed; inset: 0; z-index: 1080; background: rgba(0,0,0,.9); display: none; align-items: center; justify-content: center; }
.r-gallery-lightbox.open { display: flex; }
.r-gallery-lightbox .lb-img { max-width: 92vw; max-height: 88vh; border-radius: 8px; box-shadow: 0 12px 48px rgba(0,0,0,.5); }
.r-gallery-lightbox button { position: absolute; background: rgba(255,255,255,.12); color: #fff; border: 0; width: 48px; height: 48px; border-radius: 50%; font-size: 1.6rem; line-height: 1; cursor: pointer; transition: background .15s; }
.r-gallery-lightbox button:hover { background: rgba(255,255,255,.28); }
.r-gallery-lightbox .lb-close { top: 18px; right: 18px; }
.r-gallery-lightbox .lb-prev { left: 18px; top: 50%; transform: translateY(-50%); }
.r-gallery-lightbox .lb-next { right: 18px; top: 50%; transform: translateY(-50%); }
.r-gallery-lightbox .lb-stage { margin: 0; display: flex; flex-direction: column; align-items: center; gap: .6rem; max-width: 92vw; }
.r-gallery-lightbox .lb-cap { color: #fff; font-size: .95rem; text-align: center; max-width: 70ch; opacity: .9; }
.r-gallery-lightbox .lb-count { position: absolute; top: 22px; left: 50%; transform: translateX(-50%); color: #fff; font-size: .85rem; opacity: .75; }
.r-gallery-lightbox .lb-spin { position: absolute; width: 38px; height: 38px; border: 3px solid rgba(255,255,255,.25); border-top-color: #fff; border-radius: 50%; animation: lbSpin .8s linear infinite; display: none; }
.r-gallery-lightbox.loading .lb-spin { display: block; }
.r-gallery-lightbox.loading .lb-img { opacity: 0; }
@keyframes lbSpin { to { transform: rotate(360deg); } }

/* Timeline Component Styles */
.timeline-container { position: relative; }
.timeline-item { position: relative; }
.timeline-centered .timeline-item { width: 100%; display: flex; justify-content: center; align-items: flex-start; gap: 0 !important; }
.timeline-centered .timeline-badge-wrapper { position: absolute; left: 50%; transform: translateX(-50%); height: 100%; }
.timeline-centered .timeline-content { width: 45%; padding: 0 30px; text-align: right; }
.timeline-centered .timeline-item:nth-child(even) .timeline-content { margin-left: 55%; text-align: left; }
.timeline-centered::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; background: rgba(var(--bs-primary-rgb), 0.1); transform: translateX(-50%); }
.timeline-horizontal { display: flex; overflow-x: auto; gap: 0; padding-bottom: 2rem; }
.timeline-horizontal .timeline-item { flex: 0 0 300px; flex-direction: column !important; gap: 1.5rem !important; }
.timeline-horizontal .timeline-badge-wrapper { flex-direction: row !important; width: 100%; align-items: center; }
.timeline-horizontal .timeline-line { height: 2px; width: 100% !important; margin: 0 !important; }
.timeline-horizontal .timeline-content { text-align: center; padding-right: 2rem; }
.tm-status-completed .timeline-badge { background-color: var(--bs-success) !important; color: white !important; }
.tm-status-completed .timeline-line { background-color: var(--bs-success) !important; opacity: 1 !important; }
.tm-status-active .timeline-badge { background-color: var(--bs-primary) !important; color: white !important; box-shadow: 0 0 0 4px rgba(var(--bs-primary-rgb), 0.2); animation: tm-active-pulse 2s infinite; }
@keyframes tm-active-pulse {
    0% { box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0.4); }
    70% { box-shadow: 0 0 0 10px rgba(var(--bs-primary-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0); }
}
.line-status-completed { background-color: var(--bs-success) !important; opacity: 1 !important; }
.line-status-active { background: linear-gradient(to bottom, var(--bs-primary), #e9ecef) !important; opacity: 1 !important; }
.line-status-pending { background-color: #e9ecef !important; opacity: 1 !important; }
.timeline-horizontal .line-status-active { background: linear-gradient(to right, var(--bs-primary), #e9ecef) !important; }

/* Visual Styles */
.icon-box-container { transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease !important; }
.icon-box-container .icon-wrapper { transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important; }
.icon-box-container:hover .icon-wrapper { transform: translateY(-2px) scale(1.06); }

/* ─────────────────────────────────────────────────────────────────────────
   MODERN REFRESH - a "soft UI" finish layered over the section library. Only
   targets section-specific classes (never generic user content) + a few opt-in
   utilities the section markup can adopt. See flagship sections for usage.
   ───────────────────────────────────────────────────────────────────────── */

/* Feature / service cards: calmer, more refined than the heavy `shadow` + inline
   colored top-accent. Hairline border, soft shadow, gentle hover lift. */
.icon-box-container {
    border: 1px solid rgba(16, 24, 40, 0.06) !important;
    border-radius: 1.25rem !important;
    box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06) !important;
}
.icon-box-container:hover {
    transform: translateY(-4px);
    box-shadow: 0 16px 34px rgba(16, 24, 40, 0.10) !important;
    border-color: rgba(var(--bs-primary-rgb), 0.20) !important;
}

/* THE big global win: retire the rainbow solid-circle icons. Every existing card
   uses `.icon-wrapper` (bg-{color} text-white rounded-circle) - normalise them to
   one restrained accent as a soft, tinted rounded-square "chip". */
.icon-box-container .icon-wrapper {
    background: rgba(var(--bs-primary-rgb), 0.10) !important;
    color: var(--bs-primary) !important;
    border-radius: 1rem !important;
}

/* Opt-in utilities for section markup (used by the modernised flagship sections) */
.icon-chip { display: inline-flex; align-items: center; justify-content: center;
    width: 3.5rem; height: 3.5rem; border-radius: 1rem; font-size: 1.5rem; flex-shrink: 0;
    background: rgba(var(--bs-primary-rgb), 0.10); color: var(--bs-primary); }
.icon-chip-lg { width: 4.25rem; height: 4.25rem; border-radius: 1.25rem; font-size: 1.9rem; }

.sec-kicker { display: inline-block; padding: 0.35rem 0.85rem; border-radius: 50rem;
    background: rgba(var(--bs-primary-rgb), 0.10); color: var(--theme-primary-ink, var(--bs-primary));
    font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
/* The chip is a 10% tint of the brand over a light section, so the LABEL on it is text on near-white
   and needs the readable form of the accent - the same one .text-primary uses. A pale palette wrote
   its eyebrow at around 2:1 here. Falls back to the raw brand colour outside a themed page. */
.bg-dark .sec-kicker, .bg-black .sec-kicker,
[data-bs-theme="dark"] .sec-kicker { color: var(--theme-primary-light, var(--bs-primary)); }

/* A short accent rule belongs with the text it introduces. Sections draw it as a 60px <hr> above the
   kicker, and browsers leave a narrow <hr> centred - so on the eleven left-aligned blocks that use one
   it read as a dash floating in the middle of the column. Aligning it by class instead would break the
   centred layouts (the same section centres its block in one variant and left-aligns it in another),
   so it follows the block: left by default, centred where the text is centred, right where it is.
   Any explicit alignment class still wins - Bootstrap's margin utilities are !important. */
hr { margin-left: 0; margin-right: auto; }
.text-center hr { margin-left: auto; margin-right: auto; }
.text-end hr { margin-left: auto; margin-right: 0; }

/* A kicker sitting ON a darkened photo cannot use the brand colour. `.sec-kicker` is brand-coloured on
   a 10%-brand chip, which reads well on a light section and vanishes on a hero: a navy, burgundy or
   forest primary over a 35-66% black overlay is dark-on-dark. Two generated restaurant sites shipped
   with an invisible "EXPERIENCE FINE DINING" for exactly this reason.
   Scoped by the overlay element itself, which every photo hero renders as a SIBLING of its content -
   so this needs no :has() and applies wherever the pattern is used. */
/* A WHITE veil only solved half of it. White text on an 18% white chip reads over a dark photo and
   disappears over a bright one - camper-hire's sunset measured 2.12:1, which is the same invisible
   kicker in the other direction. A DARK chip with white text is the one that works over any
   photograph, bright or dark, which is what "sitting on a photo" actually has to survive. */
.image-overlay-layer ~ * .sec-kicker,
.wk-scrim-x ~ * .sec-kicker { background: rgba(0, 0, 0, 0.45); color: #fff; }

/* Bento tiles (BentoGridSection). The asymmetry comes from the column widths; this supplies the surface
   - a hairline edge, a soft lift on hover, and a floor height so a short tile beside a tall one still
   reads as a tile rather than a label. Transition and lift are dropped under reduced-motion. */
.bento-tile { border: 1px solid rgba(16, 24, 40, .07); min-height: 12rem;
    display: flex; flex-direction: column; justify-content: center;
    transition: transform .25s ease, box-shadow .25s ease; }
.bento-tile:hover { transform: translateY(-3px); box-shadow: 0 14px 34px rgba(16,24,40,.10), 0 4px 8px rgba(16,24,40,.06); }
.bento-tile.sec-gradient-dark { border-color: rgba(255, 255, 255, .10); }
.bento-tile.sec-gradient-dark .icon-chip { background: rgba(255,255,255,.14); color: #fff; }
@media (prefers-reduced-motion: reduce) {
    .bento-tile { transition: none; }
    .bento-tile:hover { transform: none; }
}

/* Numbered cards - a subtle 01/02/03 index on each card in a grid (the modern "Strive/Clarity" look).
   Opt in by adding `.cards-numbered` to a section; the number is a faint accent watermark in the
   card corner, so it never obscures content. Safe no-op if the section has no `.row > col` cards. */
.cards-numbered { counter-reset: cardnum; }
.cards-numbered .row > [class*="col-"] { counter-increment: cardnum; }
.cards-numbered .row > [class*="col-"] > * { position: relative; }
.cards-numbered .row > [class*="col-"] > *::after {
    content: counter(cardnum, decimal-leading-zero);
    position: absolute; top: .7rem; right: 1rem;
    font-size: 2.2rem; font-weight: 800; line-height: 1;
    color: rgba(var(--bs-primary-rgb), 0.13);
    pointer-events: none; z-index: 1;
}

/* Depth for dark hero/CTA sections: a diagonal base + soft accent glows. No
   !important, so an inline background-image (photo heroes) still wins - this only
   fills in when the section has no image of its own. */
.sec-gradient-dark { background-color: #0b1020;
    background-image:
        radial-gradient(60rem 40rem at 82% -12%, rgba(var(--bs-primary-rgb), 0.38), transparent 60%),
        radial-gradient(52rem 42rem at -5% 112%, rgba(var(--bs-primary-rgb), 0.20), transparent 55%); }

/* LIGHT companion to sec-gradient-dark: a soft brand-tinted radial mesh for plain white/light heroes
   (the modern SaaS/agency touch). Layers only background-image with transparent stops, so the section's
   own base colour shows through and an inline photo background still wins. Add `.hero-glow`. */
.hero-glow {
    background-image:
        radial-gradient(48rem 32rem at 85% -10%, rgba(var(--bs-primary-rgb), 0.10), transparent 60%),
        radial-gradient(42rem 34rem at -6% 110%, rgba(var(--bs-primary-rgb), 0.06), transparent 55%);
}

/* Section imagery: consistent radius + soft depth. */
.sec-media { border-radius: 1.25rem; box-shadow: 0 24px 48px rgba(16, 24, 40, 0.16); }

/* Tighter tracking on big display headings - a subtle, premium touch across all sections.
   An inline letter-spacing (property panel) still overrides it. */
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 { letter-spacing: -0.02em; }

/* Marquee: a full-bleed, seamlessly-looping horizontal band (MarqueeStripSection). The track holds
   TWO identical runs and scrolls left by exactly half its width, so the second run takes the first's
   place with no visible seam. Motion-only decoration - paused entirely under reduced-motion. */
.marquee { display: flex; overflow: hidden; width: 100%; }
.marquee-track { display: flex; flex-shrink: 0; align-items: center; gap: 2.5rem; padding-right: 2.5rem;
    white-space: nowrap; animation: marquee-scroll 32s linear infinite; }
.marquee-item { flex-shrink: 0; }
.marquee-sep { flex-shrink: 0; font-size: 1.25rem; opacity: 0.7; }
@keyframes marquee-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* display:contents keeps the two runs' items as direct flex children of the track, so gap and the
   -50% scroll are unchanged; the wrapper exists only to be hidden and to carry aria-hidden. Declared
   BEFORE the reduced-motion block: at equal specificity the later rule wins, and this one must lose. */
.marquee-run { display: contents; }
@media (prefers-reduced-motion: reduce) {
    /* !important because consulting's track carries its animation INLINE (its own keyframe), and an
       inline declaration beats every stylesheet rule but an important one. Reduced motion is the one
       preference where that trade is correct. */
    .marquee-track { animation: none !important; flex-wrap: wrap; white-space: normal; justify-content: center; }
    /* The track holds every phrase TWICE so the loop has no seam. Stopped and wrapped, that is a word
       cloud with every entry repeated - and a screen reader read it twice even when it moved. The
       second run is presentation only: hide it here, and mark it aria-hidden in the markup. */
    .marquee-run.marquee-run-dup { display: none; }
}
.tm-style-glass .timeline-badge { background: rgba(var(--bs-primary-rgb), 0.1) !important; color: var(--bs-primary) !important; backdrop-filter: blur(5px); border: 1px solid rgba(var(--bs-primary-rgb), 0.2); }
.tm-style-glass .timeline-content { background: rgba(255,255,255,0.05); border: 1px solid rgba(0,0,0,0.05); padding: 1.5rem !important; border-radius: 15px; box-shadow: 0 8px 32px rgba(0,0,0,0.05); }
.tm-style-minimal .timeline-badge { background: transparent !important; color: var(--bs-primary) !important; border: 2px solid var(--bs-primary); font-weight: 800; shadow: none !important; }
.tm-style-minimal .timeline-line { border-left-style: dashed !important; background: transparent !important; border-left-width: 2px; }

/* Premium Header Effects */
.navbar { transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important; }
.nav-glass { backdrop-filter: blur(12px) !important; -webkit-backdrop-filter: blur(12px) !important; background: rgba(255, 255, 255, 0.7) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.2) !important; }
body[data-bs-theme="dark"] .nav-glass { background: rgba(33, 37, 41, 0.7) !important; border-bottom: 1px solid rgba(255, 255, 255, 0.05) !important; }
.nav-transparent-scroll:not(.is-scrolled) { background-color: transparent !important; border-bottom-color: transparent !important; opacity: 1 !important; }
.nav-transparent-scroll.is-scrolled { opacity: var(--nav-scroll-opacity-d, var(--nav-scroll-opacity-m, 1)) !important; box-shadow: 0 10px 30px rgba(0,0,0,0.08) !important; }
.nav-shrink { padding-top: 1rem !important; padding-bottom: 1rem !important; }
.nav-shrink.is-scrolled { padding-top: 0.4rem !important; padding-bottom: 0.4rem !important; box-shadow: 0 10px 30px rgba(0,0,0,0.08) !important; }

/* Header on a phone: brand + CTA + burger must stay on ONE row.
   The brand is the only elastic part, so it yields; without min-width:0 a long trade name
   ("Pet Grooming & Boarding") pushed the CTA onto a second line and doubled the header height. */
@media (max-width: 991.98px) {
  .dynamic-navbar .wk-brand-elastic { min-width: 0 !important; max-width: 56%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* Hero scrims that fade LEFT-to-RIGHT read fine on a desktop, where the copy occupies the dark half.
   On a phone the copy is full-width, so its right-hand edge lands on the un-dimmed photo and the
   last word of every line loses contrast. Below the lg breakpoint the fade becomes vertical. */
@media (max-width: 991.98px) {
  .wk-scrim-x { background: linear-gradient(180deg, rgba(8,9,12,.72) 0%, rgba(8,9,12,.90) 100%) !important; }
  .wk-scrim-x-light { background: linear-gradient(180deg, rgba(255,255,255,.82) 0%, rgba(255,255,255,.95) 100%) !important; }
}
/* Hero overlays are tuned for a desktop hero, where the copy sits low and the gradient is darkest.
   A phone hero is taller than it is wide, so the same copy lands mid-frame where the fade has run
   out. This adds neutral darkening across the top and middle only - the per-template tint of the
   layer underneath is preserved, and the bottom (already dark) is left alone. */
@media (max-width: 991.98px) {
  .image-overlay-layer::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0,0,0,.30) 0%, rgba(0,0,0,.34) 55%, rgba(0,0,0,.08) 100%); }
}
/* Four countdown tiles at min-width:100px plus p-4 need 448px; a phone has 390. They are the only
   thing in the catalogue that pushed a page into horizontal scroll. Sized down rather than wrapped
   so the timer still reads as one row. */
@media (max-width: 575.98px) {
  .timer-item { min-width: 76px !important; padding: 0.75rem !important; }
  .timer-item .display-4 { font-size: 1.9rem; }
}
@media (max-width: 575.98px) {
  .dynamic-navbar .wk-brand-elastic { max-width: 46%; font-size: 1.05rem; }
  .dynamic-navbar .wk-brand-elastic.fs-1, .dynamic-navbar .wk-brand-elastic.fs-2, .dynamic-navbar .wk-brand-elastic.fs-3 { font-size: 1.15rem !important; }
  /* The header CTA gives up a little size rather than the whole row: a long label
     ("See the programs") next to a long trade name wrapped the button onto a second line. */
  .dynamic-navbar .wk-brand-elastic ~ .d-flex > .btn { font-size: .875rem; padding-left: .7rem !important; padding-right: .7rem !important; }
}

/* Premium Social Follow Styles */
.social-container .social-btn { transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important; display: inline-flex !important; align-items: center !important; justify-content: center !important; padding: 0 !important; }
.social-v-sm .social-btn { width: 32px !important; height: 32px !important; font-size: 0.85rem !important; }
.social-v-md .social-btn { width: 44px !important; height: 44px !important; font-size: 1.25rem !important; }
.social-v-lg .social-btn { width: 60px !important; height: 60px !important; font-size: 1.75rem !important; }
.social-s-solid .social-btn[data-platform="facebook"] { background-color: #1877F2 !important; color: #fff !important; }
.social-s-solid .social-btn[data-platform="twitter-x"] { background-color: #000000 !important; color: #fff !important; }
.social-s-solid .social-btn[data-platform="instagram"] { background-color: #E4405F !important; color: #fff !important; }
.social-s-solid .social-btn[data-platform="linkedin"] { background-color: #0A66C2 !important; color: #fff !important; }
.social-s-solid .social-btn[data-platform="youtube"] { background-color: #FF0000 !important; color: #fff !important; }
.social-s-solid .social-btn[data-platform="tiktok"] { background-color: #000000 !important; color: #fff !important; }
.social-s-solid .social-btn[data-platform="whatsapp"] { background-color: #25D366 !important; color: #fff !important; }
.social-s-outline .social-btn { background-color: transparent !important; border: 1px solid currentColor !important; }
.social-s-outline .social-btn[data-platform="facebook"] { color: #1877F2 !important; }
.social-s-outline .social-btn[data-platform="twitter-x"] { color: #000000 !important; }
.social-s-outline .social-btn[data-platform="instagram"] { color: #E4405F !important; }
.social-s-outline .social-btn[data-platform="linkedin"] { color: #0A66C2 !important; }
.social-s-outline .social-btn[data-platform="youtube"] { color: #FF0000 !important; }
.social-s-outline .social-btn[data-platform="tiktok"] { color: #000000 !important; }
.social-s-outline .social-btn[data-platform="whatsapp"] { color: #25D366 !important; }
.social-s-minimal .social-btn { background-color: transparent !important; border: none !important; box-shadow: none !important; }
.social-s-minimal .social-btn[data-platform="facebook"] { color: #1877F2 !important; }
.social-s-minimal .social-btn[data-platform="twitter-x"] { color: #000000 !important; }
.social-s-minimal .social-btn[data-platform="instagram"] { color: #E4405F !important; }
.social-s-minimal .social-btn[data-platform="linkedin"] { color: #0A66C2 !important; }
.social-s-minimal .social-btn[data-platform="youtube"] { color: #FF0000 !important; }
.social-s-minimal .social-btn[data-platform="tiktok"] { color: #000000 !important; }
.social-s-minimal .social-btn[data-platform="whatsapp"] { color: #25D366 !important; }
.social-s-glass .social-btn { background-color: rgba(255,255,255,0.1) !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important; border: 1px solid rgba(255,255,255,0.2) !important; color: #fff !important; }
.social-s-glass .social-btn:hover { background-color: rgba(255,255,255,0.2) !important; }
.social-btn:hover { opacity: 0.85; transform: translateY(-3px); box-shadow: 0 8px 15px rgba(0,0,0,0.1) !important; }

/* CMS STYLES */
.cms-item-wrapper { transition: transform 0.2s ease; }
.cms-item-wrapper:hover { transform: translateY(-5px); }
.text-truncate-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* Table & Layout Styles */
table { table-layout: auto; } 
table.fixed-layout { table-layout: fixed; width: 100%; } 
table.fixed-layout th { overflow: hidden; }

/* Modern Section Utilities */
.hover-lift { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.hover-lift:hover { transform: translateY(-8px); box-shadow: 0 20px 40px rgba(0,0,0,0.08); }
.hover-grow { transition: transform 0.3s ease; }
.hover-grow:hover { transform: scale(1.03); }
.text-gradient-primary {
    background: linear-gradient(135deg, var(--bs-primary, #0d6efd), var(--bs-info, #0dcaf0));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.bg-gradient-subtle {
    background: linear-gradient(135deg, rgba(var(--bs-primary-rgb, 13,110,253), 0.03) 0%, transparent 60%);
}
.bg-gradient-dark-subtle {
    background: linear-gradient(135deg, #1a1d23 0%, #2d3748 100%);
}
.border-gradient {
    border: 1px solid transparent;
    background-clip: padding-box;
    position: relative;
}
.border-gradient::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: linear-gradient(135deg, var(--bs-primary, #0d6efd), var(--bs-info, #0dcaf0));
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
}
.glow-sm { box-shadow: 0 0 20px rgba(var(--bs-primary-rgb, 13,110,253), 0.15); }
.backdrop-blur { backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }

/* Blog Content Typography */
.blog-content { font-size: 1.1rem; line-height: 1.8; color: #1a1a2e; max-width: 720px; margin: 0 auto; }
.blog-content h2 { font-size: 1.75rem; margin: 2rem 0 1rem; font-weight: 700; }
.blog-content h3 { font-size: 1.4rem; margin: 1.75rem 0 0.75rem; font-weight: 600; }
.blog-content h4 { font-size: 1.2rem; margin: 1.5rem 0 0.5rem; font-weight: 600; }
.blog-content p { margin-bottom: 1.25rem; }
.blog-content img { max-width: 100%; height: auto; border-radius: 8px; margin: 1.5rem 0; }
.blog-content a { color: var(--bs-primary); text-decoration: underline; }
.blog-content blockquote { border-left: 4px solid var(--bs-primary); padding: 1rem 1.5rem; margin: 1.5rem 0; background: rgba(var(--bs-primary-rgb), 0.04); border-radius: 0 8px 8px 0; font-style: italic; }
.blog-content pre { background: #1e1e2e; color: #cdd6f4; padding: 1.25rem; border-radius: 8px; overflow-x: auto; margin: 1.5rem 0; font-size: 0.9rem; }
.blog-content code { font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.9em; }
.blog-content :not(pre) > code { background: #f1f3f5; padding: 0.15em 0.4em; border-radius: 4px; color: #e45858; }
.blog-content ul, .blog-content ol { padding-left: 1.5rem; margin-bottom: 1.25rem; }
.blog-content li { margin-bottom: 0.4rem; }
.blog-content hr { border: none; border-top: 2px solid #e9ecef; margin: 2rem 0; }
.blog-content table { width: 100%; border-collapse: collapse; margin: 1.5rem 0; }
.blog-content th, .blog-content td { border: 1px solid #dee2e6; padding: 0.75rem; text-align: left; }
.blog-content th { background: #f8f9fa; font-weight: 600; }
.blog-content figure { margin: 1.5rem 0; text-align: center; }
.blog-content figcaption { font-size: 0.875rem; color: #6c757d; margin-top: 0.5rem; }

/* Media & Interactions */
img.img-fluid { transition: opacity 0.2s; }
.map-overlay, .video-overlay { position: absolute; inset: 0; z-index: 10; }

/* Audio & Video Empty States */
.audio-empty-state, .video-empty-state { display: flex; align-items: center; justify-content: center; gap: 0.5rem; padding: 1.25rem; border: 2px dashed #d1d5db; border-radius: 8px; color: #9ca3af; font-size: 0.85rem; }
.audio-empty-state i, .video-empty-state i { font-size: 1.25rem; }
.video-empty-state { padding: 3rem 1.25rem; flex-direction: column; }
.video-empty-state i { font-size: 2rem; }

/* "Made with Webkio" badge + email-capture popover - shown on free published sites.
   z-index sits BELOW the cookie-consent banner (9999) / its re-open button (9998) so it
   can never cover the consent UI; JS lifts it above a visible bottom banner. */
.sp-made-with{position:fixed;right:18px;bottom:18px;z-index:9000;
    font:700 13px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}
.sp-made-with strong{font-weight:800}
.sp-made-with-ico,.sp-mw-dot{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;
    border-radius:6px;background:rgba(255,255,255,.28)}

/* Pill */
.sp-mw-pill{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:0;border-radius:999px;cursor:pointer;
    background:linear-gradient(120deg,#4338ca,#5b54d6,#0e7490);background-size:220% 220%;color:#fff;
    font:inherit;letter-spacing:.01em;box-shadow:0 8px 26px rgba(99,102,241,.32),0 2px 8px rgba(0,0,0,.18);
    transition:transform .18s ease,box-shadow .18s ease;
    animation:spBadgeIn .5s ease both .8s, spBadgeShift 12s ease-in-out infinite}
.sp-mw-pill:hover{transform:translateY(-3px) scale(1.03);box-shadow:0 12px 34px rgba(99,102,241,.42),0 3px 10px rgba(0,0,0,.22)}
/* The pill's own text is the offer now, so the hover-swap CTA (.sp-mw-cta) is gone - it could never
   fire on touch, which is where most of these impressions happen. */
.sp-mw-text{white-space:nowrap}

/* Minimize (−) chip on the pill's corner */
.sp-mw-min{position:absolute;top:-7px;right:-7px;width:20px;height:20px;border:0;border-radius:999px;cursor:pointer;
    background:#fff;color:#4338ca;font:900 14px/1 sans-serif;box-shadow:0 2px 6px rgba(0,0,0,.25);
    display:none;align-items:center;justify-content:center;opacity:0;transition:opacity .15s ease}
.sp-made-with:hover .sp-mw-min{display:inline-flex;opacity:1}

/* Collapsed dot (after minimize) */
.sp-mw-dot{display:none;width:44px;height:44px;border:0;border-radius:999px;cursor:pointer;color:#fff;
    background:linear-gradient(120deg,#4338ca,#5b54d6,#0e7490);box-shadow:0 8px 22px rgba(99,102,241,.34),0 2px 8px rgba(0,0,0,.2)}
.sp-mw-dot:hover{transform:scale(1.06)}
.sp-mw-dot svg{width:18px;height:18px}

/* Minimized state */
.sp-made-with.is-min .sp-mw-pill,.sp-made-with.is-min .sp-mw-min,.sp-made-with.is-min .sp-mw-pop{display:none!important}
.sp-made-with.is-min .sp-mw-dot{display:inline-flex;align-items:center;justify-content:center}

/* Popover */
.sp-mw-pop{position:absolute;right:0;bottom:calc(100% + 12px);width:300px;max-width:78vw;
    background:#fff;color:#1e2430;border-radius:16px;padding:18px 18px 14px;text-align:left;
    box-shadow:0 18px 50px rgba(15,23,42,.28),0 4px 14px rgba(0,0,0,.12);
    animation:spPopIn .18s ease both}
.sp-mw-pop[hidden]{display:none}
.sp-mw-close{position:absolute;top:8px;right:10px;border:0;background:transparent;cursor:pointer;
    font:700 20px/1 sans-serif;color:#9aa3b2}
.sp-mw-close:hover{color:#4338ca}
.sp-mw-eyebrow{display:inline-flex;align-items:center;gap:5px;color:#5b54d6;font-size:10px;font-weight:800;
    letter-spacing:.08em;text-transform:uppercase;margin-bottom:6px}
.sp-mw-eyebrow svg{width:12px;height:12px;color:#5b54d6}
.sp-mw-headline{font-size:17px;font-weight:800;color:#11151f;margin-bottom:4px}
.sp-mw-sub{font-size:12.5px;font-weight:500;line-height:1.45;color:#5b6478;margin:0 0 12px}
.sp-mw-form{display:flex;gap:6px}
.sp-mw-form input{flex:1;min-width:0;padding:9px 12px;border:1px solid #d7dbe3;border-radius:10px;
    font:600 13px/1 inherit;color:#1e2430;background:#fff}
.sp-mw-form input:focus{outline:0;border-color:#5b54d6;box-shadow:0 0 0 3px rgba(91,84,214,.18)}
.sp-mw-form button{flex:0 0 auto;padding:9px 14px;border:0;border-radius:10px;cursor:pointer;color:#fff;
    font:800 13px/1 inherit;background:linear-gradient(120deg,#4338ca,#5b54d6)}
.sp-mw-form button:hover{filter:brightness(1.07)}
.sp-mw-form button:disabled{opacity:.6;cursor:default}
.sp-mw-msg{margin-top:10px;font-size:12.5px;font-weight:600;line-height:1.4}
.sp-mw-msg[hidden]{display:none}
.sp-mw-msg.is-ok{color:#0f7b3f}
.sp-mw-msg.is-err{color:#c0392b}
/* `block`, not `inline-block`: the success text wraps to two lines, and an inline-block link simply
   continued that last line - so the primary CTA read as "…the link too).Create your free site →",
   glued to the end of a sentence. It is the most important element in this state; it gets its own row. */
.sp-mw-msg a{display:block;margin-top:8px;font-weight:800;color:#4338ca;text-decoration:none}
.sp-mw-msg a:hover{text-decoration:underline}
.sp-mw-credit{display:inline-block;margin-top:11px;font-size:11px;font-weight:700;color:#9aa3b2;text-decoration:none}
.sp-mw-credit:hover{color:#5b54d6}

@keyframes spBadgeIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}
@keyframes spBadgeShift{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
@keyframes spPopIn{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}
@media (max-width:480px){.sp-made-with{right:12px;bottom:12px}.sp-mw-pill{padding:9px 14px;font-size:12px}}
@media print{.sp-made-with{display:none}}
@media (prefers-reduced-motion:reduce){.sp-mw-pill{animation:spBadgeIn .5s ease both .8s}.sp-mw-pop{animation:none}}

/* ── List markers (icon list) ───────────────────────────────────────────────
   Property-driven list markers for the List component. Rendered as CSS ::before
   glyphs (NOT injected DOM) so editing/saving list items can never duplicate them.
   Colour comes from --list-marker-color (set by the Marker Color property), falling
   back to the theme primary. Standard Unicode glyphs → no icon-font dependency. */
.sb-list-marker { padding-left: 0; margin-left: 0; }
.sb-list-marker > li {
    position: relative;
    padding-left: 1.75em;
    margin-bottom: 0.4rem;
}
.sb-list-marker > li::before {
    position: absolute;
    left: 0;
    top: 0;
    line-height: inherit;
    font-weight: 700;
    color: var(--list-marker-color, var(--bs-primary));
}
.sb-list-marker-check  > li::before { content: "\2713"; }  /* ✓ */
.sb-list-marker-arrow  > li::before { content: "\2192"; }  /* → */
.sb-list-marker-chevron> li::before { content: "\203A"; font-weight: 900; }  /* › */
.sb-list-marker-star   > li::before { content: "\2605"; }  /* ★ */
.sb-list-marker-dash   > li::before { content: "\2013"; }  /* – */
.sb-list-marker-dot    > li::before { content: "\2022"; font-size: 1.4em; line-height: 1; }  /* • */

/* ── Parallax background bands ──────────────────────────────────────────────
   Pure CSS, no JS: `background-attachment: fixed` makes the image hold still while the section
   scrolls over it. Chosen over a scroll-listener implementation deliberately - published pages are
   customers' own sites with Core Web Vitals being measured on them, and a per-frame scroll handler
   mutating background-position is exactly the kind of thing that shows up in their INP.

   HONEST LIMITATION: iOS Safari ignores `background-attachment: fixed` and paints a normal cover
   background instead. The effect is therefore a desktop/Android enhancement, not something that
   happens everywhere - which is fine, because the section is designed to look right WITHOUT it.
   That is also why the overlay and text colours never depend on the parallax working.

   Reduced motion switches it off: a background that slides against the page is exactly the kind of
   scroll-coupled movement that triggers vestibular discomfort, and the section still reads correctly
   as a static cover image. */
.sp-parallax {
    background-attachment: fixed;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
}
@media (prefers-reduced-motion: reduce) {
    .sp-parallax { background-attachment: scroll; }
}
/* Touch devices: `fixed` is either ignored (iOS) or janky while dragging, so ask for the cheap,
   correct rendering rather than a half-working effect. */
@media (hover: none) and (pointer: coarse) {
    .sp-parallax { background-attachment: scroll; }
}

/* Readability layer for text over a photographic band. Kept as a class so every template band gets
   the same contrast treatment instead of each one inventing its own rgba(). */
.sp-band-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8,10,20,.62), rgba(8,10,20,.78)); }
.sp-band-content { position: relative; z-index: 1; }

/* ── NO SIDEWAYS SCROLL ON A PHONE ─────────────────────────────────────────────────────────────────
   A Bootstrap `.row` carries negative side margins equal to half its gutter, and a container's padding
   is fixed at 0.75rem. So a `g-5` row (3rem gutter → -1.5rem margins) sticks out 0.75rem each side of
   its container: on a 375px screen that is a page which scrolls horizontally, with the whole layout
   shifting under the thumb. Seventeen sections ship such a row, so this is fixed once here rather than
   in each of them - and only below `sm`, where the space is not there. Desktop spacing is untouched. */
@media (max-width: 575.98px) {
    .r-block .row.g-5,
    .r-block .row.gx-5 { --bs-gutter-x: 1.5rem; }
}
