/*
 * Glacial Blocks — shared block CSS.
 * Loaded on the front end and inside the editor iframe (see glacial-blocks.php).
 * Webflow classes are styled by css/webflow.css; only block-specific utilities
 * and ported Webflow interactions live here.
 */

/*
 * Editor canvas content column (.editor-styles-wrapper never matches the
 * front end). theme.json declares no layout.contentSize, so the canvas root
 * is unconstrained; mirror the front end instead: root-level content blocks
 * sit in a .wrap-equivalent column (90% / 1600px — webflow.css .wrap), while
 * glacial/* section blocks keep the full canvas width their full-width
 * templates give them (they carry their own .wrap inside).
 */
.editor-styles-wrapper .is-root-container > .wp-block:not([data-type^="glacial/"]):not(.alignfull):not(.alignwide),
.editor-styles-wrapper .is-root-container > .block-list-appender {
	max-width: min(90%, 1600px);
	margin-left: auto;
	margin-right: auto;
}

.editor-styles-wrapper .editor-visual-editor__post-title-wrapper,
.editor-styles-wrapper .edit-post-visual-editor__post-title-wrapper {
	max-width: min(90%, 1600px);
	margin-left: auto;
	margin-right: auto;
}

/*
 * Text alignment for glacial/heading (attribute `align`). Kept separate from the
 * colour variants: Webflow's .h2-center bakes navy + centred into one class, so
 * it can never combine with .h2-white / .h4-gold. These carry alignment only.
 * `left` is offered explicitly so a heading can opt out of a centred ancestor.
 */
.gl-text-left { text-align: left; }
.gl-text-center { text-align: center; }
.gl-text-right { text-align: right; }

/*
 * Long unbreakable strings — nearly always a URL pasted in as its own link
 * text — carry no break opportunity, so instead of wrapping they push past
 * their container. It shows up worst in the fixed-width cards: .gl-timeline-item
 * is width: calc(50% - 2.5rem) and cannot grow, so the text simply spills out
 * of the cream box.
 *
 * overflow-wrap is an inherited property, so declaring it on the container
 * covers its paragraphs, list items and anchors without selecting each one.
 * `anywhere` additionally shrinks the element's min-content width, which is what
 * stops a long URL blowing out a grid or flex track; `break-word` is declared
 * first as the fallback for Safari < 15.4, which doesn't know `anywhere`.
 */
.gl-list,
.gl-timeline-item,
.gl-grid,
.gl-faq,
.gl-page-intro {
	overflow-wrap: break-word;
	overflow-wrap: anywhere;
}

/* glacial/grid — generic column layout */
.gl-grid {
	display: grid;
	gap: 2rem;
}

.gl-grid.gl-cols-2 {
	grid-template-columns: repeat(2, 1fr);
}

/*
 * Three columns where the container can hold them, two where it can't —
 * WITHOUT breaking the equal-height row (every cell still stretches to the
 * tallest, which is what gives the cards their block of colour).
 *
 * The problem this solves is container width, not viewport width, so a media
 * query can't see it: an inner page with the Specialties sidebar gives the grid
 * ~800px, so three columns are only ~246px wide, and a cell with four
 * paragraphs towers over one with two. On /dermatology/acne/ that left 1276px
 * of empty navy across the row; at two columns it is 251px, with no cell
 * shorter than its own copy.
 *
 * `max(280px, (100% - 4rem) / 3)` is what caps the count at three: when the
 * container is wide enough, the track floor IS a third of it, so exactly three
 * fit; when it is narrower than 3x280px, the floor is 280px and only two fit.
 * Without the max() half, auto-fit would happily lay out FOUR columns on a
 * full-bleed page (measured — /cosmetics/hair-restoration/ did exactly that).
 * The 4rem is the two 2rem gaps between three tracks.
 *
 * The 991px / 767px rules below still apply and still win, being later.
 */
.gl-grid.gl-cols-3 {
	grid-template-columns: repeat(auto-fit, minmax(max(280px, (100% - 4rem) / 3), 1fr));
}

.gl-grid.gl-cols-4 {
	grid-template-columns: repeat(4, 1fr);
}

/* glacial/grid — "Last cell full width" option (gl-last-full). The final cell
 * spans every column, so Columns 2 + three cells = two columns with one
 * full-width column underneath. Holds at the 991 breakpoint (3/4 collapse to
 * 2 columns) and is moot at 767, where the grid is a single column. */
.gl-grid.gl-last-full > :last-child {
	grid-column: 1 / -1;
}

/* Editor: the inserter appender is the real last child, so span the cell that
 * precedes it (and the appender itself, so it doesn't sit in a stray column). */
.editor-styles-wrapper .gl-grid.gl-last-full > :has(+ .block-list-appender) {
	grid-column: 1 / -1;
}

@media screen and (max-width: 991px) {
	.gl-grid.gl-cols-3,
	.gl-grid.gl-cols-4 {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media screen and (max-width: 767px) {
	.gl-grid.gl-cols-2,
	.gl-grid.gl-cols-3,
	.gl-grid.gl-cols-4 {
		grid-template-columns: 1fr;
	}
}

/* glacial/grid — a fixed-width <iframe> must not set the column floor.
 *
 * An `<iframe width="504">` (LinkedIn's compact post embed, and any other
 * paste-in embed that ships width/height attributes) is a REPLACED element:
 * that attribute becomes a definite width, so the cell's min-content
 * contribution is 504px + the cell's 3rem padding. `1fr` is shorthand for
 * `minmax(auto, 1fr)`, and `auto` as a track MINIMUM resolves to exactly that
 * contribution — so a two-column grid of LinkedIn embeds demanded ~1136px and
 * could not shrink.
 *
 * ⚠ The symptom is not a scrollbar on the grid. `.main-content` is `flex: 1`
 * inside `.outer-flex-wrapper`, which `style.css` declares `flex-wrap: wrap`,
 * and a flex item's own `min-width: auto` floors it at its content's
 * min-content size — so the content column refused to go below ~1136px and the
 * Specialties `<aside>` wrapped to the BOTTOM of the page instead.
 * (/partnership-opportunities/, 2026-09-15.)
 *
 * `min-width: 0` on the cell lets the track shrink past that floor;
 * `max-width: 100%` is what then lets the iframe follow it down — one without
 * the other does nothing. `gl-cols-3` is unaffected either way: its track
 * minimum is an explicit `max(280px, …)`, never `auto`.
 *
 * ⚠ The `margin-inline: auto` rule is scoped to a DIRECT child of the cell.
 * The Wistia embeds on /hair-restoration/ and Paul Rose's page sit inside a
 * `.gsd-wistia` padding-ratio box as `position: absolute; inset: 0` — they are
 * grandchildren, so they keep their own sizing untouched. The width attribute
 * still caps these at 504px, so centring is what keeps them off the left edge
 * of a cell wider than that.
 */
.gl-grid > * {
	min-width: 0;
}

.gl-grid iframe {
	max-width: 100%;
}

.gl-grid > * > iframe {
	display: block;
	margin-inline: auto;
}

/* glacial/grid — "Cell background" option (gl-cellbg-*). Every direct child
 * (typically a glacial/grid-cell) is a card; the option only swaps its color,
 * and the default — no gl-cellbg-* class at all — is WHITE. Colors are the
 * theme.json brand palette. Teal/navy count as dark: their cell text flips
 * white — headings and links carry their own colors in webflow.css, so they
 * need the explicit override on top of the inherited color. Square corners by
 * owner call (2026-08-12) — no radius on the cells. */
.gl-grid {
	margin-bottom: 2rem;
}

.gl-grid > * {
	padding: 1.5rem;
	background-color: #fff;
}

.gl-grid > * > :first-child {
	margin-top: 0;
}

.gl-grid > * > :last-child {
	margin-bottom: 0;
}

.gl-grid.gl-cellbg-cream > * { background-color: #fcf5e9; } /* lum-cream */
.gl-grid.gl-cellbg-sage > * { background-color: #a5b092; }  /* lum-sage */
.gl-grid.gl-cellbg-teal > * { background-color: #4b7881; }  /* lum-teal */
.gl-grid.gl-cellbg-navy > * { background-color: #001543; }  /* gsd-navy */

.gl-grid.gl-cellbg-teal > *,
.gl-grid.gl-cellbg-navy > * {
	color: #fff;
}

.gl-grid.gl-cellbg-teal > * :is(h1, h2, h3, h4, h5, h6, a),
.gl-grid.gl-cellbg-navy > * :is(h1, h2, h3, h4, h5, h6, a) {
	color: #fff;
}

/* A core button in a dark cell: the site button is a NAVY outline, which
 * vanishes on the navy cell. Gold outline + white label, hover fills gold with
 * a navy label (white on gold is ~2.4:1) — the split-content dark band's set.
 * First used by the Morgan Hill Grand Opening event's RSVP card. */
.gl-grid:is(.gl-cellbg-teal, .gl-cellbg-navy) > * .wp-block-buttons a.wp-block-button__link {
	border-color: var(--color-6, #d29f13);
	background-color: transparent;
	color: #fff;
}

.gl-grid:is(.gl-cellbg-teal, .gl-cellbg-navy) > * .wp-block-buttons a.wp-block-button__link:hover {
	background-color: var(--color-6, #d29f13);
	color: var(--color-2, #001543);
}

/* Editor: the inserter appender is also a direct grid child — keep it plain. */
.editor-styles-wrapper .gl-grid > .block-list-appender {
	padding: 0;
	background: none;
	color: inherit;
}

/* glacial/grid — "Number the cells" option (gl-grid--numbered). The numeral is
 * SEQUENCING, not content: a CSS counter fills a ::before on each cell, so
 * reordering or inserting cells renumbers the set and nothing has to be typed
 * into the copy. Mirrors the homepage service stack's .title-number (trajan,
 * 2em, line-height 1) so the two read as the same device.
 * ⚠ Excludes .block-list-appender — in the editor that is also a direct grid
 * child, and without the guard it would take a number of its own AND leave the
 * count one ahead of what the front end prints.
 * Color: navy by default (it sits on the white/cream/sage cells); the dark
 * cells flip it to brand gold, which is 7.4:1 on navy. Gold is deliberately NOT
 * the default — on white it is 2.4:1 and would fail SC 1.4.3. */
.gl-grid--numbered {
	counter-reset: gl-grid-cell;
}

.gl-grid--numbered > *:not(.block-list-appender)::before {
	counter-increment: gl-grid-cell;
	content: counter(gl-grid-cell, decimal-leading-zero);
	display: block;
	margin-bottom: 0.75rem;
	font-family: trajan-sans-pro, sans-serif;
	font-size: 2em;
	font-weight: 400;
	line-height: 1em;
	color: var(--color-2, #001543);
}

.gl-grid--numbered.gl-cellbg-teal > *::before,
.gl-grid--numbered.gl-cellbg-navy > *::before {
	color: var(--color-6, #d29f13);
}

/* glacial/location-specialties — accordion behavior (Webflow IX ported) */
.glacial-specialties .faq2_question-2 {
	cursor: pointer;
}

.glacial-specialties .faq2_answer {
	height: auto;
	max-height: 0;
	overflow: hidden;
	transition: max-height 0.35s ease;
}

.glacial-specialties .faq2_accordion.open .faq2_answer {
	max-height: 1200px;
}

.glacial-specialties .faq2_icon-2 {
	transition: transform 0.35s ease;
}

.glacial-specialties .faq2_accordion.open .faq2_icon-2 {
	transform: rotate(180deg);
}

/* glacial/location-specialties — cap the content column.
   The block is full-bleed (its navy band spans the viewport) and its two inner
   columns come from webflow.css: `.wrap` is 90% / max 1600px and
   `.section_faq2-2` is a bare 90% with NO cap — so at 1440px the heading, intro
   and accordion all ran 1296px wide, and past ~1778px the accordion overshot
   even the heading (1728px vs 1600px at 1920px). Both columns now share one
   cap, centred in the band (their auto margins), so they stay aligned; below
   ~1223px the 90% is already narrower and nothing changes. Child combinators
   keep the cap off any `.wrap` a block nested in the intro might carry. Tune
   with --gl-specialties-max. */
.wp-block-glacial-location-specialties {
	--gl-specialties-max: 1100px;
}

.wp-block-glacial-location-specialties > .main-service-section > .wrap,
.wp-block-glacial-location-specialties > .main-service-section > .section_faq2-2 {
	max-width: var(--gl-specialties-max);
}

/* Service pills keep the same margin on every side, the last one included.
   style.css:27 zeroes margin-bottom on the last child of ANYTHING inside
   .main-service-section — (0,2,1), which beats webflow.css's
   `.service-link-block { margin: 2.5px }` (0,1,0) — so the final pill in a
   `.service-link-holder` lost its bottom margin and the row's
   `align-items: center` dropped it 1.25px below its neighbours (every office's
   accordion; spotted on Sparks' "Warts", 2026-10-12). Scoped to this block, the
   only place the pills are used; (0,4,0) restores it. */
.wp-block-glacial-location-specialties .service-link-holder > .service-link-block.rev {
	margin: 2.5px;
}

/* glacial/location-insurances — optional SEO subtext under a carrier name */
.insurance .insurance-subtext {
	font-size: 0.8em;
	opacity: 0.75;
}

/* glacial/location-testimonials + glacial/testimonial-card — close the gap a
   short review leaves above its attribution.

   The cards sit in a flex row that stretches them all to the tallest quote,
   and webflow.css:2246 parks each card at `justify-content: space-between` —
   so the gold "-Name" is pinned to the card floor no matter how short the
   review is. Alamo's three reviews run 171 / 464 / 705 characters and the two
   short ones showed a yawning hole; a dozen offices carry a spread that wide
   (Rossmoor 515, Pleasanton 413, Folsom 386, Walnut Creek Mohs 383 …).

   Centring the quote+name pair keeps the equal-height band the design wants
   while the leftover height reads as padding rather than a hole. The quote
   icon is absolutely positioned, so it is out of flow and unaffected. */
.testimonial-div-ip {
	justify-content: center;
}

/* Editor-only niceties for dynamic-block placeholders */
.glacial-block-placeholder {
	padding: 24px;
	border: 1px dashed #949494;
	background: #f0f0f0;
	color: #1e1e1e;
	font-size: 13px;
	text-align: center;
}

/* ---------------------------------------------------------------------------
 * Block option flags (Kadence-pattern; breakpoints = Webflow's 991/767).
 * Classes are emitted only when a toggle is on, so existing content is
 * unaffected. Editor keeps hidden blocks editable, dimmed.
 * ------------------------------------------------------------------------- */
@media (min-width: 992px) { .gl-hide-desktop { display: none !important; } }
@media (min-width: 768px) and (max-width: 991px) { .gl-hide-tablet { display: none !important; } }
@media (max-width: 767px) { .gl-hide-mobile { display: none !important; } }
.editor-styles-wrapper .gl-hide-desktop,
.editor-styles-wrapper .gl-hide-tablet,
.editor-styles-wrapper .gl-hide-mobile { display: revert !important; opacity: 0.55; }

/* Column-order swap on the two-column luminous sections. The flag sits on the
 * block root; each rule targets that block's real flex container. 992px is the
 * design's own collapse point (columns go 100%/flex-flow column at 991). */
@media (min-width: 992px) {
	.gl-swap-desktop.ip-luminous-hero,
	.gl-swap-desktop.ip-1-service,
	.gl-swap-desktop.cta .inner-cta-div,
	.gl-swap-desktop.stat-section > .wrap.flex,
	.gl-swap-desktop.gl-page-intro > .wrap.flex,
	.gl-swap-desktop.new-hero-2,
	.gl-swap-desktop.luminous-text-section > .wrap.flex { flex-direction: row-reverse; }
}
@media (max-width: 991px) {
	.gl-swap-mobile.ip-luminous-hero,
	.gl-swap-mobile.ip-1-service,
	.gl-swap-mobile.cta .inner-cta-div,
	.gl-swap-mobile.stat-section > .wrap.flex,
	.gl-swap-mobile.gl-page-intro > .wrap.flex,
	.gl-swap-mobile.new-hero-2,
	.gl-swap-mobile.luminous-text-section > .wrap.flex { flex-direction: column-reverse; }
}

/* ---------------------------------------------------------------------------
 * glacial/split-content — optional background band (`background` attribute).
 * Empty emits no class, so every block saved before the option is untouched.
 *
 * Light bands keep the section's own type: the teal .h2-lum is >= 4.0:1 and
 * the #333 body copy >= 10.5:1 on all three. Full sage (#a5b092) is NOT offered
 * — the teal heading drops to 2.1:1 on it.
 *
 * Padding: .stat-section's own 5% runs 19px on a phone, too tight for a band,
 * hence the clamp. It deliberately also beats .stat-section.less-mob's
 * `padding-bottom: 0` at <=991px (same 0,2,0; this file prints later) — on a
 * band that would end the colour flush against the last line.
 * ------------------------------------------------------------------------- */
.stat-section:is(.gl-bg-cream, .gl-bg-tint, .gl-bg-sage, .gl-bg-navy, .gl-bg-slate) {
	padding-top: clamp(40px, 5vw, 72px);
	padding-bottom: clamp(40px, 5vw, 72px);
}
.stat-section.gl-bg-cream { background-color: var(--_luminous---color-4); } /* #fcf5e9 */
.stat-section.gl-bg-tint  { background-color: #e6eaf1; } /* 10% --color-10 on white */
.stat-section.gl-bg-sage  { background-color: #e8ebe4; } /* 25% lum sage on white */
.stat-section.gl-bg-navy  { background-color: var(--color-2); } /* #001543 */
.stat-section.gl-bg-slate { background-color: var(--_luminous---color-5); } /* #2e3e4a */

/* .emph-div.lum IS cream, so on a cream band the box would vanish — lift it
 * to white there. */
.stat-section.gl-bg-cream .emph-div.lum {
	background-image: linear-gradient(to bottom, var(--color), var(--color));
}

/* Dark bands: the light text set. Heading gold (Luminous #e1a300: 7.9:1 navy,
 * 5.0:1 slate — large text), copy and links white (17.7 / 11.0).
 * ⚠ Scoped to the text column's DIRECT children so a glacial/emphasis box,
 * which keeps its own light fill, keeps its dark text.
 * ⚠ Element-qualified: `.entry a` (style.css) and `.button.lum:hover` would
 * otherwise win. */
.stat-section.gl-bg-dark .txt-div-48 > h2.h2-lum {
	color: var(--_luminous---color);
}
.stat-section.gl-bg-dark .txt-div-48 > :is(p, ul, ol, h3, h4, h5, h6) {
	color: var(--color);
}
.stat-section.gl-bg-dark .txt-div-48 > :is(p, ul, ol, h3, h4, h5, h6) a:not(.button):not(.wp-block-button__link) {
	color: var(--color);
	text-decoration: underline;
}
/* Buttons (a raw .button from core/html, or core/buttons): gold outline, white
 * label. Hover fills gold and turns the label NAVY — white on the gold is
 * ~2.4:1 and fails 1.4.3; navy is ~7.3:1. */
.stat-section.gl-bg-dark .txt-div-48 > a.button,
.stat-section.gl-bg-dark .txt-div-48 > .btn-div a.button,
.stat-section.gl-bg-dark .txt-div-48 > .wp-block-buttons a.wp-block-button__link {
	border-color: var(--color-6);
	background-color: transparent;
	color: var(--color);
}
.stat-section.gl-bg-dark .txt-div-48 > a.button:hover,
.stat-section.gl-bg-dark .txt-div-48 > .btn-div a.button:hover,
.stat-section.gl-bg-dark .txt-div-48 > .wp-block-buttons a.wp-block-button__link:hover {
	background-color: var(--color-6);
	color: var(--color-2);
}

/* glacial/faq — native details/summary accordion (no JS) */
.gl-faq details { border-bottom: 1px solid rgba(0, 0, 0, 0.12); }
.gl-faq summary { cursor: pointer; padding: 1em 2.2em 1em 0; font-weight: 600; list-style: none; position: relative; }
.gl-faq summary::-webkit-details-marker { display: none; }
.gl-faq summary::after { content: "+"; position: absolute; right: 0.4em; top: 50%; transform: translateY(-50%); font-size: 1.4em; line-height: 1; }
.gl-faq details[open] > summary::after { content: "\2212"; }
.gl-faq .gl-faq-answer { padding: 0 0 1.2em; }

/* glacial/slider — scroll-snap image strip with prev/next arrows (view.js).
 * ~2.5 slides visible desktop, 1.5 tablet, 1 mobile; arrows ship [hidden] and
 * only appear when JS finds overflow, so no-JS keeps a clean swipe strip. */
.gl-slider {
	position: relative;
	margin-bottom: 30px;
}

.gl-slider .gl-slider-track {
	display: flex;
	gap: 1rem;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
}

.gl-slider .gl-slider-slide {
	flex: 0 0 calc((100% - 2rem) / 2.5);
	margin: 0;
	scroll-snap-align: start;
}

.gl-slider .gl-slider-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.gl-slider .gl-slider-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: #001543; /* gsd-navy */
	color: #fff;
	cursor: pointer;
}

.gl-slider .gl-slider-prev { left: -10px; }
.gl-slider .gl-slider-next { right: -10px; }

.gl-slider .gl-slider-arrow:disabled {
	opacity: 0.35;
	cursor: default;
}

.gl-slider .gl-slider-arrow:focus-visible {
	outline: 2px solid #001543;
	outline-offset: 2px;
}

/* Lightbox thumbnails: the <a> wrapper must not disturb the track/grid
 * layout, and reads as zoomable. */
.gl-slider--lightbox .gl-slider-zoom {
	display: block;
	line-height: 0;
	cursor: zoom-in;
	height: 100%;
}

.gl-slider--lightbox .gl-slider-zoom:focus-visible {
	outline: 2px solid var(--color-6, #d29f13);
	outline-offset: 3px;
}

/* The lightbox dialog itself. Base .modal/.modal__overlay/.micromodal-slide
 * animation CSS lives in the theme's style.css (shared with the search
 * modal); these rules only widen the container for imagery and lay out the
 * stage + pager. */
.gl-lightbox .gl-lightbox__container {
	max-width: min(1400px, 94vw);
	padding: 44px 20px 20px;
	background: #fff;
}

.gl-lightbox .gl-lightbox__stage {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 40vh;
}

.gl-lightbox .gl-lightbox-slide {
	margin: 0;
}

.gl-lightbox .gl-lightbox-img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 74vh;
	margin: 0 auto;
	object-fit: contain;
}

.gl-lightbox .gl-lightbox__nav {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1.5rem;
	margin-top: 1rem;
}

.gl-lightbox .gl-lightbox-arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: #001543; /* gsd-navy */
	color: #fff;
	cursor: pointer;
}

.gl-lightbox .gl-lightbox-arrow:focus-visible {
	outline: 2px solid var(--color-6, #d29f13);
	outline-offset: 2px;
}

.gl-lightbox .gl-lightbox-counter {
	margin: 0;
	min-width: 5em;
	text-align: center;
	font-size: 0.9em;
}

.gl-slider--empty {
	padding: 32px 16px;
	border: 1px dashed #949494;
	text-align: center;
	color: #757575;
}

/* "Grid" layout (gl-gallery-grid + gl-gallery-cols-N): same track markup,
 * laid out as a column grid — no arrows, no scrolling. Collapses like the
 * glacial/grid block: 3/4 cols -> 2 at 991, everything -> 1 at 767. */
.gl-slider.gl-gallery-grid .gl-slider-track {
	display: grid;
	overflow: visible;
	scroll-snap-type: none;
}

.gl-slider.gl-gallery-grid .gl-slider-slide {
	flex-basis: auto;
}

.gl-slider.gl-gallery-cols-2 .gl-slider-track { grid-template-columns: repeat(2, 1fr); }
.gl-slider.gl-gallery-cols-3 .gl-slider-track { grid-template-columns: repeat(3, 1fr); }
.gl-slider.gl-gallery-cols-4 .gl-slider-track { grid-template-columns: repeat(4, 1fr); }

@media screen and (max-width: 991px) {
	.gl-slider.gl-gallery-cols-3 .gl-slider-track,
	.gl-slider.gl-gallery-cols-4 .gl-slider-track {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media screen and (max-width: 767px) {
	.gl-slider.gl-gallery-grid .gl-slider-track {
		grid-template-columns: 1fr;
	}
}

/* "Auto" gallery (gl-gallery-auto + gl-gallery-cols-N, render.php): a
 * slider-layout gallery holding only TWO or THREE images. There is nothing to
 * page through on a wide screen and the 2.5-across track leaves dead space, so
 * from 768px up it lays out as a column grid — reusing the gl-gallery-cols-N
 * track rules above — and below 768 it falls back to the scroll-snap slider
 * the base rules already give it.
 * It does NOT take those rules' 3 -> 2 collapse at 991, unlike an explicit
 * grid: with exactly three images that strands an orphan on its own row, and
 * in a before/after gallery the orphan reads as a missing pair. Three across
 * at 768px is ~235px a column, the same as a 3-col grid inside the
 * Specialties sidebar, so nothing is cramped by holding the count.
 * The arrows ship in the markup for the mobile case; view.js reveals them only
 * when the track overflows, and display:none here means a mis-measure can
 * never float a dead arrow over the grid. */
@media screen and (min-width: 768px) {
	.gl-slider.gl-gallery-auto .gl-slider-track {
		display: grid;
		overflow: visible;
		scroll-snap-type: none;
	}

	/* (0,4,0) — beats the 991 collapse above on specificity as well as order. */
	.gl-slider.gl-gallery-auto.gl-gallery-cols-2 .gl-slider-track { grid-template-columns: repeat(2, 1fr); }
	.gl-slider.gl-gallery-auto.gl-gallery-cols-3 .gl-slider-track { grid-template-columns: repeat(3, 1fr); }

	.gl-slider.gl-gallery-auto .gl-slider-slide {
		flex-basis: auto;
	}

	.gl-slider.gl-gallery-auto .gl-slider-arrow {
		display: none;
	}
}

@media screen and (max-width: 991px) {
	.gl-slider .gl-slider-slide {
		flex-basis: calc((100% - 1rem) / 1.5);
	}
}

@media screen and (max-width: 767px) {
	.gl-slider .gl-slider-slide {
		flex-basis: 100%;
	}
}

/* .gl-button-grid — "Additional CSS class" for a core/buttons block: equal-
 * width button cells in a grid, each button filling its cell. Four across to
 * match the live /online-appointments/ model (Elementor col-25 +
 * align-justify), stepping down on narrower screens. Doubled class beats
 * core's :where() flex-layout rules regardless of print order. */
.wp-block-buttons.gl-button-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1rem;
}
/* Both elements: the region finder upgrades this grid's region links to real
 * <button>s, and an anchor-only rule left those one step smaller. */
.wp-block-buttons.gl-button-grid a,
.wp-block-buttons.gl-button-grid button {
	font-size: 1.1rem;
}

/* gl-button-grid--3: three across at full width, for a set of exactly three
 * (/providers/' provider-type buttons, 2026-10-08) so a fourth cell isn't left
 * empty. Scoped to >1080px so the base grid's narrower steps still apply. */
@media (min-width: 1081px) {
	.wp-block-buttons.gl-button-grid.gl-button-grid--3 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 1080px) {
	.wp-block-buttons.gl-button-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 800px) {
	.wp-block-buttons.gl-button-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 540px) {
	.wp-block-buttons.gl-button-grid { grid-template-columns: 1fr; }
}

.wp-block-buttons.gl-button-grid .wp-block-button {
	width: 100%;
	margin: 0;
	height: 100%;
}

.wp-block-buttons.gl-button-grid .wp-block-button__link {
	display: block;
	width: 100%;
	text-align: center;
}

/* glacial/instagram — Instagram's own embed styles itself; we only constrain
 * the width (--gl-ig-max, set per block) and optionally center it. The editor
 * preview swaps the blockquote for an iframe, so both are covered. */
.gl-instagram {
	margin: 0 0 1.5rem;
}

.gl-instagram--center {
	display: flex;
	justify-content: center;
}

/* Several embeds side by side. Grid wins over the flex centering above (both
 * set `display`, this comes later), and each cell caps at --gl-ig-max. */
.gl-instagram--grid {
	display: grid;
	gap: 1.5rem;
	justify-content: center;
	justify-items: center;
}

.gl-instagram-cols-2 { grid-template-columns: repeat(2, minmax(0, var(--gl-ig-max, 540px))); }
.gl-instagram-cols-3 { grid-template-columns: repeat(3, minmax(0, var(--gl-ig-max, 540px))); }

@media screen and (max-width: 991px) {
	.gl-instagram-cols-3 { grid-template-columns: repeat(2, minmax(0, var(--gl-ig-max, 540px))); }
}

@media screen and (max-width: 767px) {
	.gl-instagram-cols-2,
	.gl-instagram-cols-3 { grid-template-columns: minmax(0, var(--gl-ig-max, 540px)); }
}

.gl-instagram .instagram-media,
.gl-instagram .gl-instagram-frame {
	max-width: var(--gl-ig-max, 540px) !important;
	width: 100% !important;
	min-width: 0 !important;
	margin: 0 !important;
}

.gl-instagram .gl-instagram-frame {
	display: block;
	background: #fff;
	border: 1px solid #dbdbdb;
	border-radius: 3px;
}

/* Spotlight Instagram feed ([gsd_instagram] / the homepage band) — portrait tiles (2026-10-01).
 * Spotlight squares every grid cell with `padding-bottom: 100%` and lays the photo over it at
 * `object-fit: cover`, so a 4:5 post lost its top and bottom. Its thumbnails keep their real
 * shape (600×741 for a post, 600×1067 for a Reel), so a 4:5 cell shows a post whole and gives a
 * Reel a centred 4:5 crop, as Instagram's own grid does. The cell content is absolutely
 * positioned at inset 0 (`layout__fill-parent`), so it follows the cell's new height.
 * The loading placeholders get the same shape so the band does not jump when the images arrive.
 * (0,2,0) beats Spotlight's (0,1,0) whatever the load order; change --gsd-insta-ratio to retune. */
.spotlight-instagram-feed {
	--gsd-insta-ratio: 4 / 5;
}

.spotlight-instagram-feed .FeedGridLayout__cell,
.spotlight-instagram-feed .FeedLayout__fake-media {
	padding-bottom: 0;
	aspect-ratio: var(--gsd-insta-ratio);
}

/* glacial/list — brand list. The arrow marker is the theme's circled-arrow
 * SVG used as a MASK, so its color is ours (navy to match the asset; change
 * the background-color below to var(--color-6) for gold). Referencing the
 * file from this stylesheet keeps the theme URL out of saved content.
 * Columns use CSS multi-column so items flow top-down then wrap. */
.gl-list {
	margin: 0 0 1.5rem;
	padding: 0;
	list-style: none;
}

.gl-list li {
	position: relative;
	margin: 0 0 0.5rem;
	padding-left: 1.75rem;
	break-inside: avoid; /* keep an item from splitting across columns */
	font-weight: 500;
}

.gl-list--arrow li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.15em;
	width: 1.1em;
	height: 1.1em;
	background-color: var(--color-2, #001543);
	-webkit-mask: url("../../images/locations/icons8-right-arrow_2.svg") no-repeat center / contain;
	mask: url("../../images/locations/icons8-right-arrow_2.svg") no-repeat center / contain;
}

/* Plain-bullet variant and ordered lists keep native markers, indented to
 * match the arrow rhythm. */
.gl-list:not(.gl-list--arrow) {
	padding-left: 1.35rem;
	list-style: disc;
}

ol.gl-list {
	list-style: decimal;
}

.gl-list:not(.gl-list--arrow) li {
	padding-left: 0.35rem;
}

.gl-list-cols-2 { columns: 2; column-gap: 2.5rem; }
.gl-list-cols-3 { columns: 3; column-gap: 2.5rem; }
.gl-list-cols-4 { columns: 4; column-gap: 2rem; }

@media screen and (max-width: 991px) {
	.gl-list-cols-3,
	.gl-list-cols-4 { columns: 2; }
}

@media screen and (max-width: 767px) {
	.gl-list-cols-2,
	.gl-list-cols-3,
	.gl-list-cols-4 { columns: 1; }
}

/* glacial/timeline — vertical timeline: gold center rail (brand --color-6),
 * cream cards alternating sides via nth-child; single left rail + stacked
 * cards under 768. Square corners per the site's card convention. */
.gl-timeline {
	position: relative;
	max-width: 1100px;
	margin: 0 auto;
	padding: 1rem 0;
}

.gl-timeline::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: 2px;
	margin-left: -1px;
	background: var(--color-6, #d29f13);
}

/* The item IS the cream card (single wrapper, step-card save shape). */
.gl-timeline-item {
	position: relative;
	width: calc(50% - 2.5rem);
	margin: 0 0 2.5rem;
	padding: 2rem;
	background: #fcf5e9; /* lum-cream */
}

.gl-timeline-item:nth-child(even) {
	margin-left: calc(50% + 2.5rem);
}

.gl-timeline-item:last-child {
	margin-bottom: 0.5rem;
}

/* rail dot */
.gl-timeline-item::before {
	content: "";
	position: absolute;
	top: 2rem;
	right: calc(-2.5rem - 11px);
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: #fff;
	border: 3px solid var(--color-6, #d29f13);
	z-index: 1;
}

.gl-timeline-item:nth-child(even)::before {
	right: auto;
	left: calc(-2.5rem - 11px);

}

.gl-timeline-item > :last-child,
.gl-timeline-item > div > :last-child {
	margin-bottom: 0;
}

.gl-timeline-title {
	margin-top: 0;
	color: #001543; /* gsd-navy */
}

@media screen and (max-width: 767px) {
	.gl-timeline::before {
		left: 8px;
	}

	.gl-timeline-item,
	.gl-timeline-item:nth-child(even) {
		width: auto;
		margin: 0 0 2rem 2.2rem;
	}

	.gl-timeline-item::before,
	.gl-timeline-item:nth-child(even)::before {
		right: auto;
		left: calc(-2.2rem - 1px);
	}
}

/* glacial/timeline — "Single column (left rail)" layout (gl-timeline-stack).
 * The same shape the alternating layout already collapses to under 768px, held
 * at every width: rail hard left, one full-width column, dots down the left.
 *
 * Asked for on the 2026-09-14 edit sheet for /appointment-information/ ("we
 * did not like the alternating boxes layout") — alternating leaves half of
 * every row empty, which is the same dead space flagged elsewhere on that
 * sheet. Scoped to the class, so every other timeline keeps the center rail.
 *
 * Declared BEFORE the 767px block below so the mobile rules still win there
 * (they are identical anyway; this only matters if the two ever diverge). */
.gl-timeline.gl-timeline-stack::before {
	left: 8px;
}

.gl-timeline.gl-timeline-stack > .gl-timeline-item,
.gl-timeline.gl-timeline-stack > .gl-timeline-item:nth-child(even) {
	width: auto;
	margin: 0 0 2.5rem 2.75rem;
}

.gl-timeline.gl-timeline-stack > .gl-timeline-item:last-child {
	margin-bottom: 0.5rem;
}

.gl-timeline.gl-timeline-stack > .gl-timeline-item::before,
.gl-timeline.gl-timeline-stack > .gl-timeline-item:nth-child(even)::before {
	right: auto;
	left: calc(-2.75rem - 1px);
}

/* Editor: the appender is a direct child of .gl-timeline — center it clear
 * of the rail so it doesn't read as a mispositioned card. */
.editor-styles-wrapper .gl-timeline > .block-list-appender {
	position: relative;
	width: 100%;
	text-align: center;
	padding: 0.5rem 0;
	background: #fff;
}

/* glacial/latest-posts — SSR card grid */
.gl-posts-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2em; }
.gl-posts-grid .gl-post-card { display: block; text-decoration: none; }
.gl-posts-grid .gl-post-card img { width: 100%; height: 200px; object-fit: cover; display: block; }
.gl-posts-grid .gl-post-date { display: block; margin: 0.75em 0 0.25em; font-size: 0.85em; opacity: 0.7; }
@media (max-width: 991px) { .gl-posts-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 767px) { .gl-posts-grid { grid-template-columns: 1fr; } }

/* new-hero: the export's title was a div.ip-header; the block emits it as an
   h1 (these pages have no other h1) — neutralize the element's own margin. */
.new-hero h1.ip-header {
	margin-top: 0;
}

/* Luminous teal for bands that are navy by default — /skin-care-products/'s
   "Premium Skincare Brands" heading band and its product list. Opt-in through
   each block's `modifier` (service-section, product-list), so every other
   .blue band and the homepage's .services-holder stack stay navy. The first
   selector matches .main-service-section.less.blue's (0,3,0) and wins on load
   order. White on #4b7881 is ~4.9:1 (AA). */
.main-service-section.blue.lum-bg,
.services-holder.lum-bg {
	background-color: var(--_luminous---color-2);
}

/* ---------------------------------------------------------------------------
 * glacial/page-intro — top-of-page split (copy beside a photo).
 * The photo column fills the full height of the row and the image cover-crops
 * to it, so the two columns always square off however long the copy runs.
 * Stacked (<=991px) the photo reverts to its own aspect ratio.
 * With no image the copy column runs full width.
 * ------------------------------------------------------------------------- */
.gl-page-intro > .wrap.flex {
	/* stretch (not center) so the photo column takes the full row height — that
	   resolved height is what .gl-intro-img's height:100% cover-crop needs. */
	align-items: stretch;
	justify-content: space-between;
	gap: 4%;
}

.gl-page-intro .gl-intro-text {
	flex: 1 1 auto;
	min-width: 0;
}

.gl-page-intro .gl-intro-text--full {
	flex-basis: 100%;
}

.gl-page-intro .gl-intro-media {
	flex: 0 0 44%;
	max-width: 44%;
	display: flex;
	overflow: hidden;
}

/* Fills the column and crops to it. Specificity has to beat style.css's
 * `img, .entry img { height: auto }`, hence the two-class selector. */
.gl-page-intro .gl-intro-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/* Editor only (the front end renders no media column at all when there is no
 * image): the "Choose image" placeholder drops to its own row UNDER the copy so
 * the copy fills the container exactly as it will on the front end, instead of
 * being squeezed into a column by editor-only chrome. */
.gl-page-intro > .wrap.flex:has(> .gl-intro-media--empty) {
	flex-wrap: wrap;
}

.gl-page-intro .gl-intro-media--empty {
	flex-basis: 100%;
	max-width: 100%;
	/* explicit, because a percentage row-gap resolves against an auto height */
	margin-top: 24px;
	padding: 32px 16px;
	border: 1px dashed #949494;
	text-align: center;
	justify-content: center;
	align-items: center;
	flex-direction: column;
}

.gl-page-intro .gl-intro-media--empty p {
	margin: 8px 0 0;
	font-size: 13px;
	color: #757575;
}

@media screen and (max-width: 991px) {
	.gl-page-intro > .wrap.flex {
		flex-flow: column;
		gap: 24px;
	}

	.gl-page-intro .gl-intro-media {
		flex-basis: auto;
		max-width: 100%;
		width: 100%;
	}

	/* Stacked: no row height to fill, so show the photo whole again. */
	.gl-page-intro .gl-intro-img {
		height: auto;
	}
}

/* imageFit 'contain': the photo keeps its own aspect ratio, whole, centred in
 * its column instead of filling it. For product shots on white (the skin-care
 * brand pages), where the cover-crop would clip the outer bottles beside a
 * long intro. The column still stretches so the row squares off; only the
 * image inside stops stretching. */
.gl-page-intro.gl-intro-fit-contain .gl-intro-media {
	align-items: center;
}

.gl-page-intro.gl-intro-fit-contain .gl-intro-img {
	height: auto;
	object-fit: contain;
}

.gl-faq {
	margin-bottom: 30px;
}

a.button {
	text-decoration: none;
}

.wp-block-list a {
	text-wrap: wrap;
}

/*
 * glacial/treatment-link — luminous variant.
 * Webflow's cosmetic-dermatology-v2 export puts `lum` (and `btm` on the last
 * row) on each .inside-treatment-link, but the block's save() emits a fixed
 * class list, so the modifier can't ride on the child. It only ever appears
 * inside a .counter-holder-copy.lum-2 parent — which glacial/treatment-links
 * DOES emit via its `modifier` attribute — so scope it off the parent instead.
 * Mirrors css/webflow.css .inside-treatment-link.lum / .lum.btm.
 */
.counter-holder-copy.lum-2 .inside-treatment-link {
	padding: 10px 10px 0;
	line-height: 1.3em;
}

.counter-holder-copy.lum-2 .inside-treatment-link:hover {
	background-image: linear-gradient(to bottom, var(--_luminous---color-4), var(--_luminous---color-4));
}

.counter-holder-copy.lum-2 > .inside-treatment-link:last-child {
	padding-bottom: 10px;
}

.welcome-img-holder img {
	height: 100%;
}

/* ---------------------------------------------------------------------------
 * glacial/service-tabs — #hash landing under the fixed header.
 *
 * The three Hair / Face / Body sections on /cosmetics/ carry ids and are the
 * targets of the on-page pills AND the Cosmetic mega-menu column headings
 * (2026-09-09). The header is fixed — 151px tall at desktop, 138px <=991px,
 * 103px on phones — so a bare #hash jump parked each section's heading
 * underneath it. scroll-margin-top keeps the heading clear (same fix and
 * numbers as the region finder's panel, css/gsd-region-finder.css).
 * ------------------------------------------------------------------------- */
.wp-block-glacial-service-tabs {
    scroll-margin-top: 172px;
}

@media (max-width: 991px) {
    .wp-block-glacial-service-tabs {
        scroll-margin-top: 160px;
    }
}

@media (max-width: 767px) {
    .wp-block-glacial-service-tabs {
        scroll-margin-top: calc(var(--gsd-header-h, 103px) + 21px); /* single-row header since 2026-10-05; see style.css */
    }
}

/* ---------------------------------------------------------------------------
 * glacial/service-tabs — tighten the vertical rhythm around the tab set.
 *
 * The Webflow export sizes this whole section in PERCENTAGES of the container
 * width, and on a Full Bleed page the container IS the viewport — so the gaps
 * grow with the window instead of with the type. Measured on /cosmetics/ at
 * 1440px (webflow.css .ajax.face `margin: 5% 5% 0%` + .ajax.face.btm-marg
 * `margin-bottom: 8%`):
 *
 *   Hair/Face/Body heading -> its tab row        72px
 *   end of one tab set -> the next heading      187px  (115 + the section's
 *                                                       own 5% padding-top)
 *
 * Both read as dead bands between the three sections. Swapped for clamp()s
 * that hold a sane size at every width, matching the idiom the rest of this
 * file already uses: heading -> tabs 24-28px, below the tab set 32-80px.
 *
 * The bottom gap was first set at clamp(32px, 3vw, 44px) and opened back up to
 * clamp(32px, 5vw, 80px) (owner, 2026-09-23). Phones
 * (<=640px) are unchanged at the 32px floor; 51px at 1024, 72px at 1440, 80px
 * from 1600. At 1440px on /cosmetics/: heading gap 28px, end of one tab set ->
 * the next heading ~144px (72 + the section's 5% padding-top).
 *
 * ⚠ Applies to EVERY service-tabs block — /cosmetics/, /esthetician-services/,
 * /hair-restoration/, /vein-treatment/. A banded section is unaffected (its
 * own rule below zeroes this margin), but the gap ABOVE a band is a collapse
 * of this margin with the band's margin-top, so above 1440px it follows this
 * value (up to 80px) rather than the band's 72px.
 *
 * Scoped to the block because .ajax.face is shared Webflow furniture and
 * css/webflow.css is a per-site export that a re-export would overwrite — the
 * only markup emitting it is blocks/service-tabs/render.php.
 *
 * ⚠ The heading gap is a MARGIN COLLAPSE, not a single value: .wrap.btm-marg
 * .center carries `margin-bottom: 50px` and the tab set carries the top
 * margin, so the larger of the two wins. Lowering only the top margin floors
 * the gap at 50px — that is why the wrap is zeroed here as well.
 *
 * The left/right 5% is deliberately untouched (longhands, not the shorthand);
 * it is the section's horizontal gutter, not part of this.
 * ------------------------------------------------------------------------- */
.wp-block-glacial-service-tabs .wrap.btm-marg.center {
    margin-bottom: 0;
}

.wp-block-glacial-service-tabs .ajax.face {
    margin-top: clamp(24px, 2vw, 28px);
}

.wp-block-glacial-service-tabs .ajax.face.btm-marg {
    margin-bottom: clamp(32px, 5vw, 80px);
}

/* ---------------------------------------------------------------------------
 * glacial/service-tabs — optional background band (`background` attribute).
 *
 * The three Hair / Face / Body sections on /cosmetics/ sit on the page's white
 * ground and run together. Setting `background` on one lays a colour band
 * behind it, which breaks the page into readable chunks. Opt-in: an empty
 * attribute emits no class at all, so every section built before this renders
 * unchanged.
 *
 * Colours are the Luminous palette this page already uses — `cream` is the
 * same #fcf5e9 as .emph-div.lum and the treatment-link hover, `tint` the pale
 * navy wash .pick-section carries. Both are light, so the section's own type,
 * gold tab underline and outlined buttons keep working; a dark band would need
 * an inverted palette for all three and is deliberately not offered.
 *
 * ⚠ The bottom padding is NOT decoration — .main-service-section.lum sets
 * `padding-bottom: 0%` (css/webflow.css), which is invisible on white and
 * would end the band flush against the last tab pane. (0,3,0) here beats that
 * (0,2,0).
 *
 * ⚠ The top margin COLLAPSES with the preceding section's tab set: .ajax.face
 * .btm-marg's margin-bottom passes straight through .main-service-section.lum
 * (no bottom padding, no border) and out of the block wrapper, so the gap
 * above the band is max(that, this) — NOT the sum. That is why this clamp sits
 * above the 32/44 one and not alongside it; at 1440px the gap reads 72px.
 *
 * ⚠ And the band has to ZERO its own tab set's btm-marg, for the mirror image
 * of that reason: with no bottom padding that 32-44px escaped the section, but
 * the moment padding-bottom exists it is trapped INSIDE and stacks on top of
 * it, so the band ran 115px deep under its last pane against 72px above its
 * heading. Zeroed, the padding owns the space on both sides and the band reads
 * symmetrical (72/72 at 1440px). The space it used to contribute below the
 * section is replaced by the band's own padding plus the next section's
 * padding-top.
 * ------------------------------------------------------------------------- */
.wp-block-glacial-service-tabs.gl-service-tabs-bg {
    margin-top: clamp(40px, 5vw, 72px);
}

.wp-block-glacial-service-tabs.gl-service-tabs-bg .main-service-section {
    padding-bottom: clamp(40px, 5vw, 72px);
}

.wp-block-glacial-service-tabs.gl-service-tabs-bg .ajax.face.btm-marg {
    margin-bottom: 0;
}

.wp-block-glacial-service-tabs.gl-service-tabs-bg-cream .main-service-section {
    background-color: var(--_luminous---color-4);
}

.wp-block-glacial-service-tabs.gl-service-tabs-bg-tint .main-service-section {
    background-color: var(--color-13);
}

/* ---------------------------------------------------------------------------
 * Tab labels: navy on the selected and the rolled-over tab (owner, 2026-09-17
 * — the active tab on /cosmetics read as white).
 *
 * The export paints the active tab with --_luminous---color (#e1a300) and
 * leaves the label var(--color), which is literally `white`. White on that
 * amber is ~2.2:1 and fails SC 1.4.3; navy #001543 on the same amber is
 * ~7.9:1, past AAA. Only the LABEL changes — the amber is the section's
 * selected-tab colour and stays.
 *
 * This is the call css/gsd-provider-tabs.css already made for the provider
 * strip, which shares .tab-link.dark.lum and carries the same 2.2:1 note. The
 * two are now consistent: gold/amber tab, navy label, everywhere.
 *
 * ⚠ HOVER is included deliberately, not just .w--current.
 * `.tab-link.dark.lum:hover` puts that same amber under EVERY tab, and the
 * colour it inherits (`.tab-link.dark:hover`) is the same white — so fixing
 * only the selected tab would leave the identical failure one pointer-move
 * away. :focus rides along because Webflow's tabs module moves focus with the
 * arrow keys, which must not look different from hovering.
 *
 * ⚠ SPECIFICITY: `.dark.lum` is repeated on purpose, per the convention in
 * CLAUDE.md. The white comes from `.tab-link.dark.w--current` and
 * `.tab-link.dark:hover` — both (0,3,0) — so the tidy
 * `.wp-block-glacial-service-tabs .tab-link.w--current` would merely TIE them
 * and win on source order alone, which the next stylesheet could take back.
 * Spelling out .dark.lum makes it (0,5,0) and beats the export outright.
 * ------------------------------------------------------------------------- */
.wp-block-glacial-service-tabs .tab-link.dark.lum.w--current,
.wp-block-glacial-service-tabs .tab-link.dark.lum.w--current:hover,
.wp-block-glacial-service-tabs .tab-link.dark.lum.w--current:focus,
.wp-block-glacial-service-tabs .tab-link.dark.lum:hover,
.wp-block-glacial-service-tabs .tab-link.dark.lum:focus {
    color: var(--color-2, #001543);
}

/* ---------------------------------------------------------------------------
 * Even tab heights: a two-line label no longer leaves its neighbours short.
 *
 * `.tabs-menu` (css/webflow.css:2728) sets `align-items: center`, so every tab
 * sizes to its OWN label. A label that wraps to two lines stands taller than
 * the one-line ones, the amber blocks step against each other, and white shows
 * between the short tabs and the underline.
 *
 * The export already fixes this — but only inside
 * `@media screen and (max-width: 991px)` (css/webflow.css:3648). Desktop never
 * got it, which is exactly where labels wrap most: `.tab-link.dark.lum` is
 * `width: 20%`, so "Regenerative & Bio-Enhancement Therapies" has ~246px to
 * fit on a 1232px container. The declarations below are that same pair, copied
 * verbatim from the export so the two breakpoints cannot drift apart, and the
 * widths left behind because those ARE breakpoint-specific.
 *
 * ⚠ SCOPED to this block deliberately, even though `.tabs-menu.hair` /
 * `.tab-link.dark.lum` are shared markup. The only other user is
 * `includes/gsd/gsd-provider-tabs.php`, and `css/gsd-provider-tabs.css` has
 * ALREADY made this exact fix for itself (`.gsd-provider-tabs .tabs-menu`
 * stretch + `.gsd-provider-tabs .tab-link` flex). An unscoped
 * `.tab-link.dark.lum` here is (0,3,0) and would outrank that file's
 * deliberate (0,2,0) row-flex rule from another stylesheet — so the tidy-
 * looking shared fix is the one that breaks the provider strip. Keep it scoped;
 * if a third consumer of `.tabs-menu` ever appears, give it its own rule
 * rather than widening this one.
 * ------------------------------------------------------------------------- */
.wp-block-glacial-service-tabs .tabs-menu.face,
.wp-block-glacial-service-tabs .tabs-menu.hair {
    align-items: stretch;
}

.wp-block-glacial-service-tabs .tab-link.dark.lum {
    display: flex;
    flex-flow: column;
    justify-content: center;
    align-items: center;
}

/* ---------------------------------------------------------------------------
 * Steps Section — the quarter cards fade lighter across the row.
 *
 * The Webflow export hand-carries this as combo classes on each individual
 * card (.serv-txt-49._24 / ._2._24 / ._3._24 / ._3._24._4 — see
 * webflow/mohs-micrographic-surgery.html), which welds the shade to a card's
 * position in the source order. Driving it from :nth-child instead keeps every
 * card's markup identical, so reordering, inserting or deleting a card in the
 * editor re-ramps the row on its own and no stored content has to change.
 * enqueue_block_assets loads this file inside the editor iframe too, so the
 * canvas shows the same ramp as the front end.
 *
 * Colours are the export's, unchanged: 25% -> 15% -> 10% -> 5% navy. Card 1
 * keeps webflow.css's --color-13 (#002d7240). Rows longer than four hold at
 * the lightest step rather than fading out to nothing.
 * ------------------------------------------------------------------------ */
.services-2 > .serv-txt-49._24:nth-child(2) {
	background-color: #002d7226;
}

.services-2 > .serv-txt-49._24:nth-child(3) {
	background-color: #002d721a;
}

.services-2 > .serv-txt-49._24:nth-child(n+4) {
	background-color: #002d720d;
}

/* ---------------------------------------------------------------------------
 * Buttons in the editor canvas.
 *
 * The site's button look (outlined navy on transparent) lives in style.css,
 * which the editor never loads — the canvas chain is normalize -> components
 * -> webflow.css -> this file (see glacial-blocks.php). So core's default
 * solid-fill button showed instead, with no border.
 *
 * style.css also selects `a.wp-block-button__link`, and the editor's button is
 * a RichText element rather than an anchor, so the tag qualifier is dropped
 * here. Declarations otherwise mirror the front end exactly — keep the two in
 * step ("Button Code" in style.css).
 *
 * The front-end :hover transform (scale(.9)) is deliberately NOT mirrored: a
 * button that shrinks under the pointer is a moving hit target while editing.
 * ------------------------------------------------------------------------ */
.editor-styles-wrapper .wp-block-button__link {
	color: var(--color-2, #001543);
	font-size: 18px;
	font-weight: 500;
	line-height: 1em;
	border: 2px solid var(--color-2, #001543);
	border-radius: 0;
	text-transform: capitalize;
	display: inline-block;
	padding: 15px 30px;
	text-align: center;
	text-decoration: none;
	background: transparent;
}

/* The reversed button the CTA/hero bands use sits on a dark ground. */
.editor-styles-wrapper .wp-block-button__link.rev,
.editor-styles-wrapper .inner-cta-div .wp-block-button__link {
	color: var(--color, #fff);
	border-color: var(--color, #fff);
}

/* ---------------------------------------------------------------------------
 * Service Row vertical alignment.
 *
 * webflow.css gives .wrap.flex `align-items: stretch` (equal-height columns)
 * and ships one modifier, .center-align, which the block reuses verbatim for
 * "Middle". Top and Bottom have no export equivalent, so they get these.
 * Below 991px webflow.css turns .wrap.flex into a column, where align-items
 * governs the horizontal axis instead — so these stop applying there and the
 * stacked rows keep the export's own behaviour.
 * ------------------------------------------------------------------------ */
@media (min-width: 992px) {
	.wrap.flex.gl-align-start {
		align-items: flex-start;
	}

	.wrap.flex.gl-align-end {
		align-items: flex-end;
	}
}

/* ---------------------------------------------------------------------------
 * CTA bands stop growing at 1350px (2026-09-21, owner).
 *
 * webflow.css gives .cta-wrap a bare `width: 80%` with auto margins, so on a
 * wide monitor the band and its cut-out photo kept scaling with the viewport
 * and the copy ran to very long line lengths. The cap holds the centring (the
 * auto margins still do the work) and simply stops the growth.
 *
 * ⚠ Scoped `.cta .cta-wrap`, which is (0,2,0) and so beats webflow's bare
 * `.cta-wrap` (0,1,0) on specificity rather than relying on load order.
 *
 * ⚠ This intentionally covers `glacial/location-insurances` as well as
 * `glacial/cta-section` — both emit the identical
 * `<section class="cta"><div class="cta-wrap">` shell, and they appear on the
 * same pages, so capping only one would leave the two bands misaligned at
 * wide widths. Narrow to `.wp-block-glacial-cta-section .cta-wrap` if they
 * should ever diverge.
 * ------------------------------------------------------------------------- */
.cta .cta-wrap {
    max-width: 1350px;
}

/* ---------------------------------------------------------------------------
 * CTA band on phones — no cut-out photo, no reserved space.
 *
 * The photo is absolutely placed at the bottom of .inner-cta-div, and
 * webflow.css reserves 200-300px of padding-bottom (varying by variant and
 * breakpoint) purely to clear it. At phone widths that photo is decorative and
 * the reserved band is mostly empty, so both go.
 *
 * Each variant is listed explicitly because webflow.css sets them at the same
 * (0,2,0) specificity — this file loads after it, so equal specificity wins on
 * source order. .cta-column.txt keeps its own 20px, so the copy still breathes.
 * ------------------------------------------------------------------------ */
@media (max-width: 479px) {
	.inner-cta-div > .cta-column.hide-outer {
		display: none;
	}

	.inner-cta-div,
	.inner-cta-div.lum,
	.inner-cta-div.insur,
	.inner-cta-div.mohs,
	.inner-cta-div.vein,
	.inner-cta-div.skin {
		padding-bottom: 0;
	}
}

/* ---------------------------------------------------------------------------
 * glacial/grid — "Icon images".
 *
 * Grid cells are cards, so an <img> in one fills the column: the 512px and
 * 835px square PNGs on /about-us/ rendered ~500px wide. This caps images in
 * the cells to icon size and keeps them from stretching, without touching
 * grids whose cells hold real photographs (partnership-opportunities), which
 * is why it is opt-in per grid rather than a blanket .gl-cell rule.
 *
 * Size is a custom property so it can be tuned per grid from the editor's
 * Advanced > Additional CSS, or globally here.
 * ------------------------------------------------------------------------ */
.gl-grid--icons {
	--gl-grid-icon-size: 96px;
}

.gl-grid--icons .gl-cell .wp-block-image img {
	width: auto;
	max-width: var(--gl-grid-icon-size);
	height: auto;

	/* Centred over the cell's copy, which stays left-aligned. */
	display: block;
	margin-left: auto;
	margin-right: auto;
}

/* The figure is the block wrapper — zero it so the centring above is measured
   against the cell, not an inherited margin. */
.gl-grid--icons .gl-cell .wp-block-image {
	margin-left: 0;
	margin-right: 0;
}

.single-location h1 {
	color: var(--color-2);
	margin-top: 0;
	margin-bottom: 20px;
	font-family: trajan-sans-pro, sans-serif;
	font-size: 2.5em;
	font-weight: 400;
	line-height: 1.2em;
}

@media (max-width: 991px) {
	.single-location h1 {
		font-size: 2em;
	}
}


/* ==========================================================================
 * Homepage section blocks — glacial/home-* (2026-09-02)
 *
 * The homepage was a hand-ported copy of webflow/index.html until it became
 * blocks. Everything below exists because a block has to be REORDERABLE and
 * REUSABLE where the export could hard-code position: the export encodes
 * "which panel am I" and "which pills are on a white panel" as literal classes
 * (._1…._8, .purple, ._48, .light.short); the blocks derive the same looks from
 * DOM position and from the parent they sit in, so the client can reorder a
 * service panel and every offset, colour and number follows.
 * ========================================================================== */

/* --- Service panels: position-derived sticky stacking -----------------------
   webflow.css gives each .sticky-service-section a ._N modifier that pins its
   sticky `top` at 120 + 70·(N−1) px and paints even panels white with the
   navy-tint gradient. Those classes ARE the position, so a block can't carry
   them; the parent's DOM order supplies them instead. nth-of-type, not
   nth-child — .spacer is the first child and the trailing button the last.
   The export's ten literal offsets are one calc() here, fed by --gl-panel-top
   and --gl-panel-step on .services-holder, so retuning the stack is a
   two-value edit instead of ten (2026-09-08).
   Specificity (0,3,0) beats webflow's ._N rules at (0,2,0). ._8 in the export
   lacked width:100% (an authoring slip that renders identically under
   flex-shrink), and ._1's padding-top:20px is already the base padding — both
   normalised here. Same idea as steps-section's :nth-child fade ramp. */
.services-holder {
	counter-reset: gl-home-panel;

	/* THE TWO KNOBS for the whole sticky stack. Every panel's `top` — and the
	   trailing .spacer's — is calc()'d from these, so moving the FIRST panel
	   moves the entire ramp and the gaps stay even. Defaults reproduce the
	   export's ramp shape: 70px of visible title lip per card. --gl-panel-top
	   is where card 01 pins and every other card follows it.

	   It is 190px, not the export's 120px, because .glacial-top-banner is
	   FIXED and 151px tall here — at 120px the header cropped the top 31px of
	   card 01, cutting "01 MEDICAL DERMATOLOGY" in half (measured 2026-09-08).
	   The export was drawn against a shorter header. 155px is the tightest
	   value that clears it if you want the cards tucked flush under the nav;
	   190px leaves a deliberate ~39px of navy above card 01.
	   Change --gl-panel-step to fan the cards apart or tighten the lip.
	   Nothing else needs touching — the panels and the .spacer all follow. */
	--gl-panel-top: 190px;
	--gl-panel-step: 70px;
}

/* The class is repeated on purpose: it lifts this rule to (0,3,0) so the
   calc()'d `top` still outranks webflow's `._N { top: <literal>px }` at
   (0,2,0) on its own specificity, not on stylesheet order. Block-rendered
   panels carry no `._N`, but the retired hand-ported front-page markup does,
   and source order is the weaker guarantee of the two. */
.services-holder > .sticky-service-section.sticky-service-section {
	width: 100%;
	counter-increment: gl-home-panel;
	--gl-panel-index: 1;
	top: calc(var(--gl-panel-top) + var(--gl-panel-step) * (var(--gl-panel-index) - 1));
}

.services-holder > .sticky-service-section:nth-of-type(even) {
	background-color: var(--color);
	background-image: linear-gradient(to bottom, var(--color-3), var(--color-3));
}

/* Position → index, and that is ALL nth-of-type supplies now; the formula
   above turns the index into a `top`. Ten rules cover the homepage's eight
   with headroom, and an 11th panel keeps index 1 (pinned at the base) rather
   than falling back to webflow.css's top:0 and pinning under the header. */
.services-holder > .sticky-service-section:nth-of-type(2)  { --gl-panel-index: 2; }
.services-holder > .sticky-service-section:nth-of-type(3)  { --gl-panel-index: 3; }
.services-holder > .sticky-service-section:nth-of-type(4)  { --gl-panel-index: 4; }
.services-holder > .sticky-service-section:nth-of-type(5)  { --gl-panel-index: 5; }
.services-holder > .sticky-service-section:nth-of-type(6)  { --gl-panel-index: 6; }
.services-holder > .sticky-service-section:nth-of-type(7)  { --gl-panel-index: 7; }
.services-holder > .sticky-service-section:nth-of-type(8)  { --gl-panel-index: 8; }
.services-holder > .sticky-service-section:nth-of-type(9)  { --gl-panel-index: 9; }
.services-holder > .sticky-service-section:nth-of-type(10) { --gl-panel-index: 10; }

/* webflow.css pins .spacer at a flat top:890px — the same ramp carried two
   steps past a tenth panel (120 + 70·11). Restated at (0,2,0) so it beats the
   bare .spacer rule and tracks the knobs; otherwise raising the base would
   leave the stack's tail-out gap stranded at the old offset. */
.services-holder > .spacer {
	top: calc(var(--gl-panel-top) + var(--gl-panel-step) * 11);
}

/* The "01 … 08" beside each title is sequencing, not content: the block emits
   an EMPTY .title-number and the counter fills it, so a reorder renumbers.
   :empty keeps this off any hand-written panel that still carries the literal
   number as text (the pre-block template) — it would otherwise read "0101". */
.services-holder > .sticky-service-section .title-number:empty::before {
	content: counter(gl-home-panel, decimal-leading-zero);
}

/* = .services-holder-main.stack (webflow.css:939). The export stacks the
   copy-only panels (flex column) and lays link lists side by side (flex row);
   which one a panel is follows from what it holds, so it is derived from the
   content: a panel whose main area contains a paragraph stacks. (Panel 8 in the
   export carried a paragraph WITHOUT .stack — a one-child column and a
   one-child row render identically, so this is faithful for it too.) */
.services-holder-main:has(> p) {
	flex-flow: column;
}

/* Mirrors webflow.css's ≤991 rule for ._1…._8 (margins off, no longer sticky). */
@media screen and (max-width: 991px) {
	.services-holder > .sticky-service-section {
		margin-left: 0;
		margin-right: 0;
		position: static;
	}
}

/* --- Link pills: derived variants ------------------------------------------
   glacial/link-pill emits the bare `doc-patient-link w-inline-block`. The
   export's three modifiers turn out to be facts about the CONTAINER, not the
   pill, so they are restated here on the container:

   .purple      — exactly the even (white-background) service panels
   ._48         — only exists inside media queries, and only on pills in a
                  full-width list; ._100 itself is "the only list in the panel"
   .light.short — only in the stats band (.gl-home-stats)

   Each block below is a copy of the matching webflow.css rule (lines 701–725,
   3156, 3737, 4125) under the derived selector; icons resolve from this file's
   own location (blocks/assets/ → ../../images/). */

/* = .doc-patient-link.purple (webflow.css:717-725) */
.services-holder > .sticky-service-section:nth-of-type(even) .doc-patient-link {
	background-image: url('../../images/icons8-right-arrow-1.svg');
	width: auto;
}

.services-holder > .sticky-service-section:nth-of-type(even) .doc-patient-link:hover {
	background-color: var(--color);
	color: var(--color-3);
}

/* = .services-list._100 (webflow.css:951-953, :3222-3225). A list is "full"
   exactly when it is the only list in its panel, so that is derived as well:
   add a second glacial/home-service-list and both drop to the 49% column
   width on their own. */
.services-holder-main > .services-list:only-child {
	width: 100%;
}

@media screen and (max-width: 991px) {
	.services-holder-main > .services-list:only-child {
		flex-flow: wrap;
		display: flex;
	}
}

/* = .doc-patient-link._48 (webflow.css:3156, :3737) — only ever on the pills
   of a full-width list. */
@media screen and (max-width: 991px) {
	.services-holder-main > .services-list:only-child > .doc-patient-link {
		width: 48%;
	}
}

@media screen and (max-width: 767px) {
	.services-holder-main > .services-list:only-child > .doc-patient-link {
		width: 100%;
	}
}

/* A pill that is NOT a link must not hover. glacial/location-services-list
   prints its trailing "And many more…" (and any service with neither a page
   nor an external_url) as a <span class="doc-patient-link"> so it sits in the
   list like its siblings, but webflow.css:694 hovers the bare class — gold
   fill, navy text, padding-left slide — and a span with nothing to go to should
   not invite a click. Element-qualified so it stays off every real <a>. */
span.doc-patient-link:hover {
	border-bottom-color: #ffffff26;
	background-color: transparent;
	color: var(--color);
	padding-left: 10px;
}

/* = .doc-patient-link.light + .light.short (webflow.css:701-715, :4125) */
.gl-home-stats .doc-patient-link {
	border-bottom-color: var(--color-7);
	color: var(--color-2);
	background-image: url('../../images/icons8-right-arrow_1.svg');
	width: 40%;
}

.gl-home-stats .doc-patient-link:hover {
	background-color: var(--color-2);
	color: var(--color);
}

@media screen and (max-width: 479px) {
	.gl-home-stats .doc-patient-link {
		width: 95%;
	}
}

/* --- Stats: the counters were eight <h1>s ----------------------------------
   Each .counter-div held two <h1 class="heading"> (value, suffix) — eight h1s
   in one section. .heading is class-styled (colour, size, weight, line-height)
   so the block emits <div class="heading"> instead; this restores the only
   thing the h1 tag contributed, its margins (components.css:199-212). */
.gl-home-stats .heading {
	margin: 20px 0 10px;
}

/* --- Hero: background video cover -------------------------------------------
   The export sized the Vimeo iframe with a leaked inline
   style="width:1905px;height:1073px" and let .hero-column-right-2's
   overflow:hidden crop it — a fixed-pixel fake of object-fit:cover that
   nothing else in the CSS provides (.code-embed iframe is unsized). Vimeo's
   background player letterboxes rather than covers, so the frame must stay
   16:9 AND be at least the box in both dimensions:
     width  = max(W, H·16/9),  height = max(H, W·9/16)
   which is exactly 16:9 whichever branch wins. W and H are the column's size
   in viewport units at each breakpoint (60vw × 85vh; 100vw × 400px; × 260px). */
.new-hero-2 .code-embed {
	position: absolute;
	inset: 0;
	overflow: hidden;
}

.new-hero-2 .code-embed iframe {
	position: absolute;
	top: 50%;
	left: 50%;
	width: max(100%, 151.12vh);   /* 85vh × 16/9 */
	height: max(100%, 33.75vw);   /* 60vw × 9/16 */
	transform: translate(-50%, -50%);
}

@media screen and (max-width: 991px) {
	.new-hero-2 .code-embed iframe {
		width: max(100%, 711.12px);  /* 400px × 16/9 */
		height: max(100%, 56.25vw);  /* 100vw × 9/16 */
	}
}

@media screen and (max-width: 479px) {
	.new-hero-2 .code-embed iframe {
		width: max(100%, 462.23px);  /* 260px × 16/9 */
	}
}

/* The self-hosted branch (videoType: 'file', the homepage default since
   2026-09-15) needs NONE of the maths above: an <iframe> cannot be told to
   cover its box, but a <video> can, so this is the whole rule. The element
   fills .hero-column-right-2, which webflow.css already makes position:
   relative with overflow: hidden.

   object-position stays centred on purpose — the montage frames its subjects
   centrally, and the column crops from the sides on desktop (60vw × 85vh) and
   from top and bottom ≤991px (100vw × 400px).

   The navy on .hero-column-right-2 is repeated here so the box is never white
   in the sliver before the poster decodes, and after view.js drops the src on
   a narrow screen. */
.new-hero-2 .gsd-hero-video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	background-color: #001543;
}

/* Click-to-play button, revealed by view.js wherever the video is not
   auto-loaded — phones, and prefers-reduced-motion at any width. There is
   deliberately NO media query governing when it SHOWS: view.js reveals it from
   the same branch that withholds the src, so the 768px line lives in one place.

   ⚠ A DELIBERATE MIRROR of `.gsd-pause` in css/gsd-pause-controls.css
   (owner request 2026-09-17). The two share the corner and are never on screen
   together — play shows only while the video is unloaded, pause only once it
   is — so they have to read as ONE control that changes word, not as two
   different buttons swapping places. Navy pill, 2px white ring, 13px/600 label
   beside a 14px glyph, 44px floor, the shadow, the hover, the focus ring and
   the ≤767 step-down are all that file's values. KEEP THE TWO IN STEP.

   ⚠ It cannot simply BE a `.gsd-pause`, tempting as that is:
   js/gsd-pause-controls.js binds every `button.gsd-pause` on the page as a
   pause toggle, so the class would hand this button to that script — which
   would flip `data-paused`, swap in the pause glyph and fight view.js for it.
   The class carries the behaviour, not just the look.

   The 44px floor is well past SC 2.5.8, and white on #031444 is ~16:1, so the
   glyph and the label both carry non-text contrast (SC 1.4.11) whatever the
   poster behind them happens to look like. */
.new-hero-2 .gsd-hero-play {
	position: absolute;
	/* The SAME inset as .gsd-pause (right/bottom 16px, z-index 5), so the control
	   does not jump when the video starts. */
	right: 16px;
	bottom: 16px;
	z-index: 5;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-width: 44px;
	min-height: 44px;
	padding: 0 10px;
	border: 2px solid #fff;
	background: #031444;
	color: #fff;
	font-family: var(--nav-font, inherit);
	font-size: 13px;
	font-weight: 600;
	line-height: 1;
	letter-spacing: .02em;
	cursor: pointer;
	box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
	-webkit-appearance: none;
	appearance: none;
}

.new-hero-2 .gsd-hero-play__icon {
	width: 14px;
	height: 14px;
	fill: currentColor;
	flex: none;
}

.new-hero-2 .gsd-hero-play:hover {
	background: #000d33;
}

.new-hero-2 .gsd-hero-play:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 3px;
}

@media screen and (max-width: 767px) {
	.new-hero-2 .gsd-hero-play {
		right: 10px;
		bottom: 10px;
		min-width: 36px;
		min-height: 36px;   /* still 1.5× the 24px minimum */
		padding: 0 12px;
	}
}

/* ⚠ The HTML `hidden` attribute is only `display: none` in the UA sheet, so the
   author `display: inline-flex` above BEATS it and the button would stay visible after
   view.js hid it — on desktop that means a play button sitting on top of an
   already-playing video. Restate it at author level. */
.new-hero-2 .gsd-hero-play[hidden] {
	display: none;
}

/* The optional separate mobile still. Sits over the <video> and is revealed by
   view.js in the same branch that withholds the src, so it is never on top of a
   playing video and needs no media query of its own. */
.new-hero-2 .gsd-hero-still {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: 1;
}

/* Same UA-vs-author trap as the play button above. */
.new-hero-2 .gsd-hero-still[hidden] {
	display: none;
}

/* ⚠ The mobile hero column collapses to ZERO height without this, so nothing in
   it is ever visible — no video, no poster, no button.

   webflow.css turns .new-hero-2 into `flex-flow: column` at ≤991px, which makes
   the cross axis HORIZONTAL: .hero-column-right-2 stretches in width only and
   takes its height from content. Every child it has is `position: absolute`
   (the video, the play button, the pause button — and .code-embed on the Vimeo
   branch), so there is no in-flow content and the box computes to 0px tall.
   webflow.css only ever gives it `max-height`, which cannot create height.

   Measured before this rule: .hero-column-right-2 was 390×0 at 390px wide.

   This is why the hero has NEVER shown media on a phone, including on the old
   Vimeo iframe — it is not a regression from the self-hosted video. The heights
   below are webflow.css's own max-height values, so the box now matches the size
   the design always intended. */
@media screen and (max-width: 991px) {
	.new-hero-2 .hero-column-right-2 {
		height: 400px;
	}
}

/* ⚠ The white text card is MEANT to overlap the photo, and the rule that says
   so has never worked. webflow.css:3501 pulls it up with `margin-bottom: -50px`
   at ≤991px, and webflow.css:2095 gives it `z-index: 1` to sit on top — but it
   sets no `position`, so that z-index applies to a static box and does nothing.

   While .hero-column-right-2 was collapsed to 0px nothing was there to overlap.
   Now that it has real height, the absolutely-positioned image inside it painted
   OVER the card and clipped the "Want to Be Seen Today?" panel.

   `position: relative` is all that is needed: it activates the z-index already
   declared. The right column is given `z-index: 0` so it becomes its own
   stacking context and keeps its own children (the video, the still, and the
   two buttons at z-index 5) contained rather than competing with the card. */
.new-hero-2 .hero-text-div-white-2 {
	position: relative;
}

.new-hero-2 .hero-column-right-2 {
	z-index: 0;
}

/* ⚠ `max-height` has to be restated alongside the height: webflow.css:4321
   caps this column at 250px here, and a `height` over a `max-height` is
   clamped, not honoured — so setting one without the other does nothing.
   260px (2026-09-17, owner request). */
@media screen and (max-width: 479px) {
	.new-hero-2 .hero-column-right-2 {
		height: 260px;
		max-height: 260px;
	}
}

/* ⚠ DESKTOP PROPORTIONS (2026-09-16, owner request): give the video more room.

   The export split the hero 40 / 60 and then let the white card spill across
   the seam — `min-width: 150%` of the left column's content box, pushed a
   further `left: 55px`. At 1440px that is a 648px card starting 127px in and
   covering ~200px of the video. The video became the point of this hero when
   it moved from a Vimeo iframe to the self-hosted file (2026-09-15), so the
   columns now go 30 / 70, the card is narrower, its type steps down, and it
   sits further left. It still crosses the seam — by ~105px instead of ~200px.

   Every number is a percentage of the SECTION, the way the export's were, so
   the overlap keeps its proportion at every desktop width instead of drifting
   the way a px cap would: card left edge at 4%, card 128% of a 26% content box
   (= 33.3% of the section), video starting at 30%.

   Scoped to `min-width: 992px` because webflow.css:3492+ already rebuilds all
   of this for the stacked layout — one column, full-width card, no overlap —
   and none of that should move. Scoped to `.new-hero-2` because
   block-builders.php emits the same class names for the inner-page hero
   (`.hero-column-left-2.ip` / `.hero-text-div-white-2.ip`); style.css's
   location hero carries a note about the same trap. */
@media screen and (min-width: 992px) {
	.new-hero-2 .hero-column-left-2 {
		width: 30%;
		/* The right padding was always dead — the card overflows past it — and
		   the left steps 5% → 4% so the card travels left with the column. */
		padding: 5% 0 5% 4%;
	}

	.new-hero-2 .hero-column-right-2 {
		width: 70%;
	}

	.new-hero-2 .hero-text-div-white-2 {
		/* ⚠ Stays `min-width`, NOT `width`: the card is a flex item in
		   .hero-column-left-2, so flex-shrink pulls any `width` over 100% back
		   to the column's content box. A floor is the only thing that holds —
		   which is why the export sized it this way too. */
		min-width: 128%;
		padding: 24px;
		/* Was 55px: the card's whole shift rightward, now off. */
		left: 0;
	}

	.new-hero-2 .hero-top-line-2 {
		font-size: 2.25em;
	}

	.new-hero-2 .hero-line-3 .text-block {
		font-size: 1.45em;
	}

	/* The card's lower half. The icon circle overhangs the button box by 25px
	   (`margin-top: -25px`), so this margin is really a 25px gap at 50px. */
	.new-hero-2 .hero-button-div-2 {
		margin-top: 40px;
	}

	.new-hero-2 .hero-button-top-line-2 {
		height: 26px;
		font-size: 1.2em;
	}

	.new-hero-2 .same-day-line {
		font-size: 1.05em;
	}
}

/* --- Hero panel: one column edge (2026-09-16, owner request) ----------------
   The white card's three pieces — heading, appointment card, gold headline band
   — now line up on the same left and right edges, with the band moved below the
   card in render.php.

   ⚠ .hero-text-holder had to be told to STRETCH. Its parent
   .hero-text-div-white-2 is `flex-flow: column; align-items: flex-start`
   (webflow.css:2095), so the holder was shrink-to-fit: its width was the widest
   line inside it, capped at the card. That is invisible while the <h1> is the
   widest thing and overflows the cap anyway — but "full width" then means "as
   wide as the longest heading", which drifts with the copy, the viewport and the
   font. Stretching makes it the card's width at every breakpoint, so the two
   rules below have something fixed to be 100% of.

   Scoped to .new-hero-2: block-builders.php and blocks/new-hero emit the same
   .hero-text-holder for the inner-page hero, where the shrink-to-fit column is
   the design. */
.new-hero-2 .hero-text-holder {
	align-self: stretch;
}

/* The appointment card spans the panel instead of shrink-wrapping its copy. Its
   own children are unaffected: .btn-2nd-line-2 is already `width: 100%` and so
   grows with it, while the navy .hero-button-top-line-2 stays centred at its
   text width — which is what cuts the notch in the white outline. */
.new-hero-2 .hero-button-div-2 {
	width: 100%;
}

/* The band was `margin: 10px 0 5px` as the h1's underline. As the panel's last
   element it needs a little more air above the card it now follows, and nothing
   below it — .hero-text-div-white-2's own padding is the bottom edge. */
.new-hero-2 .hero-line-3 {
	margin-top: 20px;
	margin-bottom: 0;
}

/* The appointment card is a link and had NO hover state at all (client audit
   2026-09-17). It is a navy card sitting on the white panel, so the affordance
   is its white outline (.btn-2nd-line-2's border) and the "Same Day…" line
   turning brand gold — NOT a background swap: `--color-6` under white text is
   ~2.2:1 and fails SC 1.4.3, while gold ON the navy is ~7.4:1.

   ⚠ The icon circle and .hero-button-top-line-2 stay navy deliberately. Both
   carry their own `background-color: #001543` and paint OVER the outline;
   tinting either gold would bury the white icon at 2.2:1, or fill in the notch
   the navy top line cuts through the border — which is the card's whole shape.

   :focus-visible is styled alongside :hover so the card reads identically to a
   keyboard, and the ring is offset clear of the icon circle, which overhangs the
   card's top edge by 25px (`margin-top: -25px`).

   No transform: the export's own `.button` hover uses `scale(.9)`, but this card
   is 100% of the panel and shrinking it would jump the layout under the cursor.
   Colour-only also means nothing here needs a prefers-reduced-motion guard. */
.new-hero-2 .btn-2nd-line-2,
.new-hero-2 .same-day-line {
	transition: border-color .2s, color .2s;
}

.new-hero-2 .hero-button-div-2:hover .btn-2nd-line-2,
.new-hero-2 .hero-button-div-2:focus-visible .btn-2nd-line-2 {
	border-color: var(--color-6, #d29f13);
}

.new-hero-2 .hero-button-div-2:hover .same-day-line,
.new-hero-2 .hero-button-div-2:focus-visible .same-day-line {
	color: var(--color-6, #d29f13);
}

.new-hero-2 .hero-button-div-2:focus-visible {
	outline: 2px solid var(--color-6, #d29f13);
	outline-offset: 3px;
}

/* --- Phone panel: one navy block, no white card (2026-09-17, owner request) --
   At 479px and under the hero panel stops being a white card sitting on the
   navy column and becomes the column: same navy, edge to edge, white heading.

   ⚠ `.hero-column-left-2` is ALREADY `#001543` at every width
   (webflow.css:2140) — what reads as white is `.hero-text-div-white-2`'s own
   `background-color: #fff` (webflow.css:2095). So clearing the CARD is what
   actually turns the panel navy; the column is restated here only so the
   intent survives a future change to either rule.

   The gold tagline band is dropped at this width — on a ~390px screen it wraps
   to three lines and pushes the appointment card below the fold. It still
   renders at every other breakpoint.

   ⚠ `margin-bottom: 0` cancels webflow.css:3500's `-50px`, which pulls the
   video column up under the panel so the card overlaps it. That overlap is the
   design on a tablet, where the card is white and reads as a separate object
   crossing the seam; with the panel now the same navy as nothing beneath it,
   the 50px would just be a navy strip over the top of the video. So the two
   bands sit flush instead.

   ⚠ The appointment card survives the swap untouched: `.hero-button-div-2` is
   navy-on-navy now, but `.btn-2nd-line-2`'s white outline is what draws it and
   `.hero-button-top-line-2` still cuts its notch through that border. Its label
   and `.same-day-line` were already `#fff`.

   Scoped to `.new-hero-2` like every rule above it — block-builders.php and
   blocks/new-hero emit the same class names for the inner-page hero
   (`.hero-column-left-2.ip` / `.hero-text-div-white-2.ip`), which must not move. */
@media screen and (max-width: 479px) {
	.new-hero-2 .hero-column-left-2 {
		background-color: #001543;
		/* webflow.css:3880 gives it 15px here; the card's own 15px
		   (webflow.css:4317) is the gutter now, so the navy runs edge to edge. */
		padding: 0;
	}

	.new-hero-2 .hero-text-div-white-2 {
		background-color: #001543;
		margin-bottom: 0;
	}

	.new-hero-2 h1.hero-top-line-2 {
		color: #fff;
	}

	.new-hero-2 .hero-line-3 {
		display: none;
	}
}

/* --- Service Tabs: the stack's rail-and-pane sibling ------------------------
   glacial/home-service-tabs replaced the sticky scrolling stack on the
   homepage 2026-09-08 (owner request: "tabs on the left, content on the
   right"). The two blocks hold the same children and transform into each
   other, so this is a second SKIN for the same content, not a fork of it:
   the pills keep the export's own `.services-holder-main` / `.services-list`
   classes and every rule that hangs off them (49% paired lists, `:only-child`
   full width, the `:has(> p)` copy column, the ≤479 stack). What is new is the
   two-column frame, the rail, and a photo well sized for a pane instead of a
   half-page panel. The rail is label-only: the stack's "01…08" numbers were
   dropped on owner request 2026-09-08, so no CSS counter appears below either.

   Geometry echoes the export's own containers rather than inventing spacing:
   the band is `.services-holder`'s navy, and both children are `.wrap`
   (90% / max 1600px / centered). The pane's slate is the exact treatment the
   export gave every even panel — white under a `--color-3` (75% navy) wash —
   so the rail reads as the darker chrome around a lighter card.

   ⚠ `.w-tabs` IS the grid. Webflow's tabs module reads `.w-tab-menu` and
   `.w-tab-content` as its direct children (and the links/panes as theirs), so
   neither side can be wrapped for layout. Its two clearfix pseudo-elements
   would land in the first grid cell, so they are switched off.
   ⚠ Nothing here carries a `data-w-id`. A scroll reveal cannot fire inside a
   pane that starts `display: none`, and the IX2 initial-state rules below
   would strand such an image at `opacity: 0` for good. */
/* Equal padding top and bottom (owner direction 2026-09-08) — unlike
   `.services-holder`, whose 5% bottom padding was there to give the sticky
   stack somewhere to unstick. */
.gl-svc-tabs {
	background-color: var(--color-2);
	padding-top: clamp(30px, 4vw, 60px);
	padding-bottom: clamp(30px, 4vw, 60px);
}

.gl-svc-tabs__intro,
.gl-svc-tabs__w {
	width: 90%;                /* = .wrap (webflow.css:774) */
	max-width: 1600px;
	margin-left: auto;
	margin-right: auto;
}

.gl-svc-tabs__intro {
	color: var(--color);
	text-align: center;
	margin-bottom: clamp(24px, 3vw, 44px);
}

.gl-svc-tabs__heading {
	color: var(--color);
}

.gl-svc-tabs__w {
	display: grid;
	grid-template-columns: minmax(200px, 290px) minmax(0, 1fr);
	gap: clamp(20px, 2.5vw, 44px);
	align-items: start;
}

.gl-svc-tabs__w:before,
.gl-svc-tabs__w:after {
	display: none;             /* components.css:1737 clearfix, as grid items */
}

/* --- The rail --------------------------------------------------------------
   Sticky at the offset the export used for the first sticky panel (120px), so
   a long pane scrolls past a rail that stays reachable. */
.gl-svc-tabs__menu {
	display: flex;
	flex-flow: column;
	position: sticky;
	top: 130px;
}

/* Every declaration here restates one of components.css's `.w-tab-link`
   defaults (grey pill, inline-block, 9px 30px) — hence the parent class on the
   selector: `.w-tab-link.w--current` is (0,2,0) and would otherwise win. */
.gl-svc-tabs__menu .gl-svc-tab {
	display: flex;
	align-items: center;
	background-color: transparent;
	border-left: 3px solid transparent;
	color: var(--color);
	padding: 14px 16px;
	text-align: left;
	text-decoration: none;
	transition: background-color .2s ease-in-out, border-color .2s ease-in-out;
}

/* Dividers BETWEEN items only, so the strip has no dangling last rule and the
   mobile layout is free to use border-bottom for the active marker. */
.gl-svc-tabs__menu .gl-svc-tab + .gl-svc-tab {
	border-top: 1px solid #ffffff26;   /* = .doc-patient-link's divider */
}

.gl-svc-tabs__menu .gl-svc-tab:hover {
	background-color: #ffffff0f;
	border-left-color: var(--color-7);
}

.gl-svc-tabs__menu .gl-svc-tab.w--current {
	background-color: var(--color);
	background-image: linear-gradient(to bottom, var(--color-3), var(--color-3));
	border-left-color: var(--color-6);
}

/* components.css:1766 zeroes the focus ring on .w-tab-link. */
.gl-svc-tabs__menu .gl-svc-tab:focus-visible {
	outline: 2px solid var(--color-6);
	outline-offset: -2px;
}

.gl-svc-tab__label {
	font-family: trajan-sans-pro, sans-serif;
	font-size: 1.05em;
	line-height: 1.25em;
}

/* --- The pane -------------------------------------------------------------- */
.gl-svc-tabs__content {
	min-width: 0;              /* grid child: let the pills wrap, not overflow */
}

.gl-svc-pane {
	background-color: var(--color);
	background-image: linear-gradient(to bottom, var(--color-3), var(--color-3));
	padding: clamp(22px, 2.4vw, 40px);
}

.gl-svc-pane__head {
	border-bottom: 2px solid var(--color-7);
	margin-bottom: clamp(18px, 2vw, 28px);
	padding-bottom: clamp(12px, 1.4vw, 18px);
}

/* h3 is navy at 1.3em in webflow.css; on the pane it is the panel title the
   stack rendered as .sticky-title-txt (white Trajan 2em) — a real heading now
   that the number no longer sits beside it. */
.gl-svc-pane__title {
	color: var(--color);
	font-family: trajan-sans-pro, sans-serif;
	font-size: clamp(1.5em, 2.2vw, 2em);
	font-weight: 400;
	line-height: 1.1em;
	margin: 0;
}

/* The well is a SHARE of the pane, not a flat width: the copy has to hold two
   pill columns wide enough not to wrap "Squamous Cell Carcinoma", and a fixed
   400px well ate that at 1440. 34% keeps the pills at the width the sticky
   stack gave them (~320px each from 1600 up) and grows the photo on wider
   screens; 260px is the floor where a 7:5 photo still reads. */
.gl-svc-pane__body {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(260px, 34%);
	gap: clamp(20px, 2.4vw, 40px);
	align-items: start;
}

.gl-svc-pane__body--wide {
	grid-template-columns: minmax(0, 1fr);
}

.gl-svc-pane__body > .services-holder-main {
	min-width: 0;
}

/* The pane's optional CTA (2026-09-17): the Skin Care Products and
   Dermatopathology panes are a paragraph with no pills, so they had no way out
   to their own page. render.php puts it INSIDE .services-holder-main — the
   body is a two-column grid and a third child would become a third grid item —
   so it is given its own full-width row and the holder is told to wrap. A pane
   that holds two 49% pill lists therefore keeps them side by side and drops the
   button underneath, rather than squeezing three items onto one flex line.

   ⚠ The `:has()` guard matters: .services-holder-main is shared verbatim with
   the retired sticky stack, so an unconditional `flex-wrap` would change panels
   that have no CTA at all. */
.services-holder-main:has(> .gl-svc-pane__cta) {
	flex-wrap: wrap;
}

.gl-svc-pane__cta {
	width: 100%;
	margin-top: clamp(16px, 1.6vw, 24px);
}

/* `.button` is navy-on-transparent and would vanish on the pane's wash, so the
   CTA is the export's `.rev` variant (gold border, white label). Its hover,
   however, fills with `--color-6` and leaves the label `--color` — white on the
   brand gold is ~2.4:1 and fails SC 1.4.3. Navy on that same gold is ~7.3:1, so
   the label flips instead of the fill being weakened.

   ⚠ Scoped to the pane on purpose. `.button.rev:hover` is the export's own rule
   and is shared with the Instagram CTA further down the homepage; correcting it
   globally is a separate, wider change. */
.gl-svc-pane__cta .button.rev:hover,
.gl-svc-pane__cta .button.rev:focus-visible {
	color: var(--color-2);
}

/* --- The pills: the pane is an EVEN panel ----------------------------------
   The export hides each pill's arrow at rest by painting it the SAME colour as
   the panel behind it, then reveals it when hover fills the pill (that is what
   the pill's `padding-left: 45px` on hover makes room for). So the icon is a
   fact about the background, and the pane wears the even panel's wash — which
   makes `icons8-right-arrow-1.svg` (#404f73, the wash) correct here and the
   base `icons8-right-arrow.svg` (#001543, the navy panel) a visible smudge
   behind the label. Same reasoning as the `:nth-of-type(even)` rules the
   sticky stack derives above; this is the pane's copy of them.
   `.doc-patient-link.purple`'s third declaration, `width: auto`, is left out:
   in a block-level list it renders identically to the base `width: 100%`, and
   the ≤991 `:only-child` rules that DO set a width are more specific anyway. */
.gl-svc-pane .doc-patient-link {
	background-image: url('../../images/icons8-right-arrow-1.svg');
}

.gl-svc-pane .doc-patient-link:hover {
	background-color: var(--color);
	color: var(--color-3);
}

/* --- The photo well -------------------------------------------------------
   The export's `.img-div._48` is a 48%-of-panel float with `.hide`; a pane
   needs a fixed well instead. Single photo takes the library's own 7:5; the
   collage keeps the export's arrangement (two stacked, one tall beside them)
   in a square, placed by slot class so a missing middle photo cannot promote
   the tall one out of its area. */
.gl-svc-pane__media {
	display: grid;
	gap: 10px;
}

.gl-svc-pane__media > .gl-svc-pane__img {
	aspect-ratio: 7 / 5;
}

.gl-svc-pane__img {
	overflow: hidden;
}

.gl-svc-pane__img > img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.gl-svc-pane__media--collage {
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr 1fr;
	aspect-ratio: 1 / 1;
}

.gl-svc-pane__media--collage > .gl-svc-pane__img {
	aspect-ratio: auto;
}

.gl-svc-pane__media--collage > .gl-svc-pane__img--1 { grid-area: 1 / 1 / 2 / 2; }
.gl-svc-pane__media--collage > .gl-svc-pane__img--2 { grid-area: 2 / 1 / 3 / 2; }
.gl-svc-pane__media--collage > .gl-svc-pane__img--3 { grid-area: 1 / 2 / 3 / 3; }

/* Between 1400 and 992 the pane is too narrow to hold two pill columns AND a
   photo, so the photo drops under the copy as a band (the collage as a row of
   three) and the pills keep their pairing. The threshold is arithmetic, not
   taste: copy = 90vw − rail − gaps − pane padding − well, and it crosses the
   ~500px two-column minimum at about 1400. */
@media screen and (max-width: 1399px) {
	.gl-svc-pane__body {
		grid-template-columns: minmax(0, 1fr);
	}

	.gl-svc-pane__media > .gl-svc-pane__img {
		aspect-ratio: 21 / 9;
	}

	.gl-svc-pane__media--collage {
		grid-template-columns: repeat(3, 1fr);
		grid-template-rows: auto;
		aspect-ratio: auto;
	}

	.gl-svc-pane__media--collage > .gl-svc-pane__img,
	.gl-svc-pane__media--collage > .gl-svc-pane__img--1,
	.gl-svc-pane__media--collage > .gl-svc-pane__img--2,
	.gl-svc-pane__media--collage > .gl-svc-pane__img--3 {
		aspect-ratio: 1 / 1;
		grid-area: auto;
	}
}

/* ≤991 the rail lies down into a scrollable strip above the pane, and the
   photos drop out entirely — which is what the stack did too (`.hide` is
   display:none from 991 down), so mobile stays a fast list of links. The
   editor keeps its pickers regardless: a narrow canvas is not a phone. */
@media screen and (max-width: 991px) {
	.gl-svc-tabs__w {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.gl-svc-tabs__menu {
		flex-flow: row;
		position: static;
		border-bottom: 1px solid #ffffff26;
		margin-bottom: 20px;
		overflow-x: auto;
		scroll-snap-type: x proximity;
		-webkit-overflow-scrolling: touch;
	}

	.gl-svc-tabs__menu .gl-svc-tab {
		border-bottom: 3px solid transparent;
		border-left: 0;
		flex: 0 0 auto;
		padding: 12px 14px;
		scroll-snap-align: start;
	}

	.gl-svc-tabs__menu .gl-svc-tab + .gl-svc-tab {
		border-top: 0;
	}

	.gl-svc-tabs__menu .gl-svc-tab:hover,
	.gl-svc-tabs__menu .gl-svc-tab.w--current {
		background-color: #ffffff14;
		background-image: none;
		border-bottom-color: var(--color-6);
	}

	.gl-svc-pane:not(.gl-svc-pane--editor) .gl-svc-pane__media {
		display: none;
	}

	.gl-svc-pane:not(.gl-svc-pane--editor) .gl-svc-pane__body {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* --- Webflow IX2 initial state ----------------------------------------------
   Webflow prints these in <head> so animated elements start hidden until the
   IX2 runtime adds .w-mod-ix to <html> and takes over; the theme never carried
   them across, so every reveal on the homepage flashed fully visible for a
   frame. Copied from webflow/index.html:10, same @media guard (mobile keeps
   everything visible), minus d03b9c21-… which no interaction in webflow.js
   ever targets. Scoped to body.home: an inner page that reuses one of these
   blocks emits the same ids under a different data-wf-page, where IX2 might
   never release them. Known trade-off: if the GSAP/ScrollTrigger CDN fails,
   these stay hidden — the standard Webflow failure mode. */
@media (min-width: 992px) {
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="74cdc493-60c5-8abd-0201-951a60f68ac5"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="579bd58b-819f-2cd4-5841-8e39a00fdf62"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="04b7b8d4-8306-64f0-5b79-0029723a983d"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="04b7b8d4-8306-64f0-5b79-0029723a983f"] {
		filter: grayscale(100%);
	}

	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="ee185414-7b1c-5cfc-594e-b753e1bff80a"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="9543251d-71d8-0f47-78df-2c4212014116"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="c224ab32-b91a-649d-6282-487794951d61"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="e73bfc67-aa0a-e66b-8ee9-2cf771bbec59"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="bae88024-ef50-ae01-8224-bfd37fbf0719"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="df839ec5-71de-86ec-3936-e97dcd0f0dce"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="7a83f499-11b1-d706-9ca7-d33081b9197a"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="6b221fb8-d350-e01c-8f54-661a19e99ddb"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="fcddf5bb-67bb-4711-0d82-ebd889bdbee4"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="04b7b8d4-8306-64f0-5b79-0029723a9830"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="0e0b9bf4-af61-701f-df65-be00d47ffa4e"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="7facdda0-c0a2-eea9-df48-36621eee54b5"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="a804f6d9-34c4-22b9-2dfe-8bde13e185c6"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="8fc33a42-56b0-c170-69f7-602ca9682ada"],
	html.w-mod-js:not(.w-mod-ix) body.home [data-w-id="6f93cfdd-023d-d530-f315-3ba40c3eb99e"] {
		opacity: 0;
	}
}

/* --- Editor canvas ----------------------------------------------------------
   webflow.js does not run in the editor iframe, so the sticky stack, the
   Webflow slider and the hero's viewport-height sizing would render as a heap.
   Flatten them into a readable, editable column; the front end is untouched. */
.editor-styles-wrapper .services-holder,
.editor-styles-wrapper .services-holder > .sticky-service-section {
	position: static;
	max-height: none;
	overflow: visible;
}

.editor-styles-wrapper .services-holder > .spacer,
.editor-styles-wrapper .services-holder > .abs-service {
	position: static;
}

.editor-styles-wrapper .services-holder > .spacer {
	display: none;
}

.editor-styles-wrapper .w-slider {
	height: auto;
	background: transparent;
}

.editor-styles-wrapper .w-slider-mask {
	overflow: visible;
}

.editor-styles-wrapper .w-slide {
	display: block;
	height: auto;
	margin-bottom: 1rem;
}

.editor-styles-wrapper .left-arrow,
.editor-styles-wrapper .right-arrow,
.editor-styles-wrapper .slide-nav {
	display: none;
}

.editor-styles-wrapper .new-hero-2 {
	margin-top: 0;
	height: auto;
	min-height: 480px;
}

/* glacial/home-service-tabs in the canvas: the rail and the pane switching are
   webflow.js's job, so edit() renders no .w-tabs markup at all — the panes
   stack, all of them editable, each already wearing its front-end pane look
   from .gl-svc-pane above. Only the editor-only chrome needs styling. */
.gl-svc-tabs__editor-panes {
	display: grid;
	gap: 16px;
	width: 90%;
	max-width: 1600px;
	margin-left: auto;
	margin-right: auto;
}

.gl-svc-tabs__editor-note {
	color: #ffffffa6;
	font-size: .8em;
	line-height: 1.4em;
	text-align: center;
	width: 90%;
	margin: 0 auto clamp(16px, 2vw, 24px);
}

.gl-svc-pane__img-picker {
	background-color: #ffffff26;
	border: 1px dashed #ffffff59;
	color: var(--color);
	cursor: pointer;
	font: inherit;
	width: 100%;
	min-height: 130px;
	height: 100%;
}

/* ---------------------------------------------------------------------------
 * glacial/product-item — optional brand-page link (`url` attr, 2026-09-09).
 * The photo anchor is display:contents so a linked card lays out exactly like
 * an unlinked one (the .img-div flex/height rules keep acting on the <img>);
 * it is aria-hidden + tabindex=-1 because the photo alt is usually empty and
 * the name link already names the destination. Every rule is (0,2,1) so it
 * beats style.css's `.entry a` (0,2,0) regardless of stylesheet order.
 * ------------------------------------------------------------------------- */
.new-skin-div a.product-img-link {
	display: contents;
}

.new-skin-div .product-title a {
	color: inherit;
	text-decoration: none;
}

.new-skin-div .product-title a:hover,
.new-skin-div .product-title a:focus-visible {
	color: var(--color-6);
	text-decoration: underline;
}

.new-skin-div a.product-more,
.new-skin-div span.product-more {
	display: block;
	width: max-content;
	margin: 4px auto 16px;
	color: var(--color-2);
	font-weight: 700;
	text-decoration: underline;
}

.new-skin-div a.product-more:hover,
.new-skin-div a.product-more:focus-visible {
	color: var(--color-6);
}

/* The office names in a product card's "Available at:" bar link to their
   location pages — see includes/gsd/gsd-product-locations.php, which adds the
   anchors at render_block time (the block is static, so its save() can't).

   The bar is Luminous cream (--_luminous---color-4), not the export's gold
   (--color-6, webflow.css:2197; changed 2026-09-22 for /skin-care-products/,
   its only user). Equal specificity, so this file's later load order wins.
   The links sit inside .entry on the templates that wrap content in it, where
   style.css:174 styles `.entry a` at (0,2,0), so every link rule is (0,2,1) to
   win — the same trap .product-more and the provider-booking buttons already
   document. Navy on the cream is ~17:1, so the underline is the affordance and
   hover drops it rather than changing colour (gold on this cream is ~2.5:1
   and fails AA). */
.available-at-div {
	background-color: var(--_luminous---color-4);
	color: var(--color-2);
}

.available-btm a.gsd-avail-link {
	color: var(--color-2);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.available-btm a.gsd-avail-link:hover,
.available-btm a.gsd-avail-link:focus-visible {
	color: var(--color-2);
	text-decoration: none;
}

.available-btm a.gsd-avail-link:focus-visible {
	outline: 2px solid var(--color-2);
	outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   glacial/location-providers — optional intro copy between the heading and
   the provider cards (2026-09-09; the live site's per-office provider bio).
   --------------------------------------------------------------------------- */
.opt-vs-oph-section .gsd-providers-intro {
	max-width: 900px;
	margin: 0 auto;
	text-align: center;
}

.opt-vs-oph-section .gsd-providers-intro p {
	margin-bottom: 1em;
}

.opt-vs-oph-section .gsd-providers-intro .wp-block-buttons {
	justify-content: center;
	margin-top: 1em;
}

/* glacial/location-welcome — two welcome photos (ACF photo + welcome_photo) side by side
   above the map, where the single photo used to sit; they stack on small screens. */
.stat-section .loc-and-map .img-div.gsd-welcome-photos {
	display: flex;
	gap: 16px;
}

.stat-section .loc-and-map .img-div.gsd-welcome-photos .img {
	width: calc(50% - 8px);
	flex: 0 0 calc(50% - 8px);
	height: 100%;
	object-fit: cover;
}

@media (max-width: 767px) {
	.stat-section .loc-and-map .img-div.gsd-welcome-photos {
		flex-direction: column;
	}

	.stat-section .loc-and-map .img-div.gsd-welcome-photos .img {
		width: 100%;
		flex-basis: auto;
	}
}

/* An h3 in the welcome copy (the practice-name line on Mountain View / San Mateo, 2026-09-30).
   webflow.css zeroes h3 margins and the location template has no `.entry` wrapper to give the
   usual 20px (`.entry h3`), so without this the heading sits flush on the paragraph below. */
.wp-block-glacial-location-welcome .txt-div-48 > h3 {
	margin-bottom: 20px;
}

/* The providers band has no top padding of its own (webflow.css zeroes it): on most offices
   the location-ctas block in front of it paints the same tint ~260px up through its absolute
   .austin-bottom-div, and that IS the space above the heading. Anywhere else — first block
   under the hero (Los Altos, mirroring live's spotlight position), or straight after a
   services list (the Roseville Mohs suite, 2026-10-12) — the heading sat flush on whatever
   came before, so it gets its own top padding. 32px floor: 4% is ~16px on a phone. */
.wp-block-glacial-location-providers.opt-vs-oph-section:not(.wp-block-glacial-location-ctas + *) {
	padding-top: max(32px, 4%);
}

/* glacial/location-events + [gsd_location_events] (includes/gsd/gsd-location-events.php):
   an office's upcoming events as a cream band in its location stack. Both print nothing
   when no event is coming up, so the band never shows empty. Cards are the events
   plugin's list cards (events.css, loaded in the editor iframe too); only the frame is
   set here, which is why it lives in this file rather than style.css. The cream is the
   grid's lum-cream; the cards' grey date line (#5a6270) stays ~5.8:1 on it. */
.gsd-location-events {
	padding: clamp(40px, 5vw, 72px) 5%;
	background-color: #fcf5e9;
}

.gsd-location-events__wrap {
	max-width: 960px;
	margin: 0 auto;
}

.gsd-location-events .gsd-event-card:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

/* "See All Events" — the house .button (Book Online's look), centred under the
   events. Its trailing 10px margins would push it off centre. */
.gsd-location-events__all {
	margin: clamp(28px, 3vw, 40px) 0 0;
	text-align: center;
}

.gsd-location-events__all .button {
	margin: 0;
}

/* --- Cards layout (gsd-events/event-tile.php) --------------------------------
   White cards with a gold top rule on the cream band. Columns are capped at
   340px and centred, so one event is one card in the middle rather than a
   stretched slab or a card stranded on the left. Icons are the site's existing
   set (gsd_location_events_icon()), all decorative and navy; the badge repeats
   the date row, so it is aria-hidden. Colours on white: navy ~16:1, #333 ~12:1,
   the muted address #5a6270 ~6.3:1; the badge's gold month on navy is ~7.4:1. */
.gsd-location-events--cards .gsd-location-events__wrap {
	max-width: 1140px;
}

.gsd-location-events__tiles {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 340px));
	justify-content: center;
	gap: 24px;
	margin-top: clamp(24px, 3vw, 36px);
}

.gsd-event-tile {
	display: flex;
	flex-direction: column;
	min-width: 0;
	background-color: #fff;
	border-top: 4px solid var(--color-6, #d29f13);
	box-shadow: 0 1px 2px rgba(0, 21, 67, 0.08), 0 8px 24px rgba(0, 21, 67, 0.08);
}

.gsd-event-tile__media {
	display: block;
	aspect-ratio: 16 / 9;
	overflow: hidden;
}

.gsd-event-tile__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.gsd-event-tile__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 16px;
	padding: 24px;
}

.gsd-event-tile__head {
	display: flex;
	align-items: flex-start;
	gap: 16px;
}

.gsd-event-tile__badge {
	flex: 0 0 60px;
	margin: 0;
	padding: 9px 0 10px;
	background-color: var(--color-2, #001543);
	color: #fff;
	line-height: 1;
	text-align: center;
}

.gsd-event-tile__badge-month {
	display: block;
	color: var(--color-6, #d29f13);
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.gsd-event-tile__badge-day {
	display: block;
	margin-top: 5px;
	font-size: 28px;
	font-weight: 600;
}

/* webflow.css's h3 is trajan at 1.4em with zero margins; keep the face, set the size. */
.gsd-event-tile__title {
	margin: 0;
	font-size: 1.25rem;
	line-height: 1.3;
}

.gsd-event-tile__title a {
	color: var(--color-2, #001543);
	text-decoration: none;
}

.gsd-event-tile__title a:hover,
.gsd-event-tile__title a:focus-visible {
	text-decoration: underline;
}

.gsd-event-tile__facts {
	display: grid;
	gap: 8px;
	margin: 0;
	padding: 0;
	color: #333;
	font-size: 15px;
	line-height: 1.4;
	list-style: none;
}

.gsd-event-tile__facts li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 0;
	padding: 0;
}

.gsd-event-tile__icon {
	flex: 0 0 18px;
	width: 18px;
	height: 18px;
	margin-top: 1px;
	color: var(--color-2, #001543);
}

/* The repeat line's ↻ is a glyph, not an SVG — no repeat icon exists in the set. */
.gsd-event-tile__icon--repeat {
	font-size: 18px;
	line-height: 18px;
	text-align: center;
}

.gsd-event-tile__place,
.gsd-event-tile__address {
	display: block;
}

.gsd-event-tile__place {
	font-weight: 600;
}

.gsd-event-tile__address {
	color: #5a6270;
	font-size: 14px;
}

.gsd-event-tile__excerpt {
	margin: 0;
	color: #333;
	font-size: 15px;
	line-height: 1.5;
}

/* Pinned to the card's floor, so a row of cards lines up whatever the copy. */
.gsd-event-tile__more {
	margin: auto 0 0;
	padding-top: 4px;
}

.gsd-event-tile__more a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	color: var(--color-2, #001543);
	font-weight: 600;
	text-decoration: none;
}

.gsd-event-tile__more a:hover,
.gsd-event-tile__more a:focus-visible {
	text-decoration: underline;
}

.gsd-event-tile__more .gsd-event-tile__icon {
	flex-basis: 16px;
	width: 16px;
	height: 16px;
	margin-top: 0;
	transition: transform 0.2s;
}

.gsd-event-tile__more a:hover .gsd-event-tile__icon {
	transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
	.gsd-event-tile__more .gsd-event-tile__icon {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
 * glacial/location-insurances — cap the band, and keep every carrier visible.
 *
 * All three rules are scoped to the block, because `.cta`, `.cta-wrap` and
 * `.cta-column.hide-outer` are shared with the other CTA-shaped blocks.
 *
 * 1. WIDTH. The section had no cap at all: `.cta-wrap` is a bare `width: 80%`,
 *    unlike the house `.wrap` (`width: 90%; max-width: 1600px`) every sibling
 *    location section uses. On a 2560px screen that put the navy card at
 *    1843px — WIDER than the 1600px its neighbours cap at — with the cut-out
 *    photo alone 865px. Capping the section at the theme's own content token
 *    lands the card at ~1190px, i.e. inset from the neighbours again, and
 *    close to what a 1440px screen already showed.
 *
 * 2. LIST COLUMNS. `.insurances` was two hard 49% columns at every width, so
 *    narrowing the band squeezes the names: measured 161px per column at
 *    1024px and 95px at 320px, where "United Health Care (includes UMR)" wraps
 *    three lines. Auto-fit grid keeps two columns while they can hold ~170px
 *    and drops to one below that instead of crushing them. render.php splits
 *    the rows into two alphabetical halves, so a single column still reads A→Z
 *    top to bottom — no PHP change needed, and the editor preview (same
 *    classes in index.js) gets it too.
 *
 * 3. ⚠ THE PHOTO WAS COVERING THE END OF THE LIST. Between 480px and 991px
 *    webflow.css takes the photo column out of flow (`position: absolute;
 *    inset: auto 0% 0% auto`) and clears it with a FIXED
 *    `padding-bottom: 450px` on `.inner-cta-div.insur`. But the photo's height
 *    is 49% of the card width times its aspect ratio, which passes 450px as
 *    soon as the card is wider than ~780px: measured 528px at a 900px
 *    viewport, where it sat on top of the last two carriers of Manteca's
 *    24-row list. A fixed reserve can never track a fluid photo, so the photo
 *    goes back in flow — still last and still right-aligned, via `order` and
 *    `margin-left: auto` — and the card sizes itself around it. Below 480px the block above already hides
 *    the photo and zeroes the reserve, so that band is untouched.
 * ------------------------------------------------------------------------ */
.wp-block-glacial-location-insurances {
	max-width: var(--gl-max-width, 1650px);
	margin-left: auto;
	margin-right: auto;
}

.wp-block-glacial-location-insurances .insurances {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
	column-gap: 2%;
}

.wp-block-glacial-location-insurances .insurance-list {
	width: auto;
}

/*
 * Side-by-side band: the cut-out photo takes a flat 49% of the card, so on a
 * 1024-1200px screen the list was left 161-190px per column — enough to wrap
 * "First Choice (Meritage Medical Network)" (the longest of the 89 carriers)
 * over three lines. A floor on the text column makes the photo, which is
 * decorative, give up the difference instead. It only bites below ~1200px;
 * at the capped width the columns still land on the design's 49/48 split.
 */
@media (min-width: 992px) {
	.wp-block-glacial-location-insurances .cta-column.txt.insur {
		min-width: 420px;
	}
}

@media (min-width: 480px) and (max-width: 991px) {
	.wp-block-glacial-location-insurances .inner-cta-div.insur {
		padding-bottom: 20px;
	}

	.wp-block-glacial-location-insurances .cta-column.hide-outer {
		position: static;
		order: 2;
		width: 49%;
		margin-left: auto;
	}
}

/* ------------------------------------------------------------------------
   glacial/home-affiliates — the logo marquee as a CSS animation (2026-09-09).

   The export animated `.marquee` with an IX2 "marquee" interaction (slide both
   halves left by 100%, snap back, loop). That engine offers no pause hook, and
   WCAG 2.2.2 (Level A) requires one for auto-moving content, so the halves are
   `.gsd-marquee` now (a class IX2 does not target) and the same movement is a
   keyframe. Rules mirror webflow.css `.marquee`. Speed = --gsd-marquee-seconds,
   set by js/gsd-pause-controls.js from GSD_AFFILIATE_SCROLL_SECONDS.
   ------------------------------------------------------------------------ */
.gsd-marquee {
	justify-content: space-around;
	width: 50%;
	margin-right: 0;
	padding-right: 0;
	display: flex;
	animation: gsd-marquee var(--gsd-marquee-seconds, 60s) linear infinite;
	will-change: transform;
}

@keyframes gsd-marquee {
	from { transform: translateX(0); }
	to   { transform: translateX(-100%); }
}

/* The pause scope is the .affiliates <section> (data-gsd-pause-scope); js/gsd-pause-controls.js
   toggles the class and the data attribute on it. */
.gsd-marquee-paused .gsd-marquee {
	animation-play-state: paused;
}

/* No JS needed for the AAA half: reduced-motion users get a still strip unless they
   press Play (the script then stamps data-gsd-motion="on" on the scope). */
@media (prefers-reduced-motion: reduce) {
	[data-gsd-pause-scope]:not([data-gsd-motion="on"]) .gsd-marquee {
		animation-play-state: paused;
	}
}

/* Swipeable on touch (2026-09-17, owner request: "any way to have the marquee
   swipable"). On a coarse pointer the strip stops being an auto-marquee and
   becomes an ordinary horizontal scroller you drag with a finger.

   ⚠ The two CANNOT run together. `.logo-scroll` is the viewport and the halves
   inside it are being translated by a keyframe, so making that box scrollable
   while the animation runs means the scroll offset and the transform fight each
   other — you swipe, and the content jumps out from under your finger. So this
   is a SWAP, not an addition: `animation: none` is the first thing it does.

   Structure has to change with it. `.logo-container` is `width: 200%` and each
   `.gsd-marquee` is `50%` of that — geometry for a thing that translates by
   exactly one half. A scroller instead wants `max-content` so the two halves
   lay out as one continuous row of all eleven logos, and items that keep their
   own width instead of taking 14% of a percentage-sized parent.

   Kept: the grayscale and .49 opacity on `.logo-blocks` (those live in
   webflow.css and are not geometry), and the desktop marquee, untouched.

   ⚠ The pause button is hidden here, and that is correct rather than a
   regression: WCAG 2.2.2 asks for a control over content that moves
   automatically, and on these devices nothing does. Leaving it would be a
   control that pauses nothing.

   ⚠ No `tabindex` on the scroller. A keyboard-reachable scroll container (2.1.1)
   would need markup, and markup cannot be media-queried — every desktop visitor
   would get a focus stop on a box that does not scroll. Nothing in the strip is
   focusable or interactive (the logos are plain <img>, not links) and no content
   is lost, so there is nothing a keyboard user cannot reach. */
@media (hover: none) and (pointer: coarse) {
	.logo-scroll {
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x proximity;
	}

	.logo-container {
		width: max-content;
		gap: 24px;
	}

	.gsd-marquee {
		animation: none;
		width: auto;
		gap: 24px;
	}

	.logo-blocks {
		flex: 0 0 auto;
		width: clamp(120px, 38vw, 170px);
		scroll-snap-align: center;
	}

	/* Nothing moves on its own here, so the control has nothing to control.

	   ⚠ (0,3,0) on purpose. css/gsd-pause-controls.css prints AFTER this file (it is
	   enqueued at render time by gsd_pause_button(), while this goes out on
	   enqueue_block_assets), and its ≤767px rule re-declares `display: inline-flex` on
	   `.affiliates > .gsd-pause` — (0,2,0), the same as a two-class hide, so on source
	   order the button came BACK on every phone: the exact devices this query is for.
	   A media query adds no specificity. The scope attribute is already on the section,
	   so naming it outranks that rule without !important. */
	.affiliates[data-gsd-pause-scope] .gsd-pause {
		display: none;
	}
}

/* … and the section has to grow its own bottom padding to replace it.

   `.affiliates` is `padding-bottom: 0%` in webflow.css at EVERY breakpoint, so below
   767px the button WAS the section's bottom spacing: css/gsd-pause-controls.css drops it
   into the flow there (`position: static; margin: 12px auto 0`) at a 36px min-height, so
   the strip sat 48px clear of whatever follows. Hiding it closed that gap to nothing.
   Above 767px the button is absolute (`top: 16px; right: 5%`) and contributed no flow
   height, which is why this restores the 48px only where it was actually lost.

   ⚠ Both conditions are needed. Touch alone would pad a coarse-pointer TABLET that
   never had the gap; ≤767px alone would pad a desktop window merely narrowed to phone
   width, where the button is still in the flow — that one would get both. */
@media (hover: none) and (pointer: coarse) and (max-width: 767px) {
	.affiliates {
		padding-bottom: 48px;
	}
}

/* ------------------------------------------------------------------------
   glacial/home-press — the homepage "In the Media" carousel (2026-09-30),
   between For Patients and "Care That Starts With Listening".
   The header row is latest-posts' (.wrap.flex.blog: 80% wide, 90% <=991,
   stacking <=479); the rail is glacial/slider's track and arrows, restyled
   here as cards. Everything is scoped under .gsd-press / .gsd-press__rail,
   so the gallery block is untouched.
   ------------------------------------------------------------------------ */
.gsd-press {
	padding-top: clamp(24px, 3vw, 48px);
	padding-bottom: clamp(8px, 1vw, 16px); /* .service-section below brings its own 4% */
}

/* The kicker borrows .h3-gold but is a <p> above the h2 (an h3 there puts the
   outline at h2 -> h3 -> h2), so it carries what webflow.css's `h3` would have
   given it. #94700d, not .h3-gold's 50%-alpha gold (~1.6:1 on white): 4.6:1.
   Same treatment as .gsd-provider-intro__eyebrow in gsd-provider-tabs.css. */
.gsd-press .gsd-press__kicker {
	margin-top: 0;
	font-family: trajan-sans-pro, sans-serif;
	font-weight: 400;
	line-height: 1.2em;
	color: #94700d;
}

.gsd-press__rail.gl-slider {
	width: 80%;
	margin-top: 36px;
	margin-bottom: 0;
}

/* The track is a scroll container, so it clips anything outside its padding
   box — including a card's focus ring. 6px of padding cancelled by -6px of
   margin gives the ring room without moving the cards off the header's edge. */
.gsd-press__rail.gl-slider .gl-slider-track {
	gap: 24px;
	margin: -6px;
	padding: 6px 6px 14px;
	scroll-padding-inline: 6px;
}

.gsd-press__rail.gl-slider .gl-slider-slide {
	flex: 0 0 calc((100% - 72px) / 4);
}

/* normalize.css's `[hidden] { display: none }` is (0,1,0) and loses to the
   gallery's `.gl-slider .gl-slider-arrow { display: flex }`, so the attribute
   view.js toggles would hide nothing. */
.gsd-press__rail.gl-slider .gl-slider-arrow[hidden] {
	display: none;
}

/* (0,2,1): `.entry a` (style.css:174) is (0,2,0). */
.gsd-press a.gsd-press__card {
	display: flex;
	flex-direction: column;
	height: 100%;
	color: var(--color-2);
	text-decoration: none;
}

.gsd-press a.gsd-press__card:focus-visible {
	outline: 2px solid var(--color-2);
	outline-offset: 2px;
}

.gsd-press .gsd-press__media {
	aspect-ratio: 4 / 5; /* the press graphics' own shape; landscape photos crop to centre */
	overflow: hidden;
	background-color: var(--color-9);
}

.gsd-press .gsd-press__photo {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.4s ease;
}

.gsd-press a.gsd-press__card:hover .gsd-press__photo {
	transform: scale(1.04);
}

.gsd-press .gsd-press__body {
	padding-top: 16px;
}

.gsd-press .gsd-press__outlet {
	margin: 0 0 6px;
	font-family: trajan-sans-pro, sans-serif;
	font-size: 0.8em;
	line-height: 1.3;
	letter-spacing: 3px;
	text-transform: uppercase;
	color: #94700d; /* 4.6:1 on white */
}

/* Body face, not the h3's Trajan: these are 60–140 character headlines. Three
   lines, then an ellipsis; the full text stays in the DOM for the link name. */
.gsd-press .gsd-press__headline {
	margin: 0;
	font-family: inherit;
	font-size: 1em;
	font-weight: 500;
	line-height: 1.35;
	color: var(--color-2);
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
}

.gsd-press a.gsd-press__card:hover .gsd-press__headline {
	text-decoration: underline;
}

.gsd-press .gsd-press__who {
	margin: 0 0 8px; /* under the outlet, above the headline (2026-10-06) */
	font-size: 0.85em;
	color: #555; /* 7.5:1 */
}

/* The "Featuring" pill in place of the who line (2026-10-06) — the blog cards'
   chip (style.css, "Featuring pill on blog cards"), recoloured for a WHITE card:
   the base rules are written for navy, where the type is 72% white (invisible
   here) and the label 85% gold (~2:1 on white). Square, no avatar border, like
   the other two. Unlinked: the card is the link.
   The provider Blog / Media tab cards (.gsd-provider-tabs__posts, 2026-10-12) are
   white too and share these colours; their spacing is in css/gsd-provider-tabs.css. */
.gsd-press .gsd-card-featured {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0 0 10px; /* between the outlet line and the headline */
}

.gsd-press .gsd-post-featured__pill,
.gsd-provider-tabs__posts .gsd-post-featured__pill {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	max-width: 100%;
	padding: 0 12px 0 0;
	border: 1px solid rgba(148, 112, 13, 0.4);
	border-radius: 0;
	background: #fff;
}

.gsd-press .gsd-post-featured__avatar,
.gsd-provider-tabs__posts .gsd-post-featured__avatar {
	width: 36px;
	height: 36px;
}

.gsd-press .gsd-post-featured__label,
.gsd-provider-tabs__posts .gsd-post-featured__label {
	color: #94700d; /* 4.6:1 on white, same as the outlet line */
	font-size: 10px;
}

.gsd-press .gsd-post-featured__name,
.gsd-provider-tabs__posts .gsd-post-featured__name {
	font-size: 14px;
	color: var(--color-2);
}

.gsd-press .gsd-post-featured__type,
.gsd-provider-tabs__posts .gsd-post-featured__type {
	color: #555; /* 7.5:1 */
}

/* Arrows sit in the 10% side margin on desktop instead of over the cards.
   At 992px that margin is 99px and the arrow reaches 62px into it. */
@media screen and (min-width: 992px) {
	.gsd-press__rail.gl-slider .gl-slider-prev { left: -62px; }
	.gsd-press__rail.gl-slider .gl-slider-next { right: -62px; }
}

@media screen and (max-width: 991px) {
	.gsd-press__rail.gl-slider {
		width: 90%;
	}

	.gsd-press__rail.gl-slider .gl-slider-slide {
		flex-basis: calc((100% - 48px) / 2.5);
	}
}

/* One card and a peek of the next, so the strip reads as swipeable. */
@media screen and (max-width: 767px) {
	.gsd-press__rail.gl-slider {
		margin-top: 24px;
	}

	.gsd-press__rail.gl-slider .gl-slider-slide {
		flex-basis: 80%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.gsd-press .gsd-press__photo {
		transition: none;
	}

	.gsd-press a.gsd-press__card:hover .gsd-press__photo {
		transform: none;
	}
}

/* glacial/home-hero — the kicker is the homepage <h1> (2026-09-09). webflow.css styles the
   class (Trajan, 3em, weight 400, centred) exactly as it did the export's <div>; the only thing
   the element swap adds is normalize.css's `h1 { margin: .67em 0 }`, zeroed here so the hero
   renders byte-for-byte as before. Font-size stays with the class rule (it outranks `h1`). */
h1.hero-top-line-2 {
	margin: 0;
	/* Four words over two lines: without this the browser fills line 1 and drops
	   a single orphan onto line 2. `balance` is progressive enhancement — an
	   older engine simply wraps greedily, as it did before. (2026-09-16) */
	text-wrap: balance;
}

/* Hero headings promoted to <h1> via the blocks' headingLevel attribute (2026-09-09).
   /esthetician-services/ (glacial/lum-hero) and /cosmetics/ (glacial/lum-video-hero)
   had no h1. The class rules already carry the look; these only cancel what the
   element swap would otherwise change. */

/* lum-hero: .ip-header was a <div> (no top margin). normalize.css gives h1 a .67em
   top margin; the class already sets margin-bottom, so only the top needs zeroing. */
h1.ip-header {
	margin-top: 0;
}

/* lum-video-hero: .h2-lum only sets colour; the type came from webflow.css's `h2`
   element rule, repeated here for the h1 (including its two breakpoints). */
h1.h2-lum {
	margin-top: 0;
	margin-bottom: 20px;
	font-family: trajan-sans-pro, sans-serif;
	font-size: 2.5em;
	font-weight: 400;
	line-height: 1.2em;
}

@media screen and (max-width: 767px) {
	h1.h2-lum {
		font-size: 2em;
	}
}

@media screen and (max-width: 479px) {
	h1.h2-lum {
		font-size: 1.8em;
	}
}

/* Wistia's web-component player inside the Webflow ratio box (2026-09-15).
   components.css absolutely positions `iframe, object, embed` inside .w-video —
   a custom element matches none of those, so a <wistia-player> dropped into the
   ratio wrapper would stack UNDER the padding-top box instead of filling it.
   This mirrors that rule for the element. Applies to both blocks that emit the
   wrapper: glacial/lum-video-hero (the /cosmetics/ hero) and glacial/service-row. */
.w-video wistia-player {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}
