/*
 * WordPress-specific overrides.
 *
 * The three Webflow stylesheets that load before this one are kept unmodified
 * so they can be re-exported. Everything WordPress needs on top of them lives
 * here.
 */

/* ---------------------------------------------------------------------------
   Admin bar
   The Webflow navbars are position:fixed at top:0, so the admin bar overlaps
   them for logged-in users. Push the fixed chrome down instead.
   --------------------------------------------------------------------------- */
body.admin-bar .bb-nav {
	top: 32px;
}

@media screen and (max-width: 782px) {
	body.admin-bar .bb-nav {
		top: 46px;
	}
}

/* ---------------------------------------------------------------------------
   Collection lists
   Webflow renders an empty-state div when a collection has no items. Our
   templates omit the list entirely instead, but keep the class harmless in case
   imported content carries it.
   --------------------------------------------------------------------------- */
.w-dyn-empty {
	display: none;
}

/* ---------------------------------------------------------------------------
   Images that are sized by their height

   X4 gave every image its intrinsic width and height as attributes, so the
   browser can reserve the right box before the file arrives. Those attributes
   are presentational hints, which means they behave like the lowest-priority
   CSS rather than like data - and that cuts both ways:

   - an image whose CSS sets only a width was given a height that fought it.
     That was the stretching reported earlier, fixed globally by
     img { height: auto } further down.
   - an image whose CSS sets only a height is given a width that fights it the
     same way. Two cases here, and they are the mirror image of the first.

   The fix is not to drop the attributes - the ratio they carry is what reserves
   the space. It is to say which dimension leads, so the other is computed from
   that ratio. Stated here because author CSS outranks a presentational hint,
   which is the whole reason the attribute could win in the first place.
   --------------------------------------------------------------------------- */

/* Workshop wordmark. No CSS of its own in the export - it is laid out entirely
   by height="40", with the width left to follow. */
.image-3 {
	height: 40px;
	width: auto;
}

/* Workshop feature icons, 13 of them. The class fixes the height at 36px and
   says nothing about width, so a 128px-wide attribute stretched square icons
   into wide ones. */
.features-icon {
	width: auto;
}

/* ---------------------------------------------------------------------------
   Heading levels that moved, type that did not

   Several headings were re-levelled so each page has one h1 and no skipped
   levels. That is a change to the document outline, and it is meant to be
   invisible - but Webflow styles h1 through h6 as tags, setting font-family,
   font-size, font-weight, line-height and both margins on each. Where a
   heading's own class already states all of those, changing the tag changes
   nothing. Where the class leaves a gap, the tag was filling it, and moving
   the heading resizes it.

   Four did. Each rule below restores exactly the value that heading had in the
   export, and nothing else - checked property by property against the exported
   page rather than eyeballed.

   If a heading is ever re-levelled again, check the same way: compare the
   class's own declarations against the h1-h6 rules in
   re-brandbeat.webflow.css, and pin whatever the class does not set.
   --------------------------------------------------------------------------- */

/* Home and Location, closing CTA. Its class sets no type at all, so this was
   entirely the h1 rule: 38/44 rather than h2's 32/36. */
.cta_heading {
	font-size: 38px;
	line-height: 44px;
}

/* Home, offer popup. Was an h6 - the only place on the site where a heading
   took Montserrat rather than Oswald, and the tight 18px leading with it. */
.offer_popup-h6 {
	font-family: Montserrat, sans-serif;
	line-height: 18px;
}

/* Blog index, "Latest blogs". Promoted to h1, which would have loosened the
   leading to 44px; the export sets 42px type on 36px. */
.blog_content-h2 {
	line-height: 36px;
}

/* FAQs, the page title. Promoted to h1 from an h2 whose class sets only the
   family, so both size and leading came from the tag. */
.heading-2.faqs-mobile-alignment {
	font-size: 32px;
	line-height: 36px;
}

/* Related-post card titles, in the blog post's "Other blogs" row and the
   service page's sidebar. These were h5 - the class sizes them in em and
   leaves the family to the tag, and h5 is one of the two levels Webflow sets
   in Montserrat rather than Oswald. */
.content_h5 {
	font-family: Montserrat, sans-serif;
}

/*
 * FAQ group labels - "General", "Rebranding", and so on.
 *
 * The only heading on the site that was not a heading before: the export has a
 * plain div inside the orange overline strip, taking the strip's own 14px
 * Montserrat by inheritance. It has to be a heading now, because the page runs
 * h1 title, h2 group, h3 question and the group was the missing rung - but a
 * heading brings 32px Oswald and two margins with it, which turned a small
 * orange label into a headline.
 *
 * So it inherits, exactly as the div did. Semantics from the tag, appearance
 * from the strip.
 */
.section-tag_container h2 {
	margin: 0;
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
	letter-spacing: inherit;
	text-transform: inherit;
	color: inherit;
}

/* ---------------------------------------------------------------------------
   Accessibility
   The export ships no visible focus style. Add one that works on both the light
   and dark sections of the design.
   --------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
	outline: 2px solid #ed4b00;
	outline-offset: 3px;
}

/* Skip link, hidden until focused. */
.brandbeat-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	/* Above the navbar and the open menu both - it is the first thing a
	   keyboard user reaches, and it is only on screen while focused. */
	z-index: 10002;
	padding: 12px 20px;
	background: #020202;
	color: #fff;
	font-family: Montserrat, sans-serif;
	font-size: 14px;
	text-decoration: none;
}

.brandbeat-skip-link:focus {
	left: 8px;
	top: 8px;
}

/* ---------------------------------------------------------------------------
   Motion
   The Webflow interaction engine drives transforms directly, so it ignores the
   media query. Neutralise the CSS-driven motion at least.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ---------------------------------------------------------------------------
   Lifted out of inline <style> blocks in the Webflow export.

   These sat in w-embed divs on the home page (and repeat on thank-you.html).
   The awards marquee appeared twice in the export; it is defined once here.
   --------------------------------------------------------------------------- */

/* Awards / "Featured In" logo marquee. */
@keyframes scroll {
	from { transform: translateX(0); }
	to   { transform: translateX(-100%); }
}

.logos-row {
	animation: scroll 20s linear infinite;
}

.logos-container:hover .logos-row {
	animation-play-state: paused;
}

/* The marquee is decorative; stop it when the viewer asks for less motion. */
@media (prefers-reduced-motion: reduce) {
	.logos-row {
		animation: none;
	}
}

/* Frosted panel behind hero content. */
.frosted_block_parent {
	-webkit-backdrop-filter: blur(2em);
	backdrop-filter: blur(2em);
}

/* Vertical scroll-hint label. */
.horizontal {
	writing-mode: vertical-rl;
}

/* ---------------------------------------------------------------------------
   Scroll lock

   Applied by site.js while the overlay menu, the offer popup, or an expanded
   blog card is open, so the page behind the panel cannot scroll. The panels
   themselves keep their own scrolling.
   --------------------------------------------------------------------------- */
html.bb-scroll-locked,
html.bb-scroll-locked body {
	overflow: hidden;
	overscroll-behavior: none;
}

/* Replace the width the scrollbar was occupying so the layout does not shift. */
html.bb-scroll-locked body {
	padding-right: var(--bb-scrollbar-gap, 0px);
}

/* The open panel scrolls internally. */
html.bb-scroll-locked .nav_menu-hover-cont,
html.bb-scroll-locked .offer_popup-wrapper,
html.bb-scroll-locked [fs-scrolldisable-element="preserve"] {
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
}

/* ---------------------------------------------------------------------------
   Fullscreen menu: trailing space

   Superseded. The strip is a scroll container now and both ends are set in the
   block above; --bb-nav-trail is still the knob, but it is a length rather than
   a percentage of a box that no longer has a fixed width.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   FAQ accordion, service-page variant

   No animation rules here on purpose. Webflow's interaction engine owns these
   panels - it binds by CSS selector, animates the content height from 0 to
   auto on click, and dims the sibling items on hover. Adding a transition or a
   collapsed state here would run a second animation against the same element
   and make it stutter.

   Only the keyboard affordance is ours; see initItemAccordionKeyboard().
   --------------------------------------------------------------------------- */
.faq_accordion-title:focus-visible {
	outline: 2px solid #ed4b00;
	outline-offset: 3px;
}

/* ---------------------------------------------------------------------------
   Rich-text colour inheritance

   Webflow's colour classes were written for elements holding plain text. Rich
   text from the editor arrives wrapped in its own <p>, which carries no colour
   class, so it falls back to the default dark body colour on dark sections.
   Let those descendants inherit from the coloured wrapper.
   --------------------------------------------------------------------------- */
.text-color-gray.is--white,
.text-color-gray.is--white p,
.text-color-gray.is--white li,
.faq_answers .is--white p,
.faq_answers .is--white li {
	color: var(--lace-cap);
}

/*
 * The answer is var(--black) in the original. It must be stated explicitly
 * rather than inherited: .faq_accordion-item sets color:#fff, so "inherit"
 * pulls white and the answer disappears against its light panel. The nested
 * <p> that the editor emits needs the same treatment for the same reason.
 */
.faq_accordion-paragraph,
.faq_accordion-paragraph p,
.faq_accordion-paragraph li {
	color: var(--black);
}

/* ---------------------------------------------------------------------------
   Form validation states

   Messages render next to the field rather than in a browser tooltip, so they
   stay visible while the person corrects the entry.
   --------------------------------------------------------------------------- */
.bb-field-error {
	margin-top: 6px;
	font-family: Montserrat, sans-serif;
	font-size: 12.5px;
	line-height: 1.4;
	color: #ed4b00;
}

.w-input.bb-invalid,
.offer_popup-form-input.bb-invalid {
	border-color: #ed4b00;
}

/* The popup sits on a dark ground; keep the message legible there. */
.offer_popup-wrapper .bb-field-error {
	color: #ff8a5c;
}

/* ---------------------------------------------------------------------------
   Footer: social icons under the contact details

   The newsletter signup is hidden until there is a newsletter to send, which
   left the social icons stranded in an empty column. They now sit under the
   email address in the brand block instead.
   --------------------------------------------------------------------------- */
.social_block.in--brand-block {
	margin-top: 24px;
}

.social_block.in--brand-block .footer_social-icons {
	justify-content: flex-start;
}

/* The row the newsletter used to share; keep it from reserving empty space. */
.footer_social-block .contact-us_block:empty,
.footer_social-block .contact-form_block:empty {
	display: none;
}

/* ---------------------------------------------------------------------------
   Fluent Forms, restyled as the Webflow originals

   The fields already carry the Webflow class names, but Fluent Forms' own
   .ff-el-form-control and .ff-btn rules load after the theme stylesheet and
   win on several properties. These restore the original values exactly -
   measured against .offer_popup-form-input and .offer_popup-form-submit in
   re-brandbeat.webflow.css rather than guessed.

   Scoped to .brandbeat-form so any other Fluent Forms on the site keep the
   plugin's default look. The class is doubled deliberately: Fluent Forms
   enqueues its stylesheet when the shortcode runs, so it loads after this file
   and wins on equal specificity. Repeating the class adds one specificity
   point, which is cheaper to reason about than !important.
   --------------------------------------------------------------------------- */

/* Text inputs. */
.brandbeat-form.brandbeat-form .ff-el-form-control {
	color: #333;
	background-color: #fff;
	border: 1px solid #00000059;
	border-radius: 3px;
	padding-left: 20px;
	padding-right: 20px;
	margin-bottom: 15px;
	font-family: Montserrat, sans-serif;
	font-weight: 500;
	box-shadow: none;
}

.brandbeat-form.brandbeat-form .ff-el-form-control:focus {
	border-color: #000;
	box-shadow: none;
}

/* The input carries the original 15px gap; the plugin's group wrapper would
   otherwise add a second one on top. */
.brandbeat-form.brandbeat-form .ff-el-group {
	margin-bottom: 0;
}

/* The fields have placeholders, not labels, exactly as in the export. */
.brandbeat-form.brandbeat-form .ff-el-input--label {
	display: none;
}

/* Submit button. */
.brandbeat-form.brandbeat-form .ff-btn-submit {
	width: 100%;
	border: 0;
	border-radius: 3px;
	box-shadow: none;
	font-family: Montserrat, sans-serif;
	font-size: 12px;
	font-weight: 700;
	line-height: 20px;
	letter-spacing: 2px;
	text-align: center;
	text-transform: uppercase;
	transition: background-color 0.25s ease-in-out;
}

.brandbeat-form.brandbeat-form .ff-btn-submit:hover {
	background-color: var(--orange-red);
}

/* Validation messages, matched to the ones our own validator renders. */
.brandbeat-form.brandbeat-form .ff-el-is-error .ff-el-form-control {
	border-color: #ed4b00;
}

.brandbeat-form.brandbeat-form .error.text-danger {
	margin: -8px 0 12px;
	font-family: Montserrat, sans-serif;
	font-size: 12.5px;
	line-height: 1.4;
	color: #ed4b00;
}

/* ---------------------------------------------------------------------------
   Offer popup form

   Only the input font size departs from the original, by request.
   --------------------------------------------------------------------------- */
.offer_popup-wrapper .ff-el-form-control,
.offer_popup-wrapper .ff-el-form-control::placeholder {
	font-size: 0.8rem;
}


/* ---------------------------------------------------------------------------
   Blog pagination

   paginate_links() emits plain <a>/<span> elements; Webflow's pagination was
   two buttons. These give the generated links the same look and put the page
   numbers between them.
   --------------------------------------------------------------------------- */
.brandbeat-pagination {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 10px;
}

.brandbeat-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 42px;
	height: 42px;
	padding: 0 14px;
	border: 1px solid currentColor;
	border-radius: 3px;
	font-family: Montserrat, sans-serif;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 1px;
	text-transform: uppercase;
	text-decoration: none;
	transition: background-color 0.25s ease-in-out, color 0.25s ease-in-out;
}

.brandbeat-pagination .page-numbers:hover,
.brandbeat-pagination .page-numbers.current {
	background-color: var(--kimchi);
	border-color: var(--kimchi);
	color: #fff;
}

.brandbeat-pagination .page-numbers.dots {
	border-color: transparent;
}

/* ---------------------------------------------------------------------------
   Blog article

   .body-block_header is the divider image between sections. It carries a
   Webflow placeholder background in the stylesheet; the real image is set
   inline by the template, so hide the block when there is none rather than
   showing the placeholder.
   --------------------------------------------------------------------------- */
.body-block_header:not([style*="background-image"]) {
	display: none;
}

/* Images inside article rich text run full width of the column by default;
   add alignleft / alignright / aligncenter in the editor to float or centre one
   at its natural size. */
.article.w-richtext img,
.article.w-richtext figure {
	display: block;
	width: 100%;
	height: auto;
	margin: 0;
}

.article.w-richtext figure.align-left,
.article.w-richtext img.alignleft {
	width: auto;
	max-width: 50%;
	float: left;
	margin: 6px 28px 18px 0;
}

.article.w-richtext figure.align-right,
.article.w-richtext img.alignright {
	width: auto;
	max-width: 50%;
	float: right;
	margin: 6px 0 18px 28px;
}

.article.w-richtext figure.w-richtext-align-center,
.article.w-richtext img.aligncenter {
	width: auto;
	max-width: 100%;
	margin-left: auto;
	margin-right: auto;
}

.article.w-richtext figure figcaption {
	margin-top: 8px;
	font-family: Montserrat, sans-serif;
	font-size: 13px;
	text-align: center;
	color: #607080;
}

/* ---------------------------------------------------------------------------
   Blog card date
   --------------------------------------------------------------------------- */
.blog_collection-item .blog_date,
.blog_content-block .blog_date {
	color: #99a1ba;
	font-size: 1rem;
	font-weight: 400;
}

/* ---------------------------------------------------------------------------
   Blog category bar

   Inactive links keep the export's plain-text treatment; only the current one
   takes a filled pill, so the active state is the only thing that reads as a
   button.
   --------------------------------------------------------------------------- */
.blog_category-list {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: center;
}

.blog_category-link.is-active {
	padding: 8px 18px;
	border-radius: 999px;
	background-color: var(--kimchi);
	color: #fff;
	text-decoration: none;
}

.blog_category-link:focus-visible {
	outline: 2px solid var(--kimchi);
	outline-offset: 3px;
}

/* ---------------------------------------------------------------------------
   Blog card excerpt

   Three lines by default - roughly the 150-160 characters a search snippet
   shows - opening to the full text on hover or keyboard focus.

   This expands in the flow rather than floating a panel over the card. The
   overlay version covered the date and the See blog button, and its own
   bounds moved as it opened: the mouse could end up outside the element that
   was keeping it open, which closed it, which put the mouse back inside, which
   opened it again. Growing the card cannot do that - the text expands
   underneath the cursor and the card grows with it, so the pointer never
   leaves the thing it is hovering.

   Only the hovered row changes height. Cards wrap two per row and stretch to
   match, so the rows below shift down and nothing overlaps.
   --------------------------------------------------------------------------- */
.blog_excerpt-wrap {
	width: 100%;
	align-self: stretch;
}

.blog_excerpt {
	display: -webkit-box;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.blog_collection-item:hover .blog_excerpt,
.blog_collection-item:focus-within .blog_excerpt {
	-webkit-line-clamp: unset;
	line-clamp: unset;
	overflow: visible;
}

/* ---------------------------------------------------------------------------
   Blog section headings

   The export indents "Latest blogs" and "Recommended blogs" to line up with
   the cards below them, but only writes the rule inside a 991px media query -
   so on desktop, the width the indent exists for, the headings sit flush left
   and out of line with everything under them.
   --------------------------------------------------------------------------- */
.blog_section-title {
	padding-left: 10px;
}

/* ---------------------------------------------------------------------------
   Featured slide category label

   The export turns this green below 992px, which reads as a mistake rather
   than a choice - it is the brand orange everywhere else.
   --------------------------------------------------------------------------- */
.blog_slider-title {
	color: var(--kimchi);
}

/* ---------------------------------------------------------------------------
   Rich text captions

   Webflow sets figcaption to display:table-caption, which shrink-wraps it to
   the left of the column. Block keeps it under the image at full width.
   --------------------------------------------------------------------------- */
.w-richtext figure.w-richtext-figure-type-image > figcaption,
.w-richtext figure[data-rt-type="image"] > figcaption {
	display: block;
	caption-side: unset;
	text-align: center;
}

/* ---------------------------------------------------------------------------
   Blog CTA, contact variant

   The original was a newsletter row: a short heading beside a wide input with
   an absolutely-positioned button. With the input gone that button had nothing
   to size against, so the layout is rebuilt here rather than inherited.
   --------------------------------------------------------------------------- */
.bb-cta--contact .bb-cta__block {
	position: relative;
	overflow: hidden;
	padding: 56px 48px;
	border-radius: 10px;
	background-color: var(--deep-sea-exploration);
	color: #fff;
}

/* Accent: a soft off-centre glow plus a fine diagonal grid, echoing the
   gradient-and-grain treatment used across the site without competing with
   the copy. */
.bb-cta--contact .bb-cta__block::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(60% 120% at 88% 12%, rgba(237, 75, 0, 0.42), rgba(237, 75, 0, 0) 62%),
		radial-gradient(45% 100% at 8% 92%, rgba(11, 0, 218, 0.55), rgba(11, 0, 218, 0) 70%);
	pointer-events: none;
}

.bb-cta--contact .bb-cta__block::after {
	content: "";
	position: absolute;
	inset: 0;
	background-image:
		repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.055) 0 1px, transparent 1px 14px);
	pointer-events: none;
}

.bb-cta--contact .bb-cta__grid {
	position: relative;
	z-index: 1;
	/* Flex rather than grid so the copy and the button push to opposite ends
	   the way space-between does, instead of the button hugging a sized track. */
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 40px;
}

/* The copy must be allowed to shrink. Its paragraph is capped at 55ch, which is
   wider than the space left beside the button - without shrink and min-width:0
   the two wrap onto separate rows and space-between has nothing to distribute. */
.bb-cta--contact .bb-cta__copy {
	/* flex-basis 0, not auto: with auto the basis is the content width, and an
	   80px heading is wide enough to claim the whole row and push the button
	   onto a second line. From 0 the copy takes whatever is left after the
	   button and the heading wraps inside it. */
	flex: 1 1 0;
	min-width: 0;
}

.bb-cta--contact .bb-cta__action {
	flex: 0 0 auto;
}

.bb-cta--contact .bb-cta__heading {
	margin: 0 0 14px;
	font-family: Oswald, sans-serif;
	font-size: clamp(2.5rem, 6vw, 5rem);
	font-weight: 500;
	line-height: 1.1;
	text-transform: uppercase;
	color: #fff;
}

.bb-cta--contact .bb-cta__text {
	max-width: 55ch;
	margin: 0;
	font-family: Montserrat, sans-serif;
	font-size: 1.25rem;
	font-weight: 400;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.86);
}

.bb-cta--contact .bb-cta__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 16px 50px;
	border-radius: 3px;
	background-color: var(--kimchi);
	font-family: Montserrat, sans-serif;
	font-size: 1rem;
	font-weight: 700;
	letter-spacing: 2px;
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	color: #fff;
	transition: background-color 0.25s ease-in-out, transform 0.25s ease;
}

.bb-cta--contact .bb-cta__button:hover {
	background-color: var(--orange-red);
	transform: translateY(-2px);
}

.bb-cta--contact .bb-cta__button:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 3px;
}

@media screen and (max-width: 767px) {
	.bb-cta--contact .bb-cta__block {
		padding: 40px 26px;
	}
	.bb-cta--contact .bb-cta__grid {
		gap: 26px;
	}
	.bb-cta--contact .bb-cta__button {
		width: 100%;
	}
}

/* ---------------------------------------------------------------------------
   Copy-link confirmation

   The Webflow stylesheet already defines both halves of this state - an orange
   .is-copylink.active and a .copy_status reading "Copied!" - but never connects
   them: .copy_status is display:none with no rule that ever shows it. These two
   rules complete it. Buttons rather than anchors carry the share icons now, so
   the shared button reset keeps them looking identical to the exported links.
   --------------------------------------------------------------------------- */
.fs-socialshare_link.is-copylink.active .copy_icon {
	display: none;
}

.fs-socialshare_link.is-copylink.active .copy_status {
	display: block;
}

button.fs-socialshare_link {
	appearance: none;
	border: 0;
	font: inherit;
	cursor: pointer;
}

/* ---------------------------------------------------------------------------
   Sidebar CTA button

   .button-2.width-100 was written for the newsletter's <input type="submit">.
   As an anchor it needs the two things an input gets for free - to be a block
   in the flow, and to not carry a link underline. Everything else (colour,
   padding, type) comes from the Webflow stylesheet unchanged.
   --------------------------------------------------------------------------- */
a.bb-sidebar-cta__button {
	display: block;
	text-decoration: none;
}

/* The line under the button ("Prefer email?") sat straight against it. The
   newsletter version never needed this because its own fine print followed a
   form, which brought its own margin. */
.bb-sidebar-cta__button + .p_smallest {
	margin-top: 16px;
}

/* ===========================================================================
   Team member dialog

   Replaces the modal in the Webflow export, which was two unstyled images
   beside unstyled text. This one rebuilds the standalone team page's layout -
   portrait beside name, role, bio and contacts - inside a panel that uses the
   site's own vocabulary: Oswald display, Montserrat caps for the role, Vollkorn
   for the bio, the 1rem radius from .team-member-image, and kimchi as the one
   accent.

   The panel is a plain element rather than <dialog>, because the export's
   scroll-lock attribute and the site's z-index stack both assume normal flow;
   ::backdrop and the top layer would sit outside all of it.
   =========================================================================== */
.bb-modal {
	position: fixed;
	z-index: 10000;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	background-color: rgba(2, 2, 2, 0.72);
	/* The site already uses backdrop blur on the frosted nav blocks, so this
	   reads as part of the same language rather than a new effect. */
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
	overflow-y: auto;
	overscroll-behavior: contain;
}

.bb-modal.is--hidden {
	display: none;
}

.bb-modal__panel {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: 1040px;
	max-height: calc(100vh - 48px);
	margin: auto;
	background-color: var(--white, #fff);
	border-radius: 1rem;
	overflow: hidden;
	box-shadow: 0 32px 80px -24px rgba(2, 2, 2, 0.6);
}

.bb-modal__close {
	position: absolute;
	z-index: 2;
	top: 16px;
	right: 16px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	appearance: none;
	color: var(--white, #fff);
	background-color: rgba(2, 2, 2, 0.72);
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	transition: background-color 0.2s ease, transform 0.2s ease;
}

.bb-modal__close svg {
	width: 20px;
	height: 20px;
}

.bb-modal__close:hover,
.bb-modal__close:focus-visible {
	background-color: var(--kimchi, #ed4b00);
	transform: scale(1.06);
}

.bb-modal__close:focus-visible {
	outline: 2px solid var(--white, #fff);
	outline-offset: 2px;
}

/* --- the member block itself, reusable outside the dialog ---------------- */

.bb-member {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	min-height: 0;
	overflow: hidden;
}

.bb-member__portrait {
	position: relative;
	background-color: var(--anti-flash-white, #f2f3f4);
}

.bb-member__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 12%;
}

.bb-member__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.75rem;
	padding: 3rem;
	overflow-y: auto;
}

.bb-member__eyebrow {
	margin: 0;
	font-family: Montserrat, sans-serif;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--kimchi, #ed4b00);
}

.bb-member__name {
	margin: 0;
	font-family: Oswald, sans-serif;
	font-size: clamp(2rem, 3.2vw, 2.75rem);
	font-weight: 500;
	line-height: 1;
	color: var(--black, #020202);
	text-wrap: balance;
}

/* The role sits under the name behind a short orange rule - the same idea as
   the vertical divider the team page used between role and email, kept because
   it is the one detail that made that row feel like Brand Beat. */
.bb-member__role {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin: 0;
	font-family: Montserrat, sans-serif;
	font-size: 0.8125rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #6b6b6b;
}

.bb-member__role::before {
	content: "";
	flex: 0 0 auto;
	width: 28px;
	height: 2px;
	background-color: var(--kimchi, #ed4b00);
}

.bb-member__bio {
	max-width: 52ch;
	margin-top: 0.5rem;
	font-family: Vollkorn, serif;
	font-size: 1.0625rem;
	line-height: 1.75;
	color: #333;
}

.bb-member__bio p {
	/* A generic p rule in the Webflow stylesheet was winning on size. */
	font-size: inherit;
	line-height: inherit;
	margin: 0 0 0.8em;
}

.bb-member__bio p:last-child {
	margin-bottom: 0;
}

.bb-member__contact {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.5rem;
	margin: 1.25rem 0 0;
	padding: 1.25rem 0 0;
	list-style: none;
	border-top: 1px solid var(--lace-cap, #ebeaed);
	width: 100%;
}

.bb-member__link {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: Montserrat, sans-serif;
	font-size: 0.8125rem;
	font-weight: 500;
	color: var(--black, #020202);
	text-decoration: none;
	transition: color 0.2s ease;
}

.bb-member__link:hover,
.bb-member__link:focus-visible {
	color: var(--kimchi, #ed4b00);
}

.bb-member__icon {
	display: flex;
	width: 16px;
	height: 16px;
}

.bb-member__icon svg {
	width: 100%;
	height: 100%;
}

/* --- narrow screens ------------------------------------------------------ */

@media (max-width: 767px) {
	.bb-modal {
		padding: 0;
		align-items: stretch;
	}

	.bb-modal__panel {
		max-width: none;
		max-height: none;
		min-height: 100%;
		border-radius: 0;
	}

	/* Stacked, with the portrait as a banner rather than a full column - a
	   two-thirds-height photo above a paragraph pushes the text off screen. */
	.bb-member {
		grid-template-columns: minmax(0, 1fr);
	}

	.bb-member__portrait {
		height: 46vh;
		max-height: 340px;
	}

	.bb-member__body {
		gap: 0.625rem;
		padding: 1.75rem 1.5rem 2.5rem;
		overflow-y: visible;
	}
}

@media (min-width: 768px) and (max-width: 991px) {
	.bb-member__body {
		padding: 2.25rem;
	}
}

/* --- motion -------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
	.bb-modal:not(.is--hidden) {
		animation: bb-modal-fade 0.18s ease-out;
	}

	.bb-modal:not(.is--hidden) .bb-modal__panel {
		animation: bb-modal-rise 0.28s cubic-bezier(0.16, 1, 0.3, 1);
	}
}

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

@keyframes bb-modal-rise {
	from { opacity: 0; transform: translateY(16px) scale(0.985); }
	to   { opacity: 1; transform: none; }
}

/* ===========================================================================
   About page team grid

   Four adjustments to the exported card, requested by the client. The Webflow
   stylesheet stays untouched, so each is an override here rather than an edit
   there - which also means each one needs to say what it is replacing.
   =========================================================================== */

/*
 * Was width: 31.5%.
 *
 * Dropping the width entirely, as asked, does remove the hardcoded number - but
 * it drops the grid from three cards per row to two. The card then sizes to its
 * image, which lands at exactly 100%/3, and three of those plus two 25px gaps
 * is wider than the row. That 31.5% was 33.3% minus a rough allowance for the
 * gaps, which is why it looked arbitrary.
 *
 * So the number is gone, but the three-up rhythm is kept, with the gap
 * subtracted properly instead of estimated. Below 768px the export goes
 * one-up on its own and neither rule applies.
 */
@media (min-width: 992px) {
	.team_item {
		width: calc((100% - 50px) / 3); /* two 25px gaps */
	}
}

@media (min-width: 768px) and (max-width: 991px) {
	.team_item {
		width: calc((100% - 38px) / 3); /* two 19px gaps */
	}
}

/* The exported card carries padding that inset the image from its own frame. */
.team_card-content {
	padding: 0;
}

/* The image is a replaced inline element, so it sat on the text baseline and
   left a few pixels of background showing under it. */
.team_card-img {
	display: block;
}

/* ---------------------------------------------------------------------------
   Team dialog width

   Scoped to the team grid rather than set on .bb-modal__panel globally: the
   panel is a general component, and the next thing that uses it will not want
   the About page's measurements.
   --------------------------------------------------------------------------- */
.about_team-section .bb-modal__panel {
	max-width: 810px;
}

/* ===========================================================================
   Contact page
   =========================================================================== */

/* The heading sat straight on top of the paragraph under it. */
.contact_form-section .heading2 {
	margin-bottom: 1.25rem;
}

/* The hero paragraph was set at the body default, which is small for a lede
   that is the only copy on a full-height hero. */
.paragraph2.is--cloudblue {
	font-size: 1.125rem;
}

/* ---------------------------------------------------------------------------
   Contact: the two halves swap backgrounds

   The export puts the photograph behind the booking embed and flat black behind
   the form. Swapped: the form now sits on the photograph and the booking widget
   on black. The widget renders its own light card on top of whatever is behind
   it, so a photograph there was mostly hidden anyway - and the form is the half
   worth giving the image to.

   The overlay is what makes the form readable. It is a dark scrim, weighted to
   the left where the text starts, so the picture still reads as a picture on
   the right-hand side instead of being flattened to a texture.
   --------------------------------------------------------------------------- */
.contact_form-section .container.border-top {
	position: relative;
	isolation: isolate;
	background-image: url("../images/pexels-photo-2214394_1.avif");
	background-position: 50% 50%;
	background-size: cover;
}

.contact_form-section .container.border-top::before {
	content: "";
	position: absolute;
	z-index: -1;
	inset: 0;
	background-image: linear-gradient(
		100deg,
		rgba(2, 2, 2, 0.94) 0%,
		rgba(2, 2, 2, 0.88) 42%,
		rgba(2, 2, 2, 0.62) 100%
	);
	pointer-events: none;
}

/* Black, in place of the photograph the export had here. */
.calendly_embed {
	background-image: none;
	background-color: var(--black, #020202);
}

/* ---------------------------------------------------------------------------
   Contact form fields

   The design is the export's: no box, no fill, just a white rule under each
   field. Fluent Forms brings its own control styling, and its stylesheet loads
   after this one, so each property has to be stated rather than inherited.

   The doubled class is deliberate. A generic .brandbeat-form.brandbeat-form
   block further up styles the offer popup's light panel, and its doubled
   class outweighs a single one wherever both match. This matches that
   weight rather than raising it further.

   The labels are rendered but hidden. They exist because the form had none at
   all - the placeholder was the only thing naming a field, and a placeholder
   disappears the moment someone types into it, leaving a screen reader user
   and anyone re-reading their answers with nothing to go on.
   --------------------------------------------------------------------------- */
.brandbeat-form--audit .ff-el-input--label,
.brandbeat-form--contact.brandbeat-form--contact .ff-el-input--label {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.brandbeat-form--contact.brandbeat-form--contact .ff-el-form-control,
.brandbeat-form--contact.brandbeat-form--contact input[type="text"],
.brandbeat-form--contact.brandbeat-form--contact input[type="tel"],
.brandbeat-form--contact.brandbeat-form--contact input[type="email"],
.brandbeat-form--contact.brandbeat-form--contact textarea {
	width: 100%;
	height: 50px;
	padding: 0 0 0 4px;
	color: var(--white, #fff);
	background-color: transparent;
	border: 0;
	border-bottom: 1px solid var(--white, #fff);
	border-radius: 0;
	box-shadow: none;
	font-family: Montserrat, sans-serif;
	font-size: 1rem;
}

.brandbeat-form--contact.brandbeat-form--contact textarea {
	height: 100px;
	padding-top: 12px;
	resize: vertical;
}

.brandbeat-form--contact.brandbeat-form--contact ::placeholder {
	color: var(--white, #fff);
	opacity: 0.75;
}

/* A bottom rule is the only affordance these fields have, so focus has to be
   unmistakable - and visible to someone who cannot perceive the colour change
   alone, which is why the rule thickens as well as changing colour. */
.brandbeat-form--contact.brandbeat-form--contact .ff-el-form-control:focus,
.brandbeat-form--contact.brandbeat-form--contact textarea:focus {
	outline: none;
	border-bottom-width: 2px;
	border-bottom-color: var(--kimchi, #ed4b00);
}

/* Autofill repaints the field with the browser's own yellow, which loses both
   the transparent ground and the white text. */
.brandbeat-form--contact.brandbeat-form--contact input:-webkit-autofill,
.brandbeat-form--contact.brandbeat-form--contact input:-webkit-autofill:focus {
	-webkit-text-fill-color: var(--white, #fff);
	transition: background-color 100000s ease-in-out 0s;
}

/*
 * Name and phone share a row above 767px, as they do in the export.
 *
 * Fluent Forms puts every field in its own .ff-el-group, so the pairing has to
 * come from here. :has() is what makes it addressable - the groups are
 * otherwise identical, and counting them with nth-child breaks the moment a
 * field is added or the honeypot moves. Where :has() is unsupported the fields
 * simply stack, which is the mobile layout and perfectly usable.
 */
@media (min-width: 768px) {
	.brandbeat-form--contact.brandbeat-form--contact form fieldset {
		display: grid;
		margin: 0;
		padding: 0;
		border: 0;
		min-width: 0;
		grid-template-columns: 1fr 1fr;
		column-gap: 5%;
	}

	.brandbeat-form--contact.brandbeat-form--contact form fieldset > * {
		grid-column: 1 / -1;
	}

	.brandbeat-form--contact.brandbeat-form--contact .ff-el-group:has(input[name="names"]) {
		grid-column: 1;
	}

	.brandbeat-form--contact.brandbeat-form--contact .ff-el-group:has(input[name="phone"]) {
		grid-column: 2;
		grid-row: 1;
	}
}

.brandbeat-form--contact.brandbeat-form--contact .ff-el-group {
	margin-bottom: 20px;
}

/* Validation messages: the plugin's default red is too dark to read on this
   ground, and an icon-free colour change is not enough on its own. */
.brandbeat-form--contact.brandbeat-form--contact .error-text,
.brandbeat-form--contact.brandbeat-form--contact .ff-el-is-error .text-danger {
	color: #ffb4a1;
	font-family: Montserrat, sans-serif;
	font-size: 0.8125rem;
}

.brandbeat-form--contact.brandbeat-form--contact .ff-el-is-error .ff-el-form-control {
	border-bottom-color: #ffb4a1;
	border-bottom-width: 2px;
}

/* Submit: the export's own button, full width. */
.brandbeat-form--contact.brandbeat-form--contact .ff-btn-submit {
	width: 100%;
	height: auto;
	min-height: 52px;
	margin-top: 10px;
	color: var(--white, #fff);
	background-color: var(--kimchi, #ed4b00);
	border: 0;
	border-radius: 4px;
	font-family: Oswald, sans-serif;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 1px;
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color 0.25s ease;
}

.brandbeat-form--contact.brandbeat-form--contact .ff-btn-submit:hover,
.brandbeat-form--contact.brandbeat-form--contact .ff-btn-submit:focus-visible {
	background-color: #ff5100;
}

.brandbeat-form--contact.brandbeat-form--contact .ff-btn-submit:focus-visible {
	outline: 2px solid var(--white, #fff);
	outline-offset: 3px;
}

/* ===========================================================================
   Blog post table of contents
   =========================================================================== */

/* Built from the post's own h2s by brandbeat_post_body(). It reuses the service
   template's Navigate classes so the two read as one component; the rules here
   are the differences that come from sitting in the article column rather than
   a sidebar.

   Two classes on the first rule, because the service sidebar section further
   down this file zeroes .service_toc-nav's padding-left and would otherwise win
   on source order. */
.service_toc-nav.blog_toc {
	background-color: #fdfdfd;
	border: 1px solid #e8e8e8;
	margin-bottom: 40px;
	padding: 32px 40px;
}

.blog_toc .heading-2 {
	margin-top: 0;
	margin-bottom: 16px;
}

/* The export centres this list below 480px and leaves it flush left above,
   so a one-line entry sat indented among wrapped ones. */
.blog_toc .service_list.no-max-width {
	align-items: flex-start;
}

/* .service_link is display:block with 5px of padding, which reads as a solid
   run of text once there are ten of them. */
.blog_toc .service_link {
	padding: 7px 0;
	text-align: left;
}

/* The hover state in the export adds a 1px border, which shifts every link
   below it by a pixel in a list this long. */
.blog_toc .service_link:hover {
	border: 0;
	text-decoration: underline;
}

/* No scroll-margin on the headings: the navbar on a post is position:absolute
   and scrolls away, so nothing covers an anchor that a jump lands on. Webflow's
   own smooth-scroll handles these clicks and ignores scroll-margin-top anyway,
   so a rule here would look like it was doing something and would not be. */

@media screen and (max-width: 767px) {
	.service_toc-nav.blog_toc {
		padding: 24px 20px;
	}
}

/* ===========================================================================
   Service page sidebar
   =========================================================================== */

/* Was padding-left: 30px, which pushed the table of contents out of line with
   the blocks under it. */
.service_toc-nav {
	padding-left: 0;
}

/* The related-reading items sat flush against each other. The list is the
   blog sidebar's own markup, which relies on the gap between cards rather than
   a margin on the item. */
.other_blogs .collection-list-wrapper .w-dyn-items {
	display: flex;
	flex-direction: column;
	gap: 20px;
}

/* ---------------------------------------------------------------------------
   Fullscreen menu: the card strip

   The five cards are 500px each plus margins - about 2750px in total - inside a
   strip the export sizes at 120vw, or 1728px on a 1440 screen. They overflow it
   by roughly a thousand pixels no matter how wide the window is.

   Webflow pans that strip on mouse-move, but its travel is derived from the
   strip's own width against the viewport: 20vw, some 288px. That is a fraction
   of the overflow, so the pan runs out with "Contact" still hanging off the
   right edge. Nothing about the padding could fix that - the cards were always
   further away than the pan could reach.

   So the window becomes a scroll container and the strip sizes to its content,
   for every pointer rather than just touch. The interaction's transform is
   switched off, and site.js maps the mouse across the same scroll range - the
   same gesture, over a distance that actually covers the cards. Touch gets
   native swiping from the same container.

   Below 992px the strip wraps to a grid and none of this applies.
   --------------------------------------------------------------------------- */
@media (min-width: 992px) {
	.nav_menu-content {
		width: 100%;
		max-width: 100vw;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;      /* Firefox */
		-ms-overflow-style: none;   /* old Edge */
	}

	.nav_menu-content::-webkit-scrollbar {
		display: none;              /* Chrome, Safari */
	}

	/* The pan is ours now. Its transform is set inline, so this needs the
	   weight to beat it. */
	.nav_menu-hover-cont .flex_nav {
		transform: none !important;
		padding-right: 0;
	}

	/* Both strips size to their content, or the scroll has nothing to travel
	   over - each was a fixed width narrower than the cards inside it. */
	.nav_menu-hover-cont .flex_nav,
	.nav_menu-hover-cont .flex.is--nav {
		width: max-content;
		min-width: 100%;
	}

	/*
	 * Both ends stated as lengths so they cannot drift, and deliberately
	 * unequal because the design is: more room after the last card than before
	 * the first. End padding is dropped from a container's scrollable overflow
	 * once its children overflow it, so the trailing space has to be a real
	 * box rather than padding.
	 */
	.nav_menu-hover-cont .flex.is--nav {
		padding-left: var(--bb-nav-lead, 10vw);
		padding-right: 0;
	}

	.nav_menu-hover-cont .flex.is--nav::after {
		content: "";
		flex: 0 0 var(--bb-nav-trail, 24vw);
	}
}

/* ---------------------------------------------------------------------------
   The navbar

   One bar, where the export had three: a static one over the hero, plus two
   fixed ones the interaction engine faded in and out on scroll - one solid
   with black assets for the body of the page, one transparent with white
   assets for the dark bands below it. Every navbar bug came from that: three
   menu buttons and three copies of the menu, of which the script could only
   ever wire up the first.

   So the three become two axes on one element, and what IX2 did by swapping
   whole navbars is done here by changing two custom properties:

     --bb-nav-ink      the colour of the logo, the menu lines and the links
     --bb-logo-*       which of the two shipped logos is displayed

   States are ordered by precedence, last wins: the page's resting variant,
   then stuck, then light, then menu-open.

   Only Home and the location pages have a swap at all. Everywhere else the
   export ships a single absolutely-positioned bar that scrolls away with the
   hero and never returns, which is what the base rule below reproduces.
   --------------------------------------------------------------------------- */
.bb-nav {
	--bb-nav-ink: #fff;
	--bb-logo-white: block;
	--bb-logo-black: none;

	/*
	 * Absolute, like every navbar in the export. It sits at the top of the
	 * document and scrolls away with it; the pages that pin a bar do so by
	 * adding is--stuck below.
	 */
	position: absolute;
	z-index: 999;
	background-color: transparent;
	box-shadow: none;
	transition: background-color 0.2s ease, box-shadow 0.2s ease;
}

/* Resting variants, set per page by brandbeat_navbar_variant(). */
.bb-nav.is--assets-black {
	--bb-nav-ink: var(--black, #000);
	--bb-logo-white: none;
	--bb-logo-black: block;
}

.bb-nav.is--bg-solid {
	background-color: #f2f3f4;
	box-shadow: 0 2px 8px #0003;
}

/*
 * Stuck: the hero has scrolled clear of the top of the window.
 *
 * This is the export's second navbar - fixed, #f2f3f4 behind a 2px blur, black
 * assets - and it arrives the way that one did, dropping in from above over
 * half a second rather than appearing. is--leaving is the same bar on its way
 * back out, held for the length of the lift so the slide can finish.
 */
.bb-nav.is--stuck,
.bb-nav.is--leaving {
	--bb-nav-ink: var(--black, #000);
	--bb-logo-white: none;
	--bb-logo-black: block;

	position: fixed;
	z-index: 9999;
	background-color: #f2f3f4;
	box-shadow: 0 2px 8px #0003;
	-webkit-backdrop-filter: blur(2px);
	backdrop-filter: blur(2px);
}

.bb-nav.is--stuck {
	animation: bb-nav-drop 0.5s ease;
}

.bb-nav.is--leaving {
	animation: bb-nav-lift 0.5s ease forwards;
}

@keyframes bb-nav-drop {
	from { transform: translateY(-100%); }
	to   { transform: translateY(0); }
}

@keyframes bb-nav-lift {
	from { transform: translateY(0); }
	to   { transform: translateY(-100%); }
}

/*
 * Light: the mid-page block has scrolled clear too, which in the export is the
 * moment the dark band below it reaches the top of the window. The third
 * navbar - white assets, nothing behind them - and it holds for the rest of
 * the page, exactly as the interaction did.
 */
.bb-nav.is--light,
.bb-nav.is--menu-open {
	--bb-nav-ink: #fff;
	--bb-logo-white: block;
	--bb-logo-black: none;

	background-color: transparent;
	box-shadow: none;
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
}

/*
 * With the menu open the bar has to be pinned and above it, because the close
 * button lives in the bar. On the pages whose bar scrolls away this is the one
 * place it is held in view - opening the menu from a bar that has scrolled
 * halfway off screen would otherwise put the close button above the window.
 */
.bb-nav.is--menu-open {
	position: fixed;
	z-index: 10001;
	animation: none;
}

/* Reloading partway down a page should not replay the entrance. */
.bb-nav.is--instant {
	animation: none;
}

@media (prefers-reduced-motion: reduce) {
	.bb-nav.is--stuck,
	.bb-nav.is--leaving {
		animation: none;
	}
}

/* Both logos ship; the state picks one. Swapping the src instead would flash
   an empty box on every change. */
.bb-nav__logo--white {
	display: var(--bb-logo-white);
}

.bb-nav__logo--black {
	display: var(--bb-logo-black);
}

/*
 * The five lines of the button and the two of the close cross. 200ms is the
 * cross-fade the export used between the black bar and the white one; with a
 * single element the colours are what cross-fade.
 */
.bb-nav .nav-line-1,
.bb-nav .nav-line-2,
.bb-nav .nav-line-3,
.bb-nav .nav-line-4,
.bb-nav .nav_menu-xr,
.bb-nav .nav_menu-xl {
	background-color: var(--bb-nav-ink);
	transition: background-color 0.2s ease;
}

.bb-nav .nav_link {
	color: var(--bb-nav-ink);
	transition: color 0.2s ease;
}

/* The button is a <button> now rather than a div, so it arrives with a
   browser's own chrome on it. */
.bb-nav .nav_menu-btn-wrapper {
	appearance: none;
	-webkit-appearance: none;
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
	color: inherit;
}

/* Open shows the lines, closed shows the cross. The export's own classes said
   which was which; with one button it is a state instead. */
.bb-nav.is--menu-open .nav_menu-open {
	display: none;
}

.bb-nav.is--menu-open .nav_menu-close.hide {
	display: flex;
	/* The export has this fixed, which was harmless inside the panel it used to
	   live in. Inside the button it has to stay with the button. */
	position: absolute;
}

/* ---------------------------------------------------------------------------
   The fullscreen menu

   Also one per page now. Two things about it are ours: it is raised above the
   fixed chrome, and it opens on a class rather than through IX2.

   The export leaves it at z-index 999 while the fixed navbars sit at 9999, so
   anything else in that band showed through an open menu - the blog slider's
   own controls, which is what made them appear to float on top of it.
   --------------------------------------------------------------------------- */
.nav_menu-hover-cont {
	z-index: 10000;
	/*
	 * Shut means parked above the viewport, which is where the export's own
	 * transform put it, not display:none - a panel that is not rendered cannot
	 * animate on its way in. visibility keeps it away from the pointer in
	 * between, delayed on the way out so it is still visible while it leaves.
	 */
	visibility: hidden;
	transform: translate(0, -100vh);
	transition: transform 0.6s cubic-bezier(0.65, 0.05, 0, 1), visibility 0s linear 0.6s;
}

.nav_menu-hover-cont.is--open {
	visibility: visible;
	transform: translate(0, 0);
	transition: transform 0.6s cubic-bezier(0.65, 0.05, 0, 1), visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
	.nav_menu-hover-cont,
	.nav_menu-hover-cont.is--open {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
   Blog post CTA: the optional service button

   Sits beside "Contact Us" rather than above or below it - the wrapper is
   already a grid with auto-flow column, so it only needs a gap. Outlined
   rather than filled, because Contact is still the primary action and two
   solid buttons of equal weight compete instead of ranking.
   --------------------------------------------------------------------------- */
.about-cta_button-wrap {
	grid-column-gap: 16px;
	grid-row-gap: 12px;
}

.button_cta-about.is--ghost {
	background-color: transparent;
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
	transition: background-color 0.25s ease, box-shadow 0.25s ease, color 0.25s ease;
}

.button_cta-about.is--ghost:hover,
.button_cta-about.is--ghost:focus-visible {
	color: var(--black, #020202);
	background-color: var(--white, #fff);
	box-shadow: inset 0 0 0 1px var(--white, #fff);
	outline: none;
}

/* ---------------------------------------------------------------------------
   Booking embed

   Two separate reasons the widget did not fill its side of the page.

   The frame was a hardcoded 700px from the export, so any column taller than
   that showed a band of the grey backing below it. And the column itself was
   100vh, which is only the right height when the form beside it happens to be
   the same - it is a grid cell, and the form is nearly a thousand pixels tall
   at most widths.

   Both are now driven by the row: the cell takes its height from the grid, and
   the frame takes whatever is left inside it after the padding.
   --------------------------------------------------------------------------- */
.calendly_embed {
	height: 100%;
	min-height: 620px;
}

.bb-embed {
	display: flex;
	height: 100%;
	padding: 90px 15px;
	background: #f5f5f5;
}

.bb-embed__frame {
	flex: 1 1 auto;
	width: 100%;
	min-height: 420px;
	overflow: hidden;
}

.bb-embed__iframe {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

/* The two columns stack below 992px, where a full-height frame would push the
   rest of the page a long way down. */
@media (max-width: 991px) {
	.calendly_embed {
		min-height: 0;
	}

	.bb-embed {
		padding: 40px 15px;
	}

	.bb-embed__frame {
		height: 640px;
		flex: 0 0 auto;
	}
}

/* ---------------------------------------------------------------------------
   Contact section height

   The export pins this section to exactly 100vh. Its content does not depend
   on viewport height at all - the form is around 900px whatever the window is
   doing - so on any viewport shorter than the form, the section ended before
   its own contents did and the overflow ran underneath the footer.

   100vh becomes a floor rather than a fixed measure. On a tall window it still
   fills the screen; on a short one it grows to fit and the footer starts after
   it, as it should.
   --------------------------------------------------------------------------- */
.contact_form-section._100vh {
	height: auto;
	min-height: 100vh;
}

/* ---------------------------------------------------------------------------
   Images keep their own proportions

   The width and height attributes added for layout stability are presentational
   hints: the browser maps them to CSS width and height at a level below author
   styles. That is fine while nothing else sets a size - but most images here are
   sized by a class that sets only a width, and the height attribute then filled
   in the gap that "auto" used to occupy. A 189px-tall logo displayed at 64px
   wide was being drawn 64 x 189.

   height:auto restores the intrinsic ratio, and it does not undo the reason the
   attributes are there: with height auto, browsers derive aspect-ratio from the
   two attributes and still reserve the right box before the image loads.

   A bare element selector, so any class that sets a real height still wins -
   .team_card-img, .bb-member__image and the rest are untouched.
   --------------------------------------------------------------------------- */
img {
	height: auto;
}

/* ---------------------------------------------------------------------------
   Fullscreen menu: pressing a card

   On a mouse the cards respond to hover. A touch screen has no hover, so until
   the finger lifts there was nothing to say which card was about to open - and
   because the strip also drags, a press that turns into a drag needs to look
   different from one that turns into a tap.

   The card's own .overlay element is what the design dims with, so pressing
   reuses it rather than introducing a second treatment.
   --------------------------------------------------------------------------- */
@media (hover: none) {
	.nav_menu-hover-cont .large_nav-item .overlay {
		display: block;
		opacity: 0;
		transition: opacity 0.18s ease;
	}

	.nav_menu-hover-cont .large_nav-item.is--pressed .overlay {
		opacity: 0.55;
	}

	.nav_menu-hover-cont .large_nav-item {
		transition: transform 0.18s ease;
	}

	.nav_menu-hover-cont .large_nav-item.is--pressed {
		transform: scale(0.98);
	}
}

/* ---------------------------------------------------------------------------
   Screen-reader-only text

   A WordPress convention that themes are expected to define - core, and plenty
   of plugins, output .screen-reader-text and assume it is hidden. This theme
   never defined it, so anything using it was simply visible: the WhatsApp
   field's label was rendering as body copy beside the input.

   Not display:none, which would take it out of the accessibility tree along
   with the layout.
   --------------------------------------------------------------------------- */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.screen-reader-text:focus {
	z-index: 100000;
	top: 8px;
	left: 8px;
	width: auto;
	height: auto;
	padding: 12px 20px;
	clip: auto;
	clip-path: none;
	color: #fff;
	background-color: var(--black, #020202);
	border-radius: 4px;
}

/* ===========================================================================
   WhatsApp chat button

   Brand navy rather than WhatsApp green: this is Brand Beat's panel, and the
   only WhatsApp thing about it is where the message ends up. The launcher and
   the send button carry kimchi, so the two calls to action on screen read as
   the same brand.
   =========================================================================== */
.bb-wa {
	position: fixed;
	z-index: 9000;
	right: 24px;
	bottom: 24px;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 14px;
	font-family: Montserrat, sans-serif;
}

.bb-wa__launcher {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 60px;
	height: 60px;
	padding: 0;
	appearance: none;
	color: #fff;
	background-color: var(--kimchi, #ed4b00);
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	box-shadow: 0 6px 18px rgba(2, 2, 2, 0.32);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.bb-wa__launcher:hover,
.bb-wa__launcher:focus-visible {
	transform: scale(1.06);
	box-shadow: 0 10px 26px rgba(2, 2, 2, 0.38);
}

.bb-wa__launcher:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 2px;
}

/*
 * Opening the chat wipes the button from kimchi to WhatsApp green.
 *
 * A cross-fade between two saturated colours passes through a muddy middle and
 * reads as a glitch, which is what made the straight swap feel abrupt. Instead
 * the green is a disc that grows from the centre - the colour arrives as a
 * movement rather than a fade, and closing runs it backwards.
 *
 * The easing overshoots very slightly at the end, so the disc settles rather
 * than stopping dead. That is the whole flourish; anything more on a control
 * that toggles this often becomes tiring.
 */
.bb-wa__launcher::before {
	content: "";
	position: absolute;
	z-index: 0;
	inset: 0;
	background-color: #25d366;
	border-radius: 50%;
	transform: scale(0);
	transition: transform 0.42s cubic-bezier(0.34, 1.4, 0.64, 1);
}

.bb-wa.is--open .bb-wa__launcher::before {
	transform: scale(1);
}

/* Above the wipe, and turning with it. */
.bb-wa__glyph {
	position: relative;
	z-index: 1;
	width: 32px;
	height: 32px;
	transition: transform 0.42s cubic-bezier(0.34, 1.4, 0.64, 1);
}

.bb-wa.is--open .bb-wa__glyph {
	transform: rotate(-12deg) scale(1.06);
}

/*
 * The unread badge.
 *
 * Decorative, and hidden from assistive technology: there is no real message
 * waiting, and announcing "1 unread" to a screen reader would be a claim the
 * page cannot support. It shrinks away when the panel opens rather than
 * vanishing, so the eye follows it out.
 */
.bb-wa__badge {
	position: absolute;
	z-index: 2;
	top: -2px;
	right: -2px;
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 22px;
	height: 22px;
	padding: 0 5px;
	font-size: 0.6875rem;
	font-weight: 700;
	line-height: 1;
	color: #fff;
	background-color: #e01b24;
	border: 2px solid #fff;
	border-radius: 11px;
	transform-origin: 70% 30%;
	transition: transform 0.28s cubic-bezier(0.34, 1.4, 0.64, 1), opacity 0.2s ease;
}

.bb-wa.is--seen .bb-wa__badge {
	opacity: 0;
	transform: scale(0);
}

/*
 * Reduced motion: the colour still changes, because it carries meaning, but
 * nothing grows, turns or springs.
 */
@media (prefers-reduced-motion: reduce) {
	.bb-wa__launcher,
	.bb-wa__launcher::before,
	.bb-wa__glyph,
	.bb-wa__badge {
		transition-duration: 0.01ms;
	}

	.bb-wa__launcher:hover,
	.bb-wa__launcher:focus-visible {
		transform: none;
	}

	.bb-wa.is--open .bb-wa__glyph {
		transform: none;
	}
}


.bb-wa__launcher:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 2px;
}


/* --- the panel ----------------------------------------------------------- */

.bb-wa__panel {
	width: min(360px, calc(100vw - 32px));
	overflow: hidden;
	color: #fff;
	background-color: #131a7a;
	border-radius: 16px;
	box-shadow: 0 20px 52px -12px rgba(2, 2, 2, 0.55);
	transform-origin: bottom right;
}

.bb-wa__panel[hidden] {
	display: none;
}

@media (prefers-reduced-motion: no-preference) {
	.bb-wa__panel:not([hidden]) {
		animation: bb-wa-in 0.2s cubic-bezier(0.16, 1, 0.3, 1);
	}
}

@keyframes bb-wa-in {
	from { opacity: 0; transform: translateY(10px) scale(0.97); }
	to   { opacity: 1; transform: none; }
}

.bb-wa__header {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 20px 18px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}

.bb-wa__avatar {
	position: relative;
	flex: 0 0 auto;
	width: 54px;
	height: 54px;
}

.bb-wa__photo {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 20%;
	border-radius: 50%;
}

/* The availability dot. Decorative - it says the line is monitored, not that a
   named person is at the keyboard, so it is not announced. */
.bb-wa__online {
	position: absolute;
	right: 1px;
	bottom: 3px;
	width: 12px;
	height: 12px;
	background-color: #35d07f;
	border: 2px solid #131a7a;
	border-radius: 50%;
}

.bb-wa__who {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-width: 0;
	gap: 2px;
}

.bb-wa__name {
	font-size: 1.0625rem;
	font-weight: 700;
	line-height: 1.2;
}

.bb-wa__role {
	font-size: 0.8125rem;
	line-height: 1.3;
	color: rgba(255, 255, 255, 0.82);
}

.bb-wa__close {
	display: flex;
	align-self: flex-start;
	flex: 0 0 auto;
	padding: 2px;
	color: #fff;
	background: none;
	border: 0;
	border-radius: 4px;
	cursor: pointer;
	opacity: 0.75;
	transition: opacity 0.2s ease;
}

.bb-wa__close:hover,
.bb-wa__close:focus-visible {
	opacity: 1;
}

.bb-wa__close svg {
	width: 18px;
	height: 18px;
}

.bb-wa__body {
	padding: 22px 18px;
}

.bb-wa__bubble {
	max-width: 92%;
	padding: 16px 18px;
	background-color: #0c1157;
	border-radius: 12px;
}

.bb-wa__greeting,
.bb-wa__prompt {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.5;
	color: #fff;
}

.bb-wa__prompt {
	margin-top: 1em;
}

.bb-wa__form {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px 14px;
	border-top: 1px solid rgba(255, 255, 255, 0.14);
}

.bb-wa__input {
	flex: 1 1 auto;
	min-width: 0;
	height: 44px;
	padding: 0 4px;
	font-family: inherit;
	font-size: 0.9375rem;
	color: #fff;
	background-color: transparent;
	border: 0;
	border-radius: 0;
}

.bb-wa__input::placeholder {
	color: rgba(255, 255, 255, 0.62);
}

.bb-wa__input:focus {
	outline: none;
	box-shadow: inset 0 -2px 0 var(--kimchi, #ed4b00);
}

.bb-wa__send {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 42px;
	height: 42px;
	padding: 0;
	color: #fff;
	background-color: var(--kimchi, #ed4b00);
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	transition: background-color 0.2s ease, transform 0.2s ease;
}

.bb-wa__send:hover,
.bb-wa__send:focus-visible {
	background-color: #ff5100;
	transform: scale(1.05);
}

.bb-wa__send:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

.bb-wa__send svg {
	width: 17px;
	height: 17px;
	margin-left: 2px;   /* the glyph's own weight sits left of centre */
}

@media (max-width: 479px) {
	.bb-wa {
		right: 16px;
		bottom: 16px;
	}
}

/* ---------------------------------------------------------------------------
 * Split headlines, merged into one heading each.
 *
 * The design breaks several headlines across two styled lines. The Webflow
 * export gave each line its own <h2>, which put fragments like "Frequently",
 * "Trusted by" and "Let Our Work" into the document outline as headings in
 * their own right. The templates now render one <h2> with the second line as
 * a <span class="bb-h2-line2"> inside it.
 *
 * The span keeps every class the second <h2> had, so the compound selectors in
 * re-brandbeat.webflow.css that give it its colour, size and margins still
 * match. The only thing lost in the change is `display`, which an <h2> got for
 * free and a <span> does not - and what it should be depends entirely on the
 * container, because each of these three laid its children out differently:
 *
 *   .hflex_inner  plain block on desktop  -> the two lines stacked
 *   .vflex_inner  flex row on desktop     -> the two lines sat side by side
 *   .title_inner  flex row on desktop     -> the two lines sat side by side
 *
 * Below 768px all three switch to flex-flow: column, so every line stacks.
 * These rules restate exactly that, and nothing else.
 *
 * Scoped to .bb-h2-line2 on purpose. The home page already uses bare
 * <span class="h2_span highlight"> inside its headings for mid-sentence
 * emphasis ("We'll help *digitally* transform your business") - those are
 * inline by intent, and a blanket rule on .h2_span would stack them.
 * ------------------------------------------------------------------------- */
.hflex_inner .bb-h2-line2 {
	display: block;
}

.vflex_inner .bb-h2-line2,
.title_inner .bb-h2-line2 {
	display: inline;
}

/*
 * The two lines now have a real space between them in the markup, which they
 * did not before - as separate elements they were held apart by margin-left
 * (10px) or padding-left (15px) instead, and a crawler reading the rendered
 * text got "FrequentlyAsked Questions" with the words run together. That was
 * the whole reason for merging them, so the space has to be real rather than
 * implied by a gap.
 *
 * With the space doing that job, the stand-in gap would double it, so it is
 * removed here. Measured on /location/toronto at 1440px: 10px of margin
 * becomes a 9.6px word space, and 15px of padding becomes 7.5px - the first
 * is indistinguishable, the second is half a word space tighter and reads as
 * ordinary spacing rather than a designed gap.
 */
.vflex_inner .bb-h2-line2 {
	margin-left: 0;
}

.title_inner .bb-h2-line2 {
	padding-left: 0;
}

@media screen and (max-width: 767px) {
	.vflex_inner .bb-h2-line2,
	.title_inner .bb-h2-line2 {
		display: block;
	}
}

/* ---------------------------------------------------------------------------
 * Service hero: the rhetorical question, demoted out of the h1.
 *
 * service.php now puts the `headline` field in the h1 - the line that actually
 * names the service - and renders `card_heading`, the all-caps question that
 * used to be the h1, as the first line of the copy beneath it.
 *
 * It keeps .portfolio-teaser-subtitle so it matches the description that
 * follows; this only separates the two so the question reads as a lead-in
 * rather than a first paragraph that happens to be shouting.
 * ------------------------------------------------------------------------- */
.bb-service-question {
	letter-spacing: .4px;
	margin-bottom: 14px;
	font-weight: 600;
}

/* ---------------------------------------------------------------------------
 * Large screens: images and icons sized only by HTML attributes.
 *
 * Above 1440px, large-screens.css scales every pixel value in these
 * stylesheets with the window (see webflow/tools/scale_large_screens.py). An
 * element whose size comes from its width/height attributes has no pixel value
 * to scale, so it stayed at its 1440 size while everything around it grew: the
 * navbar logo, the featured-in logos, the hero's scroll arrow, the About award
 * badges and the inline SVG icons.
 *
 * Each rule restates the size the attribute already gives, so nothing moves at
 * 1441px; the generator turns these pixels into scaled values like the rest.
 * Selectors are keyed on the attribute value, because the same class carries
 * several sizes (the featured-in logos are 150, 120 and 80 wide). Measured on
 * 10 Oct: every element listed here rendered at exactly its attribute size at
 * both 1440 and 2560, and none had a CSS width of its own.
 * ------------------------------------------------------------------------- */
@media screen and (min-width: 1441px) {
	.bb-nav__logo,
	.bounce_icon { width: 50px; height: auto; }
	.logos-row .logo[width="150"] { width: 150px; height: auto; }
	.logos-row .logo[width="120"] { width: 120px; height: auto; }
	.logos-row .logo[width="80"] { width: 80px; height: auto; }
	.left_blur,
	.right_blur { width: 424px; height: auto; }
	.about_award-img-wrap .award-logo[width="350"] { width: 350px; height: auto; }
	/* ThreeBestRated's badge embed sets width:350px inline, so only !important reaches it. */
	.w-embed img[width="350"] { width: 350px !important; height: auto; }
	.about_award-img-wrap .award-logo_no-bg { width: 448px; height: auto; }
	.about_award_wrap img[width="150"] { width: 150px; height: auto; }
	.w-embed > svg[width="20"] { width: 20px; height: auto; }
	.w-embed > svg[width="21"] { width: 21px; height: auto; }
	.w-embed > svg[width="22"] { width: 22px; height: auto; }
	.w-embed > svg[width="24"],
	.w-embed > svg[width="24px"] { width: 24px; height: auto; }
	.w-embed > svg[width="32"] { width: 32px; height: auto; }
	.w-embed > svg[width="142"] { width: 142px; height: auto; }
}
