/*!
 * Gather Grove — Frontend Styles
 * Version: 0.1.0
 *
 * All classes use the .gg- prefix. Colors are exposed as CSS custom
 * properties so themes and Elementor's color system can override them.
 */

:root {

	/* ── Brand colour cascade (canonical --gg-color-* / --gg-type-* vocabulary)
	   ────────────────────────────────────────────────────────────────────────
	   Widget CSS authors directly against the categorized --gg-color-* and
	   --gg-type-* names — the canonical vocabulary shared with the sibling
	   plugins (Forms, Chat, Notion Sync) and emitted by core Brand\Palettes
	   compose-mode. The short flat names (--gg-primary, --gg-primary-dark,
	   --gg-accent, …) and the categorized aliases that bridged them were
	   retired in the token-vocabulary convergence (ADR 0001 payload 3c
	   follow-on b); per-placement palettes now recolour widgets through this
	   single vocabulary, so the core include_flat dual-emit is gone.

	   Each brand colour resolves:
	     studio override (Frontend::inject_style_defaults, rule 132)
	       → --gg-brand-* Elementor 4 Variable (rule 150)
	         → Elementor classic global (--e-global-color-*)
	           → hardcoded .io fallback (matches BrandSettings::FIELDS)
	   A real hardcoded fallback ends every chain so a --gg-color-* can never
	   resolve to nothing (the v0.7.161 scar: the old flat↔categorized aliases
	   were circular, so a missing chain link computed to the guaranteed-invalid
	   value → the property collapsed to transparent, e.g. an "invisible"
	   Book/Enroll button). Note `primary_dark` was Booking's historical flat
	   name for the SECONDARY brand colour → --gg-color-secondary here. */
	--gg-color-primary:    var(--gg-brand-primary,    var(--e-global-color-primary,   #254032));
	--gg-color-secondary:  var(--gg-brand-secondary,  var(--e-global-color-secondary, #8eb18c));
	--gg-color-accent:     var(--gg-brand-accent,     var(--e-global-color-accent,    #c4a484));
	--gg-color-text:       var(--gg-brand-text,       var(--e-global-color-text,      #2c2a26));

	/* Muted text — no brand Variable in the 7-Variable set; keeps its
	   Elementor custom-color id with a hardcoded fallback. */
	--gg-color-text-muted: var(--e-global-color-5fd1781, #6b675f);

	/* Widget / card background (Elementor custom-color id 9fd23bd). */
	--gg-color-background: var(--gg-brand-background, var(--e-global-color-9fd23bd,   #fefaf7));

	/* Functional colors — no Elementor global equivalent; hardcoded
	   .io palette, still overridable via the Brand tab (advanced group). */
	--gg-color-border:     #e8e3d8;
	--gg-color-success:    #4a7c4a;
	--gg-color-error:      #b04646;
	--gg-color-warning:    #c98828;

	/* ── Typography families (canonical --gg-type-* vocabulary)
	   ─────────────────────────────────────────────────────────
	   Brand Variable → Elementor global typography → system stack.
	   The system stack lives OUTSIDE the brand/Elementor var() so an
	   unloaded brand family can never drop to serif. */
	--gg-type-body:    var(--gg-brand-font-body, var(--e-global-typography-text-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif));
	--gg-type-heading: var(--gg-brand-font-heading, var(--e-global-typography-primary-font-family, inherit));

	/* Surface intentionally NOT aliased to --gg-color-background — cards
	   on the page need visual contrast against the page background.
	   Defaults to white per the canonical core tokens.css. Studios
	   can override via theme CSS or a future Studio Style surface
	   setting. */
	/* stylelint-disable-next-line color-no-hex */
	--gg-color-surface:        #ffffff;

	/* Semantic soft tints + info/muted — fixed functional colours (no brand
	   cascade), mirrored from the canonical tokens.css. Previously undefined in
	   this inline :root, so .gg-badge--success/error/warning/neutral/membership
	   rendered with no background; defining them here makes every badge variant
	   resolve (v0.7.164). */
	/* stylelint-disable color-no-hex */
	--gg-color-success-soft:   #e8efe5;
	--gg-color-warning-soft:   #fbf0d9;
	--gg-color-error-soft:     #f7e0e0;
	--gg-color-info:           #527591;
	--gg-color-info-soft:      #e2eaf1;
	--gg-color-muted:          #8a857a;
	--gg-color-muted-soft:     #ebe8e0;
	/* stylelint-enable color-no-hex */

	/* Typography sizes (new primitives) */
	--gg-type-size-xs:    0.75rem;     /* 12px */
	--gg-type-size-sm:    0.875rem;    /* 14px */
	--gg-type-size-md:    1rem;        /* 16px (base) */
	--gg-type-size-lg:    1.125rem;    /* 18px */
	--gg-type-size-xl:    1.25rem;     /* 20px */
	--gg-type-size-2xl:   1.5rem;      /* 24px */
	--gg-type-size-3xl:   2rem;        /* 32px */
	--gg-type-size-4xl:   2.5rem;      /* 40px */

	/* Typography weights */
	--gg-type-weight-regular: 400;
	--gg-type-weight-medium:  500;
	--gg-type-weight-bold:    600;

	/* Typography line heights */
	--gg-type-leading-tight:    1.2;
	--gg-type-leading-snug:     1.4;
	--gg-type-leading-normal:   1.55;
	--gg-type-leading-relaxed:  1.75;

	/* Spacing — 4px scale */
	--gg-space-1:   0.25rem;   /*   4px */
	--gg-space-2:   0.5rem;    /*   8px */
	--gg-space-3:   0.75rem;   /*  12px */
	--gg-space-4:   1rem;      /*  16px */
	--gg-space-5:   1.5rem;    /*  24px */
	--gg-space-6:   2rem;      /*  32px */
	--gg-space-7:   3rem;      /*  48px */
	--gg-space-8:   4rem;      /*  64px */

	/* Radius */
	--gg-radius-sm:    4px;
	--gg-radius-md:    8px;
	--gg-radius-lg:   16px;
	--gg-radius-xl:   24px;
	--gg-radius-pill: 999px;

	/* Shadow */
	--gg-shadow-sm:   0 1px 2px  rgba(28, 26, 22, 0.05);
	--gg-shadow-md:   0 4px 12px rgba(28, 26, 22, 0.08);
	--gg-shadow-lg:   0 8px 32px rgba(28, 26, 22, 0.12);

	/* Motion */
	--gg-duration-fast:   150ms;
	--gg-duration-base:   250ms;
	--gg-duration-slow:   400ms;
	--gg-ease-out:        cubic-bezier(0.16, 1, 0.3, 1);
	--gg-ease-in:         cubic-bezier(0.7, 0, 0.84, 0);
	--gg-ease-in-out:     cubic-bezier(0.4, 0, 0.2, 1);

	/* ── PR 4 foundation primitives ─────────────────────────────────────
	   Container styling pass (v0.7.95). Net-new tokens; existing widgets
	   don't consume them yet — per-widget walkthrough rolls each widget
	   onto these tokens as part of the visual QC pass. */

	/* Fluid type — clamp(min, ideal, max). Scales smoothly across
	   viewports without breakpoint jumps. Min anchors mobile, max
	   anchors desktop. Use these in place of static rem values for
	   headings + body to get modern responsive typography. */
	--gg-fluid-h1:   clamp(2rem,    1.4rem  + 3vw,    3.5rem);
	--gg-fluid-h2:   clamp(1.5rem,  1.1rem  + 2vw,    2.5rem);
	--gg-fluid-h3:   clamp(1.25rem, 1rem    + 1.25vw, 1.75rem);
	--gg-fluid-h4:   clamp(1.125rem, 1rem   + 0.625vw, 1.375rem);
	--gg-fluid-body: clamp(1rem,    0.95rem + 0.25vw, 1.0625rem);

	/* Section padding — responsive padding-block for `.gg-page-section`
	   wrappers and any container that needs to breathe with the
	   viewport. Min (mobile) is generous-but-tight, max (desktop) opens
	   up for the modern airy feel. */
	--gg-section-padding-block:  clamp(3rem, 6vw, 6rem);
	--gg-section-padding-inline: clamp(1rem, 4vw, 2.5rem);

	/* Text measure — caps prose containers at a comfortable reading
	   width. 65ch is the sweet spot; widen for media-heavy widgets,
	   tighten for headlines. */
	--gg-color-text-measure: 65ch;

	/* Touch target — WCAG 2.5.5 minimum for primary interactive
	   elements. Apply via min-height to buttons, large select boxes,
	   and clickable cards. */
	--gg-touch-target: 44px;

	/* Hover lift — magnitude of the card-elevation transform. Wrapped
	   in a var so reduced-motion users get a zero-distance lift
	   (`@media` block below sets it to 0). */
	--gg-hover-lift: -2px;

	/* Widget content cap — applied to .gg-booking-widget-inner so
	   widgets self-cap + center inside whatever container Elementor
	   gives them. 64rem (1024px) is the modern SaaS-standard content
	   width; comfortable for forms + content widgets, leaves margin on
	   wider screens. Override per-widget by setting --gg-widget-max-width
	   on the parent Elementor column (e.g. `none` for grid-heavy
	   widgets that need to fill, or 80rem for dashboard layouts). */
	--gg-widget-max-width: 64rem;
}

/* Honor user reduced-motion preference per the canonical core tokens.
   Also zeroes the card hover-lift distance — translateY animations
   are exactly the motion these users want suppressed. */
@media (prefers-reduced-motion: reduce) {
	:root {
		--gg-duration-fast:   0ms;
		--gg-duration-base:   0ms;
		--gg-duration-slow:   0ms;
		--gg-hover-lift:      0;
	}
}

/* ----------------------------------------------------------------------- */
/* Base reset                                                              */
/* ----------------------------------------------------------------------- */

.gg-booking-schedule,
.gg-booking-booking-form-wrapper,
.gg-booking-dashboard,
.gg-booking-package-shop {
	box-sizing: border-box;
	color: var(--gg-color-text);
	font-family: inherit;
}

/* border-box so a full-width child (e.g. the package buy button at width:100%)
   sits inside its container's padding instead of overflowing — its own padding
   + border are included in the width. PackageShop was missing from this reset,
   so its buy buttons bled past the card edges on the default (stretched)
   alignment (v0.7.166). */
.gg-booking-schedule *,
.gg-booking-booking-form-wrapper *,
.gg-booking-dashboard *,
.gg-booking-package-shop * {
	box-sizing: border-box;
}

/* ----------------------------------------------------------------------- */
/* Buttons                                                                 */
/* ----------------------------------------------------------------------- */

.gg-booking-btn {
	/* inline-flex + center on both axes so the label stays centered no matter
	   how tall the button gets — flex parents (popover footer flex:1, list
	   action column, card actions) can stretch an inline-block button and pin
	   its text to the top. Centering here at the shared base class fixes every
	   GG widget's buttons (live AND editor preview) in one place. */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 10px 18px;
	border: 1px solid transparent;
	border-radius: 4px;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

/* Double-class selectors (.gg-booking-btn.gg-booking-btn--primary) rather than a
   single class, to raise specificity to (0,2,0). The Elementor editor canvas
   injects a low-specificity baseline style on native <a>/<button> elements (the
   e_atomic_elements experiment) that resolves to the studio's *accent* global —
   which beat our old single-class (0,1,0) rule and painted Book buttons with the
   accent colour in the editor preview only (live was always correct). The bump
   makes our brand colours win in the canvas too, without !important and without
   scoping to .gg-booking-widget-inner (that would miss the body-mounted popover
   button). Studio Kit overrides still win — their selectors are {{WRAPPER}}-scoped
   and higher still. Shared base class → fixes every widget's buttons at once. */
.gg-booking-btn.gg-booking-btn--primary {
	background-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

/* Editor force-state preview: an ancestor .gg-force-{hover|focus|selected}
   class (added to a widget's inner root only in the Elementor editor, via the
   "Preview: Interactive State" control) makes descendants show that state's
   look WITHOUT real interaction. We pair it on the BASE button/field rules
   here so the beautiful-by-default hover/focus previews too — not just
   studio-set control overrides. Inert on the live page (the class is never
   emitted there). Kit control overrides out-specify these (~0,4,0). */
.gg-booking-btn.gg-booking-btn--primary:hover,
.gg-booking-btn.gg-booking-btn--primary:focus,
.gg-force-hover .gg-booking-btn.gg-booking-btn--primary {
	background-color: var(--gg-color-secondary);
	color: var(--gg-color-surface);
}

.gg-booking-btn.gg-booking-btn--secondary {
	background-color: transparent;
	color: var(--gg-color-primary);
	border-color: var(--gg-color-primary);
}

.gg-booking-btn.gg-booking-btn--secondary:hover,
.gg-booking-btn.gg-booking-btn--secondary:focus,
.gg-force-hover .gg-booking-btn.gg-booking-btn--secondary {
	background-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

.gg-booking-btn--full {
	display: flex;
	width: 100%;
}

.gg-booking-btn[disabled],
.gg-booking-btn:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

/* ----------------------------------------------------------------------- */
/* Schedule                                                                */
/* ----------------------------------------------------------------------- */

.gg-booking-schedule {
	background-color: transparent;
}

.gg-booking-schedule__empty {
	padding: 24px;
	text-align: center;
	color: var(--gg-color-text-muted);
}

.gg-booking-schedule-filters {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	align-items: flex-end;
	margin-bottom: 20px;
}

.gg-booking-schedule-filters__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 13px;
}

.gg-booking-schedule-filters__field span {
	color: var(--gg-color-text-muted);
}

.gg-booking-schedule-filters__field select,
.gg-booking-schedule-filters__search {
	box-sizing: border-box;
	padding: 8px 10px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	background-color: var(--gg-color-background);
	color: var(--gg-color-text);
	/* Match the dropdowns and the search box to each other by default: same
	   inherited font + line-height so they render at the same size + height
	   (a <select> and an <input> otherwise pick different UA fonts/metrics). */
	font: inherit;
	line-height: 1.4;
	min-width: 160px;
}

/* Free-text search input (D1). Shares the field chrome above; a touch wider,
   and the type="search" UA appearance is reset so our border/radius/background
   render identically to the dropdowns (WebKit otherwise insets + rounds it). */
.gg-booking-schedule-filters__search {
	min-width: 200px;
	-webkit-appearance: none;
	appearance: none;
}

.gg-booking-schedule-grid {
	display: grid;
	gap: 16px;
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.gg-booking-schedule-card {
	position: relative;
	display: flex;
	background-color: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	overflow: hidden;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.gg-booking-schedule-card__color-strip {
	width: var( --gg-color-strip-width, 6px );
	flex-shrink: 0;
	background-color: var(--gg-color-primary);
	display: var( --gg-color-strip-display, block );
}

/* List view's left-edge color strip is implemented as a border-left on
   the row. Width + visibility vars below let the studio control both
   from the Class Color Strip Style section. The inline style attribute
   in render_list_item is now `border-left-color: <class color>` only
   (not the full `border-left:` shorthand) so these vars don't get
   overridden — matches the cards strip pattern. */
.gg-booking-sessions-list__item {
	border-left-style: var( --gg-color-strip-display, solid );
	border-left-width: var( --gg-color-strip-width, 4px );
}

.gg-booking-schedule-card__body {
	flex: 1;
	padding: 16px 18px;
}

.gg-booking-schedule-card__title {
	margin: 0 0 6px;
	font-size: 18px;
	line-height: 1.3;
}

.gg-booking-schedule-card__title a {
	color: inherit;
	text-decoration: none;
}

.gg-booking-schedule-card__title a:hover {
	text-decoration: underline;
}

.gg-booking-schedule-card__meta {
	margin-bottom: 10px;
	font-size: 14px;
	color: var(--gg-color-text-muted);
	line-height: 1.5;
}

.gg-booking-schedule-card__instructor {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 4px;
}

.gg-booking-schedule-card__instructor-photo {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	object-fit: cover;
}

.gg-booking-schedule-card__instructor a,
.gg-booking-schedule-card__location a,
.gg-booking-class-card__instructor a {
	color: inherit;
	text-decoration: none;
}

.gg-booking-schedule-card__instructor a:hover,
.gg-booking-schedule-card__location a:hover,
.gg-booking-class-card__instructor a:hover {
	text-decoration: underline;
	color: var(--gg-color-primary);
}

.gg-booking-schedule-card__capacity {
	display: inline-block;
	margin-bottom: 10px;
	padding: 3px 10px;
	border-radius: 12px;
	background-color: var(--gg-color-success-soft);
	color: var(--gg-color-success);
	font-size: 12px;
	font-weight: 600;
}

.gg-booking-schedule-card__capacity--full {
	background-color: var(--gg-color-error-soft);
	color: var(--gg-color-error);
}

.gg-booking-schedule-card__price {
	margin-bottom: 12px;
	font-size: 16px;
	font-weight: 600;
	color: var(--gg-color-text);
}

.gg-booking-schedule-card__actions {
	margin-top: 12px;
}

.gg-booking-schedule-pagination {
	margin-top: 24px;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	justify-content: center;
}

.gg-booking-schedule-pagination__page {
	display: inline-block;
	min-width: 32px;
	padding: 6px 10px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	color: var(--gg-color-text);
	text-decoration: none;
	text-align: center;
	line-height: 1.2;
}

.gg-booking-schedule-pagination__page.is-active {
	background-color: var(--gg-color-primary);
	border-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

/* Prev / Next arrows — same chip, slightly heavier glyph. */
.gg-booking-schedule-pagination__nav {
	font-weight: 700;
}

/* Ellipsis bridging skipped pages — text only, no chip. */
.gg-booking-schedule-pagination__gap {
	display: inline-flex;
	align-items: flex-end;
	min-width: 16px;
	padding: 6px 2px;
	color: var(--gg-color-text-muted);
	text-align: center;
}

/* ----------------------------------------------------------------------- */
/* Booking form                                                            */
/* ----------------------------------------------------------------------- */

/* Honeypot — off-screen rather than display:none so unsophisticated bots
 * still fill it. Paired with server-side rejection in
 * BookingsController::create_booking() on a non-empty gg_check param. */
.gg-booking-hp {
	position: absolute !important;
	left: -9999px !important;
	top: -9999px !important;
	width: 1px !important;
	height: 1px !important;
	opacity: 0 !important;
	pointer-events: none !important;
}

.gg-booking-booking-form-wrapper {
	max-width: 560px;
}

.gg-booking-booking-form {
	display: flex;
	flex-direction: column;
	padding: 24px;
	background-color: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	border-radius: 8px;
}

.gg-booking-booking-form__title {
	margin: 0 0 16px;
	font-size: 22px;
}

.gg-booking-booking-form__summary {
	padding: 14px 16px;
	margin-bottom: 18px;
	/* Neutral "here's your booking" card — NOT a success state. Palette-tinted
	   (the chosen palette's soft tint, so the modal harmonises with the widget)
	   with a brand-neutral fallback for Inherit. Was --gg-color-success-soft,
	   which read fixed green under any brand. */
	background-color: var(--gg-color-primary-soft, var(--gg-color-muted-soft));
	border-left: 3px solid var(--gg-color-primary);
	border-radius: 4px;
	font-size: 14px;
	line-height: 1.5;
}

.gg-booking-booking-form__field {
	margin-bottom: 14px;
}

.gg-booking-booking-form__row--names {
	display: flex;
	gap: 12px;
}

.gg-booking-booking-form__row--names .gg-booking-booking-form__field {
	flex: 1;
}

/* --- Booking form inside GGModal (modal-host) ---------------------------- */
/* The booking form fetched into GGModal: the DIALOG is the single styleable card
   — its chrome comes from the widget's paired card-chrome controls
   (`.gg-modal.gg-booking-booking-modal …`, set in BookingFormWidget). Strip the
   form card's OWN chrome inside the modal so it doesn't double the dialog AND so
   the body content lines up with GGModal's header (title + close) at the shared
   24px padding. Anchored on `.gg-modal__body` (ALWAYS present) NOT
   `.elementor-element` — so it fires whether or not a BookingForm modal-host
   exists on the page (no host → the form renders raw inside the body, keeping its
   base 24px padding, which left the title outdented). (0,4,0) still beats the
   per-instance styleScope rule (`.elementor-element.elementor-element-{id}
   .gg-booking-booking-form` = 0,3,0) in the host case, with no !important.
   Mirrors the LoginWidget v1.1.62 stripper (css ~4739). */
.gg-modal .gg-modal__body .gg-booking-booking-form-wrapper .gg-booking-booking-form {
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	box-shadow: none;
}

.gg-modal .gg-modal__body .gg-booking-booking-form-wrapper {
	max-width: none;
}

/* Enrollment panel inside GGModal (enrollment popup, v1.1.68) — same treatment
   as the booking form above. An enrollment-mode session's booking-form fragment
   short-circuits to .gg-booking-enrollment-panel, which carries its OWN card
   chrome (bg/border/radius/padding). Inside the modal the DIALOG is the single
   styleable card (skinned by the BookingForm widget's card-chrome controls on
   .gg-modal.gg-booking-booking-modal), so strip the panel's own chrome + width
   cap — otherwise it double-cards the dialog and the widget's modal styling
   never shows through. The panel's inner elements (header divider, price row,
   open-enrollment note, Enroll button) keep their own styling. (0,4,0) beats the
   per-instance styleScope rule with no !important; mirrors the .gg-booking-form
   stripper above. */
.gg-modal .gg-modal__body .gg-booking-booking-form-wrapper .gg-booking-enrollment-panel {
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	box-shadow: none;
	max-width: none;
}

/* Defensive: the fragment already suppresses the form title server-side
   (show_title='' in default_form_settings) and GGModal's header shows the class
   name — this guards against a duplicate title if that fragment default changes. */
.gg-modal .gg-booking-booking-form__title {
	display: none;
}

/* The enrollment panel renders its own class-name title in its header, which
   duplicates the GGModal header title inside the modal. Hide just the title and
   keep the subtitle ("N-session course") as the lone header line — the session
   count stays visible without repeating the class name. */
.gg-modal .gg-booking-enrollment-panel__title {
	display: none;
}

/* Stack first/last name on phones (incl. the GGModal bottom-sheet). Placed after
   the base `__row--names` flex rule per rule 117 (media queries add no
   specificity, so they must follow the base they override). */
@media (max-width: 767px) {
	.gg-booking-booking-form__row--names {
		flex-direction: column;
		gap: 0;
	}
}

.gg-booking-booking-form__field--checkbox label {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
}

.gg-booking-booking-form__label {
	display: block;
	margin-bottom: 4px;
	font-size: 13px;
	font-weight: 600;
	color: var(--gg-color-text);
}

.gg-booking-booking-form__input {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	background-color: var(--gg-color-background);
	font-size: 14px;
	color: var(--gg-color-text);
}

.gg-booking-booking-form__input:focus,
.gg-force-focus .gg-booking-booking-form__input {
	outline: none;
	border-color: var(--gg-color-primary);
	/* Default focus ring tracks the Brand primary (rule 46 token cascade). The
	   rgba line is the fallback for browsers without color-mix; the color-mix
	   line wins where supported and follows the studio's brand. Studios can
	   replace this entirely via the Field Focus State → Focus Box Shadow control. */
	box-shadow: 0 0 0 3px rgba(92, 122, 92, 0.15);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--gg-color-primary) 20%, transparent);
}

.gg-booking-booking-form__input--card {
	padding: 12px;
}

.gg-booking-booking-form__errors {
	margin-top: 6px;
	font-size: 13px;
	color: var(--gg-color-error);
}

.gg-booking-booking-form__submit {
	/* Base cross-axis position so an auto-width button doesn't stretch to
	   fill the flex column; the Element Alignment > Submit Button control
	   overrides align-self. A full-width button (width:100%) fills
	   regardless, so alignment gracefully no-ops there. */
	align-self: flex-start;
	margin-top: 8px;
	padding: 12px 20px;
	border: none;
	border-radius: 4px;
	background-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
	font-size: 15px;
	font-weight: 600;
	cursor: pointer;
}

.gg-booking-booking-form__submit:hover,
.gg-force-hover .gg-booking-booking-form__submit {
	background-color: var(--gg-color-secondary);
}

.gg-booking-booking-form__feedback {
	margin-top: 14px;
	font-size: 14px;
}

/* ----------------------------------------------------------------------- */
/* Dashboard                                                               */
/* ----------------------------------------------------------------------- */

/* No max-width here — width is governed by the Widget Frame's dashboard-family
   per-type cap on .gg-booking-widget-inner (rule 122). The old hard 760px cap
   fought the Frame (blocked full-bleed + killed Alignment above the cap, same
   bug InstructorDashboard had); removed v1.1.65 so the Frame is the single
   width+placement authority, matching every other widget. */

.gg-booking-dashboard__section + .gg-booking-dashboard__section {
	margin-top: 32px;
}

.gg-booking-dashboard__section-title {
	margin: 0 0 14px;
	padding-bottom: 6px;
	border-bottom: 1px solid var(--gg-color-border);
	font-size: 18px;
	color: var(--gg-color-text);
}

.gg-booking-dashboard__empty {
	color: var(--gg-color-text-muted);
	font-style: italic;
}

.gg-booking-dashboard__booking-card {
	display: flex;
	flex-wrap: wrap;
	/* Card Content alignment control (ClientDashboardWidget) drives these
	   vars; unset = the space-between / left default below. */
	justify-content: var(--gg-dash-card-justify, space-between);
	text-align: var(--gg-dash-card-text-align, left);
	align-items: center;
	gap: 12px;
	padding: 14px 16px;
	margin-bottom: 10px;
	background-color: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	font-size: 14px;
	line-height: 1.5;
}

.gg-booking-dashboard__booking-meta {
	flex: 1 1 60%;
	min-width: 180px;
}

.gg-booking-dashboard__booking-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.gg-booking-dashboard__booking-actions .gg-booking-btn {
	padding: 6px 12px;
	font-size: 13px;
}

.gg-booking-dashboard--login {
	padding: 28px;
	text-align: center;
	/* Neutral logged-out prompt — palette-tinted with a neutral fallback (was
	   fixed success-green). */
	background-color: var(--gg-color-primary-soft, var(--gg-color-muted-soft));
	border-radius: 8px;
}

.gg-booking-dashboard__greeting {
	margin-bottom: 24px;
}

.gg-booking-dashboard__client-name {
	font-size: 22px;
	font-weight: 700;
	color: var(--gg-color-text);
	margin: 0;
}

/* ----------------------------------------------------------------------- */
/* Badges                                                                  */
/* ----------------------------------------------------------------------- */

.gg-badge {
	display: inline-block;
	padding: 3px 10px;
	border-radius: 12px;
	font-size: 12px;
	font-weight: 600;
	background-color: var(--gg-color-muted-soft);
	color: var(--gg-color-text-muted);
}

.gg-badge--success {
	background-color: var(--gg-color-success-soft);
	color: var(--gg-color-success);
}

.gg-badge--error {
	background-color: var(--gg-color-error-soft);
	color: var(--gg-color-error);
}

.gg-badge--warning {
	background-color: var(--gg-color-warning-soft);
	color: var(--gg-color-warning);
}

.gg-badge--neutral {
	background-color: var(--gg-color-muted-soft);
	color: var(--gg-color-text-muted);
}

.gg-badge--membership {
	background: var(--gg-color-info-soft);
	color: var(--gg-color-info);
	display: inline-block;
	padding: 3px 12px;
	border-radius: 12px;
	font-size: 12px;
	font-weight: 600;
}

/* ----------------------------------------------------------------------- */
/* Notices & spinner                                                       */
/* ----------------------------------------------------------------------- */

.gg-booking-notice {
	padding: 12px 16px;
	margin-bottom: 14px;
	border-left: 4px solid var(--gg-color-text-muted);
	background-color: var(--gg-color-muted-soft);
	font-size: 14px;
}

.gg-booking-notice--success {
	border-color: var(--gg-color-success);
	background-color: var(--gg-color-success-soft);
	color: var(--gg-color-success);
}

.gg-booking-notice--error {
	border-color: var(--gg-color-error);
	background-color: var(--gg-color-error-soft);
	color: var(--gg-color-error);
}

.gg-booking-notice--warning {
	border-color: var(--gg-color-warning);
	background-color: var(--gg-color-warning-soft);
	color: var(--gg-color-warning);
}

.gg-booking-spinner {
	display: inline-block;
	width: 16px;
	height: 16px;
	border: 2px solid currentColor;
	border-right-color: transparent;
	border-radius: 50%;
	animation: gg-booking-spin 0.7s linear infinite;
}

@keyframes gg-booking-spin {
	to { transform: rotate(360deg); }
}

/* ----------------------------------------------------------------------- */
/* Editor placeholder                                                      */
/* ----------------------------------------------------------------------- */

.gg-booking-editor-placeholder,
.gg-booking-editor-placeholder__header {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 14px;
	padding: 12px 16px;
	background-color: var(--gg-color-success-soft);
	border-radius: 6px;
	font-weight: 600;
	color: var(--gg-color-text);
}

.gg-booking-editor-placeholder__icon {
	font-size: 18px;
	color: var(--gg-color-primary);
}

/* ----------------------------------------------------------------------- */
/* Class Discovery widget (Discovery arc D2)                               */
/* ----------------------------------------------------------------------- */

/* The bar stacks: a full-width search row on top, then the facets row. */
.gg-booking-discovery-filters {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin-bottom: 20px;
}

.gg-booking-discovery-filters__search-row {
	width: 100%;
}

.gg-booking-discovery-filters__search-row .gg-booking-discovery-filters__field--search {
	width: 100%;
}

.gg-booking-discovery-filters__search-row .gg-booking-discovery-filters__search {
	width: 100%;
	min-width: 0;
}

.gg-booking-discovery-filters__facets {
	display: flex;
	flex-wrap: wrap;
	gap: 16px;
	align-items: flex-end;
}

.gg-booking-discovery-filters__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 13px;
}

.gg-booking-discovery-filters__field > span {
	color: var(--gg-color-text-muted);
}

.gg-booking-discovery-filters__field select,
.gg-booking-discovery-filters__search {
	box-sizing: border-box;
	padding: 8px 10px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	background-color: var(--gg-color-background);
	color: var(--gg-color-text);
	font: inherit;
	line-height: 1.4;
	min-width: 180px;
}

.gg-booking-discovery-filters__search {
	-webkit-appearance: none;
	appearance: none;
}

/* Facet tag pills — a calm, uniform cloud (the colored badges live on the
   cards, not the filters). Selected state is a filled accent; styling is
   overridable via the Tag Pills button controls (button class #3). */
.gg-booking-discovery-pills {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
}

.gg-booking-discovery-pill {
	display: inline-flex;
	align-items: center;
	padding: 5px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 999px;
	background-color: transparent;
	color: var(--gg-color-text);
	font-size: 13px;
	line-height: 1.3;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s, border-color 0.15s, color 0.15s;
}

.gg-booking-discovery-pill:hover {
	border-color: var(--gg-color-primary);
	color: var(--gg-color-primary);
}

.gg-booking-discovery-pill.is-active {
	background-color: var(--gg-color-primary);
	border-color: var(--gg-color-primary);
	color: #fff;
}

/* True tag cloud — every tag merged, alphabetical, sized by class count (the
   inline font-size from the renderer). Reuses the pill chrome so the Tag Pills
   style controls skin it; only the size is data-driven. */
.gg-booking-discovery-cloud {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 10px;
	align-items: baseline;
}

.gg-booking-discovery-pill--cloud {
	line-height: 1.2;
}

.gg-booking-discovery-cloud__clear {
	display: inline-flex;
	align-items: center;
	align-self: center;
	padding: 4px 8px;
	font-size: 13px;
	color: var(--gg-color-text-muted);
	text-decoration: underline;
	cursor: pointer;
}

.gg-booking-discovery-cloud__clear:hover {
	color: var(--gg-color-primary);
}

/* Editor placeholder image box — give the sized placeholder a visible fill
   (the real <img> covers it on the live front end). */
.gg-booking-class-card__img--placeholder {
	background-color: var(--gg-color-border);
}

/* Accessibility utility — used by the hidden filter submit + search label so
   no-JS / screen-reader visitors can still apply filters. Mirrors WP core's. */
.gg-booking-discovery .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	border: 0;
	white-space: nowrap;
}

.gg-booking-discovery-grid {
	display: grid;
	gap: 16px;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

.gg-booking-discovery-results {
	transition: opacity 0.15s;
}

.gg-booking-discovery__empty {
	padding: 24px 0;
	color: var(--gg-color-text-muted);
	text-align: center;
}

.gg-booking-discovery__pagination {
	display: flex;
	justify-content: center;
	gap: 12px;
	margin-top: 20px;
}

.gg-booking-discovery__page-link {
	display: inline-flex;
	align-items: center;
	padding: 8px 16px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	color: var(--gg-color-text);
	text-decoration: none;
}

.gg-booking-discovery__page-link:hover {
	border-color: var(--gg-color-primary);
	color: var(--gg-color-primary);
}

/* ----------------------------------------------------------------------- */
/* Responsive                                                              */
/* ----------------------------------------------------------------------- */

@media (max-width: 767px) {
	/* Schedule card grid collapse is handled by the Columns control's
	   mobile_default (rule 117 / GridControls) — the old
	   `.gg-booking-schedule-grid { grid-template-columns: 1fr }` here was dead
	   (the per-instance control out-specifies it) and was removed v1.1.66.
	   Breakpoint normalized 600px → 767px (canonical phone, rule 117). */
	.gg-booking-schedule-filters {
		flex-direction: column;
		align-items: stretch;
	}

	/* Discovery is already a column; stack its facets row too so dropdowns go
	   full-width (pills + cloud wrap naturally). */
	.gg-booking-discovery-filters__facets {
		flex-direction: column;
		align-items: stretch;
	}

	.gg-booking-schedule-filters__field select,
	.gg-booking-schedule-filters__search,
	.gg-booking-discovery-filters__field select,
	.gg-booking-discovery-filters__search {
		min-width: 0;
	}

	.gg-booking-dashboard__booking-card {
		flex-direction: column;
		align-items: flex-start;
	}

	.gg-booking-class-card__body {
		padding: 18px;
	}

	.gg-booking-instructor-profile {
		padding: 20px;
	}
}

/* ----------------------------------------------------------------------- */
/* Class Card widget                                                       */
/* ----------------------------------------------------------------------- */

.gg-booking-class-card {
	background-color: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	border-left: 4px solid var(--gg-color-primary);
	border-radius: 8px;
	overflow: hidden;
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
	box-sizing: border-box;
	color: var(--gg-color-text);
	font-family: inherit;
}

.gg-booking-class-card *,
.gg-booking-class-card *::before,
.gg-booking-class-card *::after {
	box-sizing: border-box;
}

.gg-booking-class-card--empty {
	border-left-color: var(--gg-color-border);
}

.gg-booking-class-card__body {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 24px;
}

.gg-booking-class-card__title {
	margin: 0;
	font-size: 22px;
	line-height: 1.25;
	color: var(--gg-color-text);
}

.gg-booking-class-card__description {
	color: var(--gg-color-text-muted);
	font-size: 14px;
	line-height: 1.55;
}

.gg-booking-class-card__description p {
	margin: 0 0 8px;
}

.gg-booking-class-card__description p:last-child {
	margin-bottom: 0;
}

.gg-booking-class-card__meta {
	color: var(--gg-color-text-muted);
	font-size: 14px;
}

.gg-booking-class-card__instructor {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
	color: var(--gg-color-text);
}

.gg-booking-class-card__instructor-photo {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	object-fit: cover;
}

.gg-booking-class-card__capacity {
	font-size: 13px;
	color: var(--gg-color-success);
	font-weight: 600;
}

.gg-booking-class-card__capacity--full {
	color: var(--gg-color-error);
}

.gg-booking-class-card__price {
	font-size: 18px;
	font-weight: 700;
	/* Brand/palette primary (was --gg-color-secondary, which dropped to the sage
	   secondary default when a studio set only its primary brand colour). */
	color: var(--gg-color-primary);
}

.gg-booking-class-card .gg-booking-btn {
	align-self: flex-start;
	margin-top: 6px;
}

/* ----------------------------------------------------------------------- */
/* Instructor Profile widget                                               */
/* ----------------------------------------------------------------------- */

.gg-booking-instructor-profile {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 14px;
	padding: 28px;
	background-color: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	border-radius: 8px;
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
	box-sizing: border-box;
	color: var(--gg-color-text);
	font-family: inherit;
	text-align: left;
}

.gg-booking-instructor-profile *,
.gg-booking-instructor-profile *::before,
.gg-booking-instructor-profile *::after {
	box-sizing: border-box;
}

.gg-booking-instructor-profile--empty {
	color: var(--gg-color-text-muted);
}

.gg-booking-instructor-profile__photo {
	width: 120px;
	height: 120px;
	overflow: hidden;
	border-radius: 50%;
	flex-shrink: 0;
}

.gg-booking-instructor-profile__photo img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	border-radius: 50%;
}

.gg-booking-instructor-profile__photo-placeholder {
	width: 120px;
	height: 120px;
	display: flex;
	align-items: center;
	justify-content: center;
	/* Neutral avatar fallback — palette-tinted, neutral fallback (was success-green). */
	background-color: var(--gg-color-primary-soft, var(--gg-color-muted-soft));
	color: var(--gg-color-text-muted);
	border-radius: 50%;
	flex-shrink: 0;
}

.gg-booking-instructor-profile__name {
	margin: 0;
	font-size: 22px;
	line-height: 1.25;
	color: var(--gg-color-text);
}

.gg-booking-instructor-profile__bio {
	color: var(--gg-color-text-muted);
	font-size: 14px;
	line-height: 1.6;
	max-width: 60ch;
}

.gg-booking-instructor-profile__bio p {
	margin: 0 0 8px;
}

.gg-booking-instructor-profile__bio p:last-child {
	margin-bottom: 0;
}

.gg-booking-instructor-profile__specialties {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	/* The tag row hugs its content, so align-self (its placement as a flex child
	   of the profile column) is what visibly moves it L/C/R; justify-content only
	   matters if a studio stretches the row full-width. Both read the same var so
	   the Specialties alignment control works in either case. */
	align-self: var( --gg-specialties-align, flex-start );
	justify-content: var( --gg-specialties-align, flex-start );
}

.gg-booking-tag {
	display: inline-block;
	padding: 4px 10px;
	/* Each tag adopts its class's own colour (gg_class_color) via the
	 * --gg-tag-class-color / --gg-tag-class-text custom props set inline per tag
	 * (PackageShop valid-class tags). Falls back to the default soft-success pill
	 * when no per-class colour is supplied. A studio's Elementor "Valid-Class
	 * Tags" background/text override sets the property directly and wins over
	 * this var-based rule. */
	background-color: var(--gg-tag-class-color, var(--gg-color-primary-soft, var(--gg-color-muted-soft)));
	color: var(--gg-tag-class-text, var(--gg-color-primary));
	border-radius: 999px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.4;
}

.gg-booking-instructor-profile__schedule {
	width: 100%;
	display: flex;
	flex-direction: column;
	align-items: var( --gg-upcoming-align, flex-start );
	gap: 8px;
	margin-top: 6px;
}

.gg-booking-instructor-profile__schedule-title {
	margin: 0 0 4px;
	font-size: 16px;
	color: var(--gg-color-text);
}

.gg-booking-instructor-profile__no-classes {
	margin: 0;
	font-size: 13px;
	color: var(--gg-color-text-muted);
}

.gg-booking-instructor-profile__class-item {
	display: flex;
	flex-direction: column;
	align-self: var( --gg-upcoming-align, flex-start );
	gap: 2px;
	padding: 10px 14px;
	/* Neutral upcoming-class row — palette-tinted, neutral fallback (was success-green). */
	background-color: var(--gg-color-primary-soft, var(--gg-color-muted-soft));
	border: 1px solid transparent;
	border-radius: 6px;
	text-align: var( --gg-upcoming-align-text, left );
	width: 100%;
}

.gg-booking-instructor-profile__class-name {
	font-weight: 600;
	color: var(--gg-color-text);
	font-size: 14px;
}

/* Linked upcoming-class name (feedback #9) — inherits the name colour, underline
   on hover so it reads as clickable. */
.gg-booking-instructor-profile__class-name a {
	color: inherit;
	text-decoration: none;
}

.gg-booking-instructor-profile__class-name a:hover {
	color: var(--gg-color-primary, #254032);
	text-decoration: underline;
}

.gg-booking-instructor-profile__class-meta {
	color: var(--gg-color-text-muted);
	font-size: 13px;
}

/* Widget Kit image model (rule 117): wrapper is a non-clipping flex container
   (no overflow:hidden — it would slice the Box Shadow control's output); the
   Alignment control sets justify-content here. The img's own border-radius
   renders cleanly without the wrapper clipping. */
.gg-booking-class-card__image {
	display: flex;
	justify-content: var( --gg-card-image-align, center );
}

/* Beautiful-by-default state matching the Kit's control defaults (16/9 cover at
   full width). img.X specificity (0,1,1) + max-width:none defend against theme
   `img { max-width: 100% }` / `height: auto` resets per the ImageControls
   docblock. The --placeholder pairing lets the editor preview <img> respond to
   the same controls. */
img.gg-booking-class-card__img,
.gg-booking-class-card__img--placeholder {
	display: block;
	max-width: none;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

/* Featured image (Cards / List / Popover) — driven by --gg-{card,list,
   cal-popover}-image-* CSS vars. Model:
     1. Wrapper (.*__image) is a flex container; alignment var = where the
        image sits when size is < 100%.
     2. Image element width = size var.
     3. Aspect ratio var derives the height (default behavior).
     4. Custom height var only applies when aspect-ratio var resolves to
        `auto` (selectors_dictionary maps "custom" → "auto"); otherwise
        aspect-ratio dominates and height var is ignored.
     5. img.gg-*__img selector boost (0,1,1) defends against theme rules
        like `.elementor img { height: auto; }` which were silently
        winning over class-only (0,1,0) rules pre-0.7.10.
   max-width: none keeps a px-based size var working against `img {
   max-width: 100% }` theme resets.
*/

.gg-booking-schedule-card__image {
	display: flex;
	justify-content: var( --gg-card-image-align, center );
	overflow: hidden;
}

img.gg-booking-schedule-card__img {
	display: block;
	width: var( --gg-card-image-size, 100% );
	max-width: none;
	aspect-ratio: var( --gg-card-image-ratio, 16 / 9 );
	height: var( --gg-card-image-height, auto );
	object-fit: var( --gg-card-image-fit, cover );
	object-position: var( --gg-card-image-position, center center );
	border-radius: var( --gg-card-image-radius, 0 );
}

/* List view image — sits at the start of the list row. */
.gg-booking-sessions-list__image {
	display: flex;
	justify-content: var( --gg-list-image-align, center );
	flex-shrink: 0;
	overflow: hidden;
}

img.gg-booking-sessions-list__img {
	display: block;
	width: var( --gg-list-image-size, 80px );
	max-width: none;
	aspect-ratio: var( --gg-list-image-ratio, 1 / 1 );
	height: var( --gg-list-image-height, auto );
	object-fit: var( --gg-list-image-fit, cover );
	object-position: var( --gg-list-image-position, center center );
	border-radius: var( --gg-list-image-radius, 4px );
}

/* List image editor-placeholder pairing — same beautiful-by-default state as
   the live <img> so the Kit ImageControls preview against it. */
.gg-booking-sessions-list__img--placeholder {
	display: block;
	max-width: none;
	width: 80px;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: 4px;
}

/* Sessions Card image — Widget Kit model (non-clipping flex wrapper; the img
   owns its own border-radius). Driven by the card_image_* controls; the
   --placeholder pairing lets the editor preview <img> respond to the same
   controls (rule 117). */
.gg-booking-sessions-card__image {
	display: flex;
	justify-content: var( --gg-card-image-align, center );
}

img.gg-booking-sessions-card__img,
.gg-booking-sessions-card__img--placeholder {
	display: block;
	max-width: none;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	border-radius: 4px 4px 0 0;
}

/* Class Sessions widget */
.gg-booking-class-sessions {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.gg-booking-class-sessions__item {
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 12px;
	border: 1px solid var(--gg-color-border, var(--gg-color-border));
	border-radius: 6px;
	flex-wrap: wrap;
}

.gg-booking-class-sessions__date {
	font-weight: 600;
	min-width: 180px;
}

.gg-booking-class-sessions__meta {
	color: var(--gg-color-text-muted, var(--gg-color-text-muted));
}

.gg-booking-class-sessions__capacity {
	margin-left: auto;
}

/* ----------------------------------------------------------------------- */
/* Sessions List widget                                                    */
/* ----------------------------------------------------------------------- */

.gg-booking-sessions-list {
	display: flex;
	flex-direction: column;
	gap: 0;
}

.gg-booking-sessions-list__item {
	display: flex;
	align-items: center;
	gap: 20px;
	padding: 16px 20px;
	border-bottom: 1px solid var(--gg-color-border);
	background: var(--gg-color-background);
	transition: background 0.15s ease;
}

.gg-booking-sessions-list__item:first-child {
	border-radius: 6px 6px 0 0;
}

.gg-booking-sessions-list__item:last-child {
	border-bottom: none;
	border-radius: 0 0 6px 6px;
}

.gg-booking-sessions-list__item:hover {
	background: var(--gg-surface, var(--gg-color-background));
}

.gg-booking-sessions-list__date-block {
	display: flex;
	flex-direction: column;
	align-items: center;
	min-width: 80px;
	text-align: center;
}

.gg-booking-sessions-list__day {
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-list__date {
	font-size: 18px;
	font-weight: 700;
	color: var(--gg-color-text);
	line-height: 1.2;
}

.gg-booking-sessions-list__time {
	font-size: 13px;
	color: var(--gg-color-primary);
	font-weight: 600;
	margin-top: 2px;
}

.gg-booking-sessions-list__duration {
	font-size: 11px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-list__info {
	flex: 1;
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.gg-booking-sessions-list__class-name a {
	font-weight: 600;
	font-size: 15px;
	color: var(--gg-color-text);
	text-decoration: none;
}

.gg-booking-sessions-list__class-name a:hover {
	color: var(--gg-color-primary);
}

.gg-booking-sessions-list__instructor {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 13px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-list__instructor-photo {
	width: 24px;
	height: 24px;
	border-radius: 50%;
	object-fit: cover;
}

.gg-booking-sessions-list__instructor a,
.gg-booking-sessions-list__location a {
	color: var(--gg-color-text-muted);
	text-decoration: none;
}

.gg-booking-sessions-list__instructor a:hover,
.gg-booking-sessions-list__location a:hover {
	color: var(--gg-color-primary);
}

.gg-booking-sessions-list__location {
	font-size: 13px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-list__badges {
	display: flex;
	gap: 6px;
	flex-wrap: wrap;
	margin-top: 2px;
	justify-content: var( --gg-badges-align, flex-start );
}

.gg-badge--type {
	background: var(--gg-color-primary-light, var(--gg-color-primary-soft, var(--gg-color-muted-soft)));
	color: var(--gg-color-primary);
}

.gg-badge--level {
	background: var(--gg-surface, var(--gg-color-background));
	color: var(--gg-color-text-muted);
	border: 1px solid var(--gg-color-border);
}

/* Course / Enrollment badge (feedback #4) — soft accent tint, brand-driven. */
.gg-badge--course {
	background: color-mix( in srgb, var( --gg-color-accent ) 18%, transparent );
	color: var( --gg-color-accent );
}

/* "N sessions" line on enrollment course cards / list rows (feedback #4). */
.gg-booking-schedule-card__session-count,
.gg-booking-sessions-list__session-count {
	font-size: 0.85em;
	color: var( --gg-color-text-muted, var( --gg-color-text-muted ) );
}

.gg-badge--full {
	background: var(--gg-color-error-soft);
	color: var(--gg-color-error);
}

.gg-badge--cancelled {
	background: var(--gg-color-background);
	color: var(--gg-color-text-muted);
	border: 1px solid var(--gg-color-border);
}

/* Cancelled session visual state */
.gg-booking-session--cancelled {
	opacity: 0.6;
	position: relative;
}

.gg-booking-session--cancelled::after {
	content: '';
	position: absolute;
	inset: 0;
	background: repeating-linear-gradient(
		-45deg,
		transparent,
		transparent 8px,
		rgba( 0, 0, 0, 0.02 ) 8px,
		rgba( 0, 0, 0, 0.02 ) 9px
	);
	pointer-events: none;
	border-radius: inherit;
}

.gg-booking-session--cancelled .gg-booking-schedule-card__color-strip,
.gg-booking-session--cancelled.gg-booking-sessions-list__item {
	border-color: var(--gg-color-text-muted) !important;
}

.gg-booking-session--cancelled .gg-booking-schedule-card__title,
.gg-booking-session--cancelled .gg-booking-sessions-list__class-name,
.gg-booking-session--cancelled .gg-booking-sessions-card__title {
	text-decoration: line-through;
	color: var( --gg-color-text-muted );
}

.gg-booking-session--cancelled-badge {
	margin-left: 6px;
}

.gg-booking-sessions-list__action {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 6px;
	min-width: 140px;
}

.gg-booking-sessions-list__price {
	font-size: 16px;
	font-weight: 700;
	color: var(--gg-color-text);
}

.gg-booking-sessions-list__capacity {
	font-size: 12px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-list__empty {
	padding: 24px;
	text-align: center;
	color: var(--gg-color-text-muted);
}

/* Sessions List — vertical stack on PHONES ONLY (≤767px, Elementor's mobile/
   tablet boundary). Tablet (768px+) keeps the horizontal row — it has room to
   breathe. Declared AFTER the base list rules above so these overrides win on
   source order (media queries add no specificity). On phones the row crams the
   class name + room into thin columns, so switch to a clean CENTERED stack:
   thumbnail centered, details + badges centered, full-width action + Book button. */
@media (max-width: 767px) {
	.gg-booking-sessions-list__item {
		flex-direction: column;
		align-items: stretch;
		gap: 12px;
		text-align: center;
	}

	.gg-booking-sessions-list__image {
		justify-content: center;
	}

	.gg-booking-sessions-list__date-block,
	.gg-booking-sessions-list__info,
	.gg-booking-sessions-list__action {
		align-items: center;
	}

	.gg-booking-sessions-list__badges {
		justify-content: center;
	}

	.gg-booking-sessions-list__action {
		width: 100%;
		flex-direction: column;
		gap: 8px;
		min-width: 0;
	}

	.gg-booking-sessions-list__action .gg-booking-btn {
		width: 100%;
	}
}

/* Sessions grid (card view) */

.gg-booking-sessions-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px;
}

/* Sessions card view */

.gg-booking-sessions-card {
	padding-left: 12px;
}

.gg-booking-sessions-card__body {
	padding: 4px 0 4px 4px;
}

.gg-booking-sessions-card__footer {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px solid var(--gg-color-border);
}

.gg-booking-sessions-card__price {
	font-size: 18px;
	font-weight: 700;
	color: var(--gg-color-text);
}

.gg-booking-sessions-card__capacity {
	font-size: 12px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-card__footer .gg-booking-btn {
	width: 100%;
	text-align: center;
}

/* Sessions Card badges row — sits above the title (canonical order). Alignment
   / gap driven by --gg-card-badges-* vars (Layout → Badges alignment). */
.gg-booking-sessions-card__badges {
	display: flex;
	flex-wrap: wrap;
	gap: var( --gg-card-badges-gap, 6px );
	justify-content: var( --gg-card-badges-align, flex-start );
	margin: 0 0 8px;
}

/* Card instructor row — flex so the optional avatar sits inline; consumes the
   Layout instructor-alignment var (parity with the list + schedule card). */
.gg-booking-sessions-card__instructor {
	display: flex;
	align-items: center;
	gap: 6px;
	justify-content: var( --gg-card-instructor-align, flex-start );
	font-size: 13px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-card__instructor-photo {
	width: 24px;
	height: 24px;
	border-radius: 50%;
	object-fit: cover;
	flex-shrink: 0;
}

/* Room + Description (both views) — soft meta text, matching location styling. */
.gg-booking-sessions-list__room,
.gg-booking-sessions-card__room {
	font-size: 13px;
	color: var(--gg-color-text-muted);
}

.gg-booking-sessions-list__description,
.gg-booking-sessions-card__description {
	font-size: 13px;
	line-height: 1.5;
	color: var(--gg-color-text-muted);
	margin-top: 4px;
}

/* Class Card badges (used by ClassCardWidget). */
.gg-booking-class-card__badges {
	display: flex;
	gap: 6px;
	flex-wrap: wrap;
	margin-bottom: 8px;
	justify-content: var( --gg-badges-align, flex-start );
}

/* Schedule widget — Cards view badges row.
   Sits between the title and the meta block. Alignment / gap / radius
   driven by --gg-card-badges-* vars (Badges Style section). */
.gg-booking-schedule-card__badges {
	display: flex;
	flex-wrap: wrap;
	gap: var( --gg-card-badges-gap, 6px );
	justify-content: var( --gg-card-badges-align, flex-start );
	margin: 6px 0 8px;
}

/* List + popover badge containers — alignment vars shared with above
   pattern; existing .gg-booking-sessions-list__badges / .gg-booking-cal-popover__badges
   declarations stay (gap default + display:flex), this adds the var
   plumbing on top. */
.gg-booking-sessions-list__badges {
	gap: var( --gg-list-badges-gap, 6px );
	justify-content: var( --gg-list-badges-align, var( --gg-badges-align, flex-start ) );
}

.gg-booking-cal-popover__badges {
	gap: var( --gg-cal-popover-badges-gap, 6px );
	justify-content: var( --gg-cal-popover-badges-align, flex-start );
}

.gg-badge--category {
	background: var(--gg-surface, var(--gg-color-background));
	color: var(--gg-color-text-muted);
	border: 1px solid var(--gg-color-border);
}

/* ----------------------------------------------------------------------- */
/* Schedule date filter                                                    */
/* ----------------------------------------------------------------------- */

.gg-booking-schedule-date-filter {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	align-items: center;
	margin-bottom: 20px;
}

.gg-booking-schedule-date-filter__buttons {
	display: flex;
	gap: 6px;
	flex-wrap: wrap;
}

.gg-booking-date-btn {
	display: inline-block;
	padding: 6px 14px;
	border-radius: 20px;
	border: 1px solid var(--gg-color-border);
	color: var(--gg-color-text);
	text-decoration: none;
	font-size: 13px;
	transition: all 0.2s ease;
	background: var(--gg-color-background);
}

.gg-booking-date-btn:hover {
	border-color: var(--gg-color-primary);
	color: var(--gg-color-primary);
}

.gg-booking-date-btn--active {
	background: var(--gg-color-primary);
	border-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

.gg-booking-date-btn--active:hover {
	color: var(--gg-color-surface);
}

.gg-booking-schedule-date-filter__picker {
	display: flex;
	gap: 8px;
	align-items: center;
	flex-wrap: wrap;
}

.gg-booking-schedule-date-filter__picker label {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 13px;
}

.gg-booking-schedule-date-filter__picker input[type="date"] {
	padding: 4px 8px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	font-size: 13px;
}

.gg-booking-date-filter__clear {
	color: var(--gg-color-text-muted);
	font-size: 12px;
	text-decoration: none;
}

.gg-booking-date-filter__clear:hover {
	color: var(--gg-color-error);
}

.gg-booking-schedule-result-count {
	font-size: 13px;
	color: var(--gg-color-text-muted);
	margin-bottom: 12px;
}

/* ----------------------------------------------------------------------- */
/* Package Shop                                                            */
/* ----------------------------------------------------------------------- */

.gg-booking-package-shop {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: 24px;
}

/* The package shop's 80rem content cap lives with the other per-widget-type
   defaults next to the .gg-booking-widget-inner base rule (search
   "Per-widget-type content caps"). */

.gg-booking-package-shop__empty {
	text-align: center;
	color: var(--gg-color-text-muted);
}

.gg-booking-package-card {
	background: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	border-radius: 8px;
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	position: relative;
	transition: box-shadow 0.2s ease;
}

.gg-booking-package-card:hover {
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.gg-booking-package-card--owned {
	border-color: var(--gg-color-primary);
}

/* Deep-link arrival highlight (membership-gate-signpost): a gate's plan link
   lands on memberships_page_url#gg-package-{id}; the browser scrolls to the
   card natively and :target flashes it so the visitor sees which plan they
   came for. Pure CSS, no JS. The brand-tinted ring persists while targeted; a
   one-shot pulse draws the eye on arrival. scroll-margin keeps it clear of any
   sticky header. */
.gg-booking-package-card:target {
	outline: 2px solid var( --gg-color-primary, var(--gg-color-primary) );
	outline-offset: 3px;
	scroll-margin-top: 90px;
	animation: gg-package-target-pulse 1.2s ease-out 1;
}

@keyframes gg-package-target-pulse {
	/* Brand-tracking pulse — was hardcoded Forest rgba(37,64,50,…); now derives
	   from --gg-color-primary via color-mix so it follows the studio's brand on
	   non-Forest palettes (same pattern as .gg-badge--course). v1.1.67. */
	0%   { box-shadow: 0 0 0 0 color-mix( in srgb, var( --gg-color-primary ) 45%, transparent ); }
	100% { box-shadow: 0 0 0 14px color-mix( in srgb, var( --gg-color-primary ) 0%, transparent ); }
}

.gg-booking-package-card__owned-badge {
	position: absolute;
	top: -10px;
	right: 16px;
	background: var(--gg-color-primary);
	color: var(--gg-color-surface);
	font-size: 11px;
	font-weight: 600;
	padding: 2px 10px;
	border-radius: 12px;
}

/* Featured image — PackageShop pt.4 (rule 117 seven-control image model).
 * The wrapper is a flex container so the Alignment control's justify-content
 * reaches the <img> at any Size value < 100%. img.gg-... raises the selector
 * specificity to 0,1,1 so a theme's `img { max-width: 100% }` reset can't
 * override the Size control — paired with `max-width: none` as the inline
 * defence. No `overflow: hidden` here: the Size slider caps at 100% so the
 * image can't overflow horizontally, and clipping the wrap would chop any
 * box-shadow set via the Image controls. The image's own `border-radius`
 * renders naturally without needing the wrap to clip it. */
.gg-booking-package-card__img-wrap {
	display: flex;
	justify-content: var( --gg-package-image-align, center );
	width: 100%;
}

img.gg-booking-package-card__img {
	display: block;
	width: 100%;
	max-width: none;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	object-position: center center;
}

.gg-booking-package-card__img--placeholder {
	width: 100%;
	aspect-ratio: 16 / 9;
	background:
		linear-gradient(135deg, transparent 45%, rgba(0, 0, 0, 0.05) 45%, rgba(0, 0, 0, 0.05) 55%, transparent 55%),
		var(--gg-color-muted-soft, rgba(0, 0, 0, 0.06));
}

.gg-booking-package-card__title {
	font-size: 18px;
	font-weight: 700;
	color: var(--gg-color-text);
	margin: 0;
}

.gg-booking-package-card__price {
	font-size: 28px;
	font-weight: 800;
	color: var(--gg-color-primary);
	line-height: 1;
}

.gg-booking-package-card__interval {
	font-size: 14px;
	font-weight: 400;
	color: var(--gg-color-text-muted);
	margin-left: 2px;
}

.gg-booking-package-card__sessions,
.gg-booking-package-card__validity {
	font-size: 14px;
	color: var(--gg-color-text-muted);
}

.gg-booking-package-card__description {
	font-size: 13px;
	color: var(--gg-color-text-muted);
	line-height: 1.6;
}
.gg-booking-package-card__description p {
	margin: 0;
}

.gg-booking-package-card__classes {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	font-size: 12px;
	color: var(--gg-color-text-muted);
	align-items: center;
}

/* Buy button base. Intentionally does NOT set `width` — the Button Width
   control (LayoutControls widths) is the sole authority, defaulting to 100%.
   Previously this rule set `width: 100%` at specificity 0,2,0, the SAME as
   the control's `{{WRAPPER}} .gg-booking-package-buy-btn`, so on environments
   where the plugin's static CSS loaded after Elementor's inline post-CSS the
   base won — locking the buy button at 100% even when the control said Auto.
   With width removed here, Auto actually shrinks the button (and Button
   alignment then has somewhere to position it). */
.gg-booking-package-card .gg-booking-package-buy-btn {
	margin-top: auto;
	text-align: center;
}

/* `align-self: flex-start` on BOTH buy buttons (not-owned BUY NOW + owned
   BUY FOR SOMEONE ELSE) — fully decouples the buy button from its parent's
   `align-items`. Owned State alignment (which sets `--gg-owned-align` →
   `.gg-booking-owned-actions { align-items }`) thus only moves the badge +
   Manage (its intended scope); the buy button is positioned exclusively by
   the Button alignment control. Also lets `width: auto` actually take
   effect (the card's default `align-items: stretch` was overriding it). */
.gg-booking-package-card .gg-booking-package-buy-btn {
	align-self: flex-start;
}

/* ----------------------------------------------------------------------- */
/* Booking Form — Payment Options                                          */
/* ----------------------------------------------------------------------- */

.gg-booking-booking-payment-options {
	margin-bottom: 24px;
}

.gg-booking-booking-payment-options h3 {
	font-size: 16px;
	font-weight: 600;
	margin-bottom: 12px;
	color: var(--gg-color-text);
}

.gg-booking-payment-option {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	margin-bottom: 8px;
	cursor: pointer;
	transition: border-color 0.15s ease, background 0.15s ease;
}

.gg-booking-payment-option:has(input:checked) {
	border-color: var(--gg-color-primary);
	background: var(--gg-surface, var(--gg-color-background));
}

.gg-booking-payment-option--disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.gg-booking-payment-option input[type="radio"] {
	margin-top: 3px;
	flex-shrink: 0;
	accent-color: var(--gg-color-primary);
}

.gg-booking-payment-option__info {
	flex: 1;
}

.gg-booking-payment-option__name {
	font-weight: 600;
	font-size: 14px;
	display: block;
	color: var(--gg-color-text);
}

.gg-booking-payment-option__meta {
	font-size: 13px;
	color: var(--gg-color-text-muted);
	display: block;
	margin-top: 2px;
}

.gg-booking-payment-option__invalid {
	font-size: 12px;
	color: var(--gg-color-error);
	display: block;
	margin-top: 2px;
}

/* ----------------------------------------------------------------------- */
/* Modal overlay                                                           */
/* ----------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
 * GGModal — generic modal host (Modal Arc, Phase 3a). Distinct namespace from
 * the legacy .gg-booking-modal (the package purchase modal) below. 720px
 * centered on desktop; slide-up bottom-sheet at <=768px (Decision 4.B).
 * ------------------------------------------------------------------------- */
html.gg-modal-lock,
body.gg-modal-lock {
	overflow: hidden;
}

.gg-modal-overlay {
	position: fixed;
	inset: 0;
	z-index: 100001;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 32px;
	background: rgba(0, 0, 0, 0.5);
	opacity: 0;
	transition: opacity var(--gg-duration-base) var(--gg-ease-out);
}

.gg-modal-overlay[hidden] {
	display: none;
}

.gg-modal-overlay.is-open {
	opacity: 1;
}

/* Top-anchored variant (opt-in via GGModal `position:'top'`). The overlay's
   32px padding becomes the top gap; mobile bottom-sheet rules still govern. */
.gg-modal-overlay--top {
	align-items: flex-start;
}

.gg-modal {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: 720px;
	max-height: 90vh;
	background: var(--gg-color-background);
	border-radius: 14px;
	box-shadow: 0 12px 48px rgba(0, 0, 0, 0.22);
	overflow: hidden;
	transform: translateY(12px) scale(0.98);
	transition: transform var(--gg-duration-base) var(--gg-ease-out);
}

.gg-modal-overlay.is-open .gg-modal {
	transform: none;
}

.gg-modal--narrow { max-width: 480px; }
.gg-modal--wide   { max-width: 920px; }

.gg-modal__handle {
	display: none; /* shown only as the bottom-sheet grab bar on mobile */
}

.gg-modal__header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
	padding: 20px 24px 12px;
}

/* Scoped to `.gg-modal` (0,2,0) so it beats Elementor's body-mounted Kit
   heading rule `.elementor-kit-N h2` (0,1,1) — the modal is appended to
   <body>, inside the Kit scope, so that rule would otherwise repaint this
   <h2> with the Kit's secondary colour (the sage-green default when a studio
   sets only its primary). Heading sibling of the body-mounted button armor. */
.gg-modal .gg-modal__title {
	margin: 0;
	font-size: 20px;
	line-height: 1.3;
	color: var(--gg-color-text);
	font-family: var(--gg-type-heading);
}

/* Container-scoped (0,2,0) — see [[elementor-kit-button-bodymounted-gotcha]]:
   this is a bare <button>, so Elementor's global Kit rule `.elementor-kit-N
   button` (0,1,1) would otherwise repaint it with the accent box + 24px padding
   + shadow. 0,2,0 beats it; box-shadow/border-radius/appearance nulled to clear
   the Kit/UA chrome. */
.gg-modal .gg-modal__close {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	-webkit-appearance: none;
	appearance: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	background: transparent;
	font-size: 22px;
	line-height: 0;
	cursor: pointer;
	color: var(--gg-color-text-muted);
	padding: 2px 4px;
}

/* SVG glyph — sized in em so a font-size override scales it; currentColor so
   the close color drives the stroke. */
.gg-modal .gg-modal__close-icon {
	width: 1em;
	height: 1em;
	display: block;
	flex-shrink: 0;
}

.gg-modal .gg-modal__close:hover,
.gg-modal .gg-modal__close:focus {
	color: var(--gg-color-text);
	/* Re-assert the bare-button reset: the Elementor kit's `button:hover/:focus`
	   rule (0,2,1) paints bg + box-shadow + radius, which leaks onto this
	   body-mounted close button. (0,3,0) overrides all of them. */
	background: transparent;
	box-shadow: none;
	border-radius: 0;
}

.gg-modal__body {
	flex: 1 1 auto;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	padding: 4px 24px 24px;
}

/* Booking/Appointment modal header + body clear the corner radius.
   The card-chrome Border Radius control rounds the DIALOG (paired selector) and
   publishes the top corner radii as vars. The dialog's overflow:hidden would clip
   the header chrome (title top-left, close top-right) at a large radius — so inset
   the header AND body horizontally by at least the corner radius (floored at the
   normal 24px). Header + body share the inset so they stay aligned. No cap on the
   radius, no clip, no studio padding tweak needed. (0,3,0) beats GGModal's base
   header/body padding (0,1,0). */
.gg-modal.gg-booking-booking-modal .gg-modal__header,
.gg-modal.gg-booking-booking-modal .gg-modal__body {
	padding-left: max(24px, var(--gg-bm-radius-tl, 0px));
	padding-right: max(24px, var(--gg-bm-radius-tr, 0px));
}

.gg-modal.gg-booking-appointment-modal .gg-modal__header,
.gg-modal.gg-booking-appointment-modal .gg-modal__body {
	padding-inline: max(24px, var(--gg-am-radius, 0px));
}

.gg-modal__error {
	color: var(--gg-color-error);
	text-align: center;
	padding: 24px 0;
}

.gg-modal__veil {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(255, 255, 255, 0.6);
}

.gg-modal__veil::after {
	content: "";
	width: 28px;
	height: 28px;
	border: 3px solid var(--gg-color-border);
	border-top-color: var(--gg-color-primary);
	border-radius: 50%;
	animation: gg-modal-spin 0.7s linear infinite;
}

.gg-modal__veil[hidden] { display: none; }

@keyframes gg-modal-spin {
	to { transform: rotate(360deg); }
}

.gg-modal__live {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}

/* Bottom-sheet on tablet/mobile (Decision 4.B — ~25-30% higher engagement). */
@media (max-width: 768px) {
	.gg-modal-overlay {
		align-items: flex-end;
		padding: 0;
	}

	.gg-modal {
		max-width: none;
		max-height: 88vh;
		border-radius: 16px 16px 0 0;
		transform: translateY(100%);
	}

	.gg-modal-overlay.is-open .gg-modal {
		transform: none;
	}

	.gg-modal__handle {
		display: block;
		width: 40px;
		height: 5px;
		margin: 10px auto 0;
		padding: 0;
		border: 0;
		border-radius: 3px;
		background: var(--gg-color-border);
		cursor: pointer;
	}

	.gg-modal__header {
		padding-top: 8px;
	}
}

.gg-booking-modal-overlay {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(0, 0, 0, 0.5);
}

.gg-booking-modal {
	background: var(--gg-color-background);
	border-radius: 12px;
	padding: 28px;
	max-width: 420px;
	width: 90%;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
}

.gg-booking-modal h3 {
	margin: 0 0 8px;
	font-size: 20px;
	color: var(--gg-color-text);
}

.gg-booking-modal p {
	margin: 0 0 16px;
	font-size: 16px;
	color: var(--gg-color-text-muted);
}

.gg-booking-modal__actions {
	display: flex;
	gap: 8px;
	margin-top: 20px;
}

.gg-booking-modal__actions .gg-booking-btn {
	flex: 1;
}

#gg-booking-package-card-element {
	padding: 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
	background: var(--gg-color-background);
}

/* ----------------------------------------------------------------------- */
/* Calendar placeholder                                                    */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/* Membership cards                                                        */
/* ----------------------------------------------------------------------- */

.gg-booking-membership-card {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 16px;
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	margin-bottom: 8px;
	flex-wrap: wrap;
}

.gg-booking-membership-card__info {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.gg-booking-membership-card__info strong {
	font-size: 15px;
	color: var(--gg-color-text);
}

.gg-booking-membership-card__info span {
	font-size: 13px;
	color: var(--gg-color-text-muted);
}

.gg-badge--warning {
	background: var(--gg-color-warning-soft);
	color: var(--gg-color-warning);
	border: 1px solid var(--gg-color-warning);
	display: inline-block;
	padding: 2px 8px;
	border-radius: 12px;
	font-size: 11px;
	font-weight: 500;
}

/* ----------------------------------------------------------------------- */
/* Calendar placeholder                                                    */
/* ----------------------------------------------------------------------- */

.gg-booking-calendar-placeholder {
	padding: 40px 20px;
	text-align: center;
	background: var(--gg-surface, var(--gg-color-background));
	border: 2px dashed var(--gg-color-border);
	border-radius: 6px;
	color: var(--gg-color-text-muted);
}

/* ----------------------------------------------------------------------- */
/* Payment select dropdown                                                 */
/* ----------------------------------------------------------------------- */

.gg-booking-booking-payment-options {
	margin-bottom: 20px;
}

.gg-booking-booking-payment-options label {
	display: block;
	font-weight: 600;
	font-size: 14px;
	margin-bottom: 6px;
	color: var(--gg-color-text);
}

.gg-booking-select {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	font-size: 14px;
	color: var(--gg-color-text);
	background: var(--gg-color-background);
	appearance: auto;
	cursor: pointer;
}

.gg-booking-select:focus {
	outline: none;
	border-color: var(--gg-color-primary);
	/* Brand-tracking focus ring (rule 46): rgba fallback, color-mix where supported. */
	box-shadow: 0 0 0 3px rgba(92, 122, 92, 0.15);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--gg-color-primary) 20%, transparent);
}

/* ----------------------------------------------------------------------- */
/* Package Shop — ownership states                                         */
/* ----------------------------------------------------------------------- */

.gg-booking-package-owned-msg {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	text-align: center;
}

.gg-booking-package-owned-msg > span {
	font-size: 13px;
	color: var(--gg-color-text-muted);
	font-weight: 500;
}

.gg-booking-btn--disabled {
	background: var(--gg-color-border);
	color: var(--gg-color-text-muted);
	border: none;
	border-radius: 6px;
	padding: 10px 20px;
	font-size: 14px;
	cursor: not-allowed;
	width: 100%;
}

.gg-booking-btn--outline {
	background: transparent;
	color: var(--gg-color-primary);
	border: 1px solid var(--gg-color-primary);
	border-radius: 6px;
	padding: 10px 20px;
	font-size: 14px;
	cursor: pointer;
	width: 100%;
	transition: background 0.15s, color 0.15s;
}

.gg-booking-btn--outline:hover {
	background: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

/* ----------------------------------------------------------------------- */
/* Modal — recipient form fields                                           */
/* ----------------------------------------------------------------------- */

.gg-booking-form-row {
	margin-bottom: 12px;
}

.gg-booking-form-row label {
	display: block;
	font-weight: 600;
	font-size: 13px;
	margin-bottom: 4px;
	color: var(--gg-color-text);
}

.gg-booking-modal__input {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	font-size: 14px;
	color: var(--gg-color-text);
	background: var(--gg-color-background);
	box-sizing: border-box;
}

.gg-booking-modal__input:focus {
	outline: none;
	border-color: var(--gg-color-primary);
	/* Brand-tracking focus ring (rule 46): rgba fallback, color-mix where supported. */
	box-shadow: 0 0 0 3px rgba(92, 122, 92, 0.15);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--gg-color-primary) 20%, transparent);
}

/* ----------------------------------------------------------------------- */
/* Purchase / T&C modals                                                   */
/* The purchase form mounts inside the shared GGModal primitive (GGModal    */
/* owns the overlay + header + close X). The .gg-booking-modal__* rules     */
/* below still dress the T&C modal (BookingForm), which keeps its bespoke   */
/* overlay for now — and the body/footer/section/price pieces that the      */
/* purchase form reuses inside GGModal.                                     */
/* ----------------------------------------------------------------------- */

.gg-booking-modal__header {
	position: relative;
	margin-bottom: 16px;
}

.gg-booking-modal__price {
	font-size: 22px;
	font-weight: 700;
	color: var(--gg-color-primary);
	margin-bottom: 16px;
}

/* Container-scoped (0,2,0) vs Elementor's Kit `button` rule (0,1,1) —
   [[elementor-kit-button-bodymounted-gotcha]]. */
.gg-booking-modal .gg-booking-modal__close {
	position: absolute;
	top: 0;
	right: 0;
	-webkit-appearance: none;
	appearance: none;
	background: none;
	border: none;
	border-radius: 0;
	box-shadow: none;
	font-size: 24px;
	color: var(--gg-color-text-muted);
	cursor: pointer;
	padding: 0;
	line-height: 1;
}

.gg-booking-modal .gg-booking-modal__close:hover {
	color: var(--gg-color-text);
}

.gg-booking-modal__body {
	margin-bottom: 16px;
}

.gg-booking-modal__footer {
	display: flex;
	gap: 8px;
}

.gg-booking-modal__footer .gg-booking-btn {
	flex: 1;
}

.gg-booking-form-section {
	margin-bottom: 20px;
	padding-bottom: 20px;
	border-bottom: 1px solid var(--gg-color-border);
}

.gg-booking-form-section:last-of-type {
	border-bottom: none;
	margin-bottom: 0;
	padding-bottom: 0;
}

.gg-booking-form-section h4 {
	font-size: 13px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--gg-color-text-muted);
	margin: 0 0 12px;
}

.gg-booking-input {
	width: 100%;
	padding: 8px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	font-size: 14px;
	color: var(--gg-color-text);
	background: var(--gg-color-background);
	box-sizing: border-box;
}

.gg-booking-input:focus {
	outline: none;
	border-color: var(--gg-color-primary);
	/* Brand-tracking focus ring (rule 46): rgba fallback, color-mix where supported. */
	box-shadow: 0 0 0 3px rgba(92, 122, 92, 0.15);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--gg-color-primary) 20%, transparent);
}

.gg-booking-toggle-label {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
	color: var(--gg-color-text);
	cursor: pointer;
	font-weight: 500;
}

.gg-booking-toggle-label input[type="checkbox"] {
	width: 16px;
	height: 16px;
	accent-color: var(--gg-color-primary);
	cursor: pointer;
}

.gg-booking-owned-actions {
	display: flex;
	flex-direction: column;
	gap: 8px;
	align-items: flex-start;
}

.gg-booking-owned-label {
	font-size: 13px;
	color: var(--gg-color-text-muted);
	font-style: italic;
}

.gg-booking-btn--sm {
	padding: 4px 12px;
	font-size: 12px;
}

.gg-booking-for-someone-wrapper {
	margin: 16px 0;
}

/* Booking form for-someone section */
#gg-booking-recipient {
	background: var(--gg-surface, var(--gg-color-background));
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
	padding: 16px;
}

/* ----------------------------------------------------------------------- */
/* Family Accounts — "Who is this for?" member selector (rule §3.1)        */
/* ----------------------------------------------------------------------- */

.gg-booking-member-selector {
	margin: 16px 0;
	padding: 14px 16px;
	background: var(--gg-surface, var(--gg-color-background));
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
}

.gg-booking-member-selector__label {
	display: block;
	margin-bottom: 10px;
	font-family: var(--gg-font-heading, var(--gg-font-base));
	font-weight: 600;
	color: var(--gg-text, var(--gg-color-text));
}

.gg-booking-member-selector__hint {
	font-weight: 400;
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-member-selector__multi-note {
	margin: 10px 0 0;
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-member-selector__options {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.gg-booking-member-selector__option {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 8px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 999px;
	cursor: pointer;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}

.gg-booking-member-selector__option:hover {
	border-color: var(--gg-primary, var(--gg-color-primary));
}

.gg-booking-member-selector__name {
	color: var(--gg-text, var(--gg-color-text));
}

/* Progressive disclosure — empty household. Collapse the card chrome and hide
   the "Who is this for?" label + the lone "Myself" radio, so a solo booker sees
   only the compact "+ Add a family member" affordance. The hidden Myself radio
   still submits book_for_client_id=0. The booking/appointment JS strips
   `--empty` on first add, revealing the full selector. */
.gg-booking-member-selector--empty {
	margin: 8px 0 16px;
	padding: 0;
	background: none;
	border: none;
}

.gg-booking-member-selector--empty .gg-booking-member-selector__label,
.gg-booking-member-selector--empty .gg-booking-member-selector__options {
	display: none;
}

.gg-booking-member-selector--empty .gg-booking-member-add {
	margin-top: 0;
}

.gg-booking-member-add {
	margin-top: 12px;
}

/* "+ Add a family member" — a ghost button mirroring .gg-booking-btn--secondary
   (transparent fill, primary border + text; fills primary on hover). The base
   CSS used a bare-link reset at (0,1,0), which LOST to Elementor's global Kit
   button rule `.elementor-kit-N button` (0,1,1) on the live front end — so the
   toggle inherited the site's global button (uppercase, accent fill) instead of
   the widget palette. Scoping under the container raises us to (0,2,0) to beat
   the Kit at rest, with a paired :hover/:focus reset at (0,3,1) to re-assert
   every property the Kit's (0,2,1) hover rule sets. See
   [[elementor-kit-button-bodymounted-gotcha]]. Per-instance Style controls
   ({{WRAPPER}} …, higher still) override this. */
.gg-booking-member-selector .gg-booking-member-add__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 8px 14px;
	background: transparent;
	border: 1px solid var(--gg-primary, var(--gg-color-primary));
	border-radius: 4px;
	font: inherit;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: normal;
	text-transform: none;
	color: var(--gg-primary, var(--gg-color-primary));
	box-shadow: none;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.gg-booking-member-selector .gg-booking-member-add .gg-booking-member-add__toggle:hover,
.gg-booking-member-selector .gg-booking-member-add .gg-booking-member-add__toggle:focus {
	background-color: var(--gg-primary, var(--gg-color-primary));
	color: var(--gg-surface, var(--gg-color-surface));
	border-color: var(--gg-primary, var(--gg-color-primary));
	border-radius: 4px;
	box-shadow: none;
}

.gg-booking-member-selector .gg-booking-member-add__toggle:disabled {
	opacity: 0.6;
	cursor: default;
}

.gg-booking-member-add__form {
	margin-top: 12px;
	padding: 12px;
	border: 1px dashed var(--gg-color-border);
	border-radius: 6px;
}

.gg-booking-member-add__row {
	margin-bottom: 10px;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.gg-booking-member-add__field-label {
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-member-add__row input {
	width: 100%;
	padding: 8px 10px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
}

.gg-booking-member-add__or {
	margin: 12px 0;
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-member-add__actions {
	display: flex;
	align-items: center;
	gap: 12px;
}

.gg-booking-member-add__feedback {
	font-size: 0.85em;
	color: var(--gg-error, var(--gg-color-error));
}

.gg-booking-member-add__feedback--ok {
	color: var(--gg-success, var(--gg-color-success));
}

/* ----------------------------------------------------------------------- */
/* Household tab (Client Dashboard — Family Accounts)                      */
/* ----------------------------------------------------------------------- */
.gg-booking-household__intro {
	margin: 0 0 16px;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-household__managed-by {
	padding: 14px 16px;
	background: var(--gg-surface, var(--gg-color-background));
	border: 1px solid var(--gg-color-border);
	border-left: 3px solid var(--gg-primary, var(--gg-color-primary));
	border-radius: 6px;
}

.gg-booking-household__managed-by p {
	margin: 0;
	color: var(--gg-text, var(--gg-color-text));
}

.gg-booking-household__roster {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin-bottom: 16px;
}

.gg-booking-household__member-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
	flex-wrap: wrap;
}

.gg-booking-household__member-id {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

.gg-booking-household__member-name {
	color: var(--gg-text, var(--gg-color-text));
}

.gg-booking-household__member-type {
	font-size: 0.75em;
}

.gg-booking-household__member-actions {
	display: inline-flex;
	align-items: center;
	gap: 8px;
}

.gg-booking-household__member-bookings {
	margin-top: 10px;
}

.gg-booking-household__member-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.gg-booking-household__member-booking {
	font-size: 0.9em;
	color: var(--gg-text, var(--gg-color-text));
}

.gg-booking-household__member-when {
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-household__member-empty {
	margin: 0;
	font-size: 0.9em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-household__add {
	margin-top: 4px;
}

.gg-booking-household__add-form {
	margin-top: 12px;
	padding: 12px;
	border: 1px dashed var(--gg-color-border);
	border-radius: 6px;
}

.gg-booking-household__add-row {
	margin-bottom: 10px;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.gg-booking-household__add-label {
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-household__add-row input {
	width: 100%;
	padding: 8px 10px;
	border: 1px solid var(--gg-color-border);
	border-radius: 4px;
}

.gg-booking-household__add-or {
	margin: 12px 0;
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-household__add-actions {
	display: flex;
	align-items: center;
	gap: 12px;
}

.gg-booking-household__add-feedback {
	font-size: 0.85em;
	color: var(--gg-error, var(--gg-color-error));
}

.gg-booking-household__add-feedback--ok {
	color: var(--gg-success, var(--gg-color-success));
}

/* Pending invitations (adult invite/accept — Phase 4). */
.gg-booking-household__invites {
	margin-top: 18px;
	padding-top: 14px;
	border-top: 1px solid var(--gg-color-border);
}

.gg-booking-household__invites-title {
	margin: 0 0 10px;
	font-size: 0.95em;
}

.gg-booking-household__invite-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.gg-booking-household__invite {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 8px;
	padding: 10px 12px;
	border: 1px solid var(--gg-color-border);
	border-radius: 6px;
}

.gg-booking-household__invite-id {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
}

.gg-booking-household__invite-email {
	font-size: 0.85em;
	color: var(--gg-text-light, var(--gg-color-text));
}

.gg-booking-household__invite-actions {
	display: flex;
	align-items: center;
	gap: 8px;
}

.gg-booking-household__invite-feedback {
	font-size: 0.85em;
	color: var(--gg-error, var(--gg-color-error));
}

.gg-booking-household__invite-feedback--ok {
	color: var(--gg-success, var(--gg-color-success));
}

/* ----------------------------------------------------------------------- */
/* Cancellation Policy                                                     */
/* ----------------------------------------------------------------------- */

.gg-booking-cancellation-policy {
	margin-top: 16px;
	padding: 12px;
	background: var(--gg-surface, var(--gg-color-background));
	border-left: 3px solid var(--gg-color-border);
	border-radius: 0 4px 4px 0;
	font-size: 13px;
	color: var(--gg-color-text-muted);
	line-height: 1.6;
}

.gg-booking-cancellation-policy p {
	margin: 0 0 8px;
}

.gg-booking-cancellation-policy p:last-child {
	margin: 0;
}

/* ----------------------------------------------------------------------- */
/* Terms & Conditions                                                      */
/* ----------------------------------------------------------------------- */

.gg-booking-tnc-wrapper {
	margin-top: 16px;
}

.gg-booking-tnc-label {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-size: 14px;
	color: var(--gg-color-text);
	cursor: pointer;
	line-height: 1.5;
}

.gg-booking-tnc-label input[type="checkbox"] {
	margin-top: 2px;
	flex-shrink: 0;
	accent-color: var(--gg-color-primary);
	width: 16px;
	height: 16px;
}

.gg-booking-tnc-label a {
	color: var(--gg-color-primary);
	text-decoration: underline;
}

.gg-booking-tnc-body {
	max-height: 400px;
	overflow-y: auto;
	font-size: 14px;
	line-height: 1.7;
	color: var(--gg-color-text);
	padding: 0 4px;
}

/* ----------------------------------------------------------------------- */
/* Widget inner wrapper                                                    */
/* ----------------------------------------------------------------------- */

.gg-booking-widget-inner {
	width: 100%;
	max-width: var(--gg-widget-max-width, 64rem);
	margin-inline: auto;
	font-family: var( --gg-type-body );
	color: var( --gg-color-text );
}

/* Per-widget-type content caps.
   Every widget centres inside .gg-booking-widget-inner and caps at
   --gg-widget-max-width (global default 64rem, set on :root). These rules
   tune that default per widget TYPE so each is beautiful by default:
     · card grids .......... 80rem  — room for 3–4 cards across; folds down
     · schedule ............ 80rem  — calendar + card/list want the width
     · single class card ... 32rem  — one card shouldn't span the page
     · book-now button ..... none   — the button owns its own width control
     · dashboards/profile .. 56rem  — tuned family cap (was the 64rem :root
                                      default; 64rem read slightly too wide for
                                      these single-column panels — v1.1.65)
   Keyed off Elementor's own `.elementor-widget-{name}` wrapper and wrapped
   in :where() for ZERO specificity, so the per-instance "Max Width" Layout
   control (`{{WRAPPER}} .gg-booking-widget-inner`, 0,2,0) always wins with no
   !important — and so a studio's override of the global default still beats
   these. The form/auth widgets (Booking Form, Login, Password Reset) and
   AppointmentBooking are intentionally excluded: they each own a dedicated
   Form/Content Max Width + alignment control that caps the inner form, so a
   second widget-level cap here would double up and fight their alignment.
   Headless fragment renders (e.g. the booking form inside a modal) have no
   `.elementor-widget-*` wrapper and fall back to the 64rem default, which the
   modal's own width caps anyway. */
:where(
	.elementor-widget-gg_package_shop,
	.elementor-widget-gg_services_showcase,
	.elementor-widget-gg_sessions_list,
	.elementor-widget-gg_schedule
) .gg-booking-widget-inner {
	--gg-widget-max-width: 80rem;
}

:where( .elementor-widget-gg_class_card ) .gg-booking-widget-inner {
	--gg-widget-max-width: 32rem;
}

/* Dashboards + Instructor Profile share a tuned reading-width default,
   narrower than the 64rem :root global — 64rem felt slightly too wide for
   these single-column content panels. An explicit family cap (rather than the
   :root default) keeps all three consistent and tunable in one place; the
   per-instance Max Width control still overrides (zero-specificity :where).
   These three are the only widgets that previously used the :root default. */
:where(
	.elementor-widget-gg_client_dashboard,
	.elementor-widget-gg_instructor_dashboard,
	.elementor-widget-gg_instructor_profile
) .gg-booking-widget-inner {
	--gg-widget-max-width: 56rem;
}

:where( .elementor-widget-gg_book_now_button ) .gg-booking-widget-inner {
	--gg-widget-max-width: none;
}

/* Frame widgets fill their flex container so Max Width can SIZE them (rule 122).
   A flex parent with `align-items: center` (Elementor containers can set it; the
   starter pages do, on .e-con-inner) shrinks a child to its CONTENT width — which
   caps how wide Max Width can make the widget (max-width can't grow a shrink-
   wrapped box). Forcing each frame widget's flex item to stretch hands Max Width
   the full container to work within; the Frame's Alignment then positions the
   capped inner block via margin-inline. (0,1,0) so a studio's explicit Advanced →
   Align Self still wins; with none set, the widget stretches. BookNowButton is
   excluded — it owns its own width. */
.elementor-widget-gg_schedule,
.elementor-widget-gg_package_shop,
.elementor-widget-gg_services_showcase,
.elementor-widget-gg_sessions_list,
.elementor-widget-gg_class_card,
.elementor-widget-gg_client_dashboard,
.elementor-widget-gg_instructor_dashboard,
.elementor-widget-gg_instructor_profile,
.elementor-widget-gg_booking_form,
.elementor-widget-gg_login,
.elementor-widget-gg_password_reset,
.elementor-widget-gg_appointment_booking {
	align-self: stretch;
}

.gg-booking-class-card__title,
.gg-booking-sessions-card__title,
.gg-booking-sessions-list__class-name,
.gg-booking-schedule-card__title,
.gg-booking-instructor-profile__name,
.gg-booking-package-card__title,
.gg-booking-dashboard__section-title,
.gg-booking-dashboard__client-name {
	font-family: var( --gg-type-heading );
}

/* ----------------------------------------------------------------------- */
/* Elementor alignment CSS variables                                       */
/* ----------------------------------------------------------------------- */
/* Elementor Pro 4.x writes the alignment control value as a CSS variable  */
/* on the {{WRAPPER}} element via selectors_dictionary. These rules        */
/* consume those variables to drive flex alignment on containers that      */
/* don't respect text-align (flex parents laying out children with         */
/* align-items, justify-content, or align-self).                           */

.gg-booking-instructor-profile {
	align-items: var( --gg-instructor-align, flex-start );
}

.gg-booking-instructor-profile__photo,
.gg-booking-instructor-profile__photo-placeholder {
	align-self: var( --gg-photo-align, auto );
}

.gg-booking-instructor-profile__name {
	align-self: var( --gg-name-align, auto );
}

.gg-booking-instructor-profile__actions {
	align-self: var( --gg-btn-align, auto );
}

.gg-booking-owned-actions {
	align-items: var( --gg-owned-align, flex-start );
}

.gg-booking-sessions-list__instructor {
	justify-content: var( --gg-list-instructor-align, flex-start );
}

.gg-booking-class-card__instructor {
	justify-content: var( --gg-card-instructor-align, flex-start );
}

/* ----------------------------------------------------------------------- */
/* Dashboard tabs                                                          */
/* ----------------------------------------------------------------------- */

.gg-booking-dashboard__tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	border-bottom: 2px solid var( --gg-color-border );
	margin-bottom: 24px;
	justify-content: var( --gg-tabs-justify, flex-start );
}

.gg-booking-dashboard__tab {
	background: none;
	border: none;
	border-bottom: 2px solid transparent;
	margin-bottom: 6px;
	padding: 10px 20px;
	font-size: 14px;
	font-weight: 500;
	color: var( --gg-color-text-muted );
	cursor: pointer;
	transition: color 0.15s ease, border-color 0.15s ease;
}

.gg-booking-dashboard__tab:hover {
	color: var( --gg-color-text );
}

.gg-booking-dashboard__tab--active {
	color: var( --gg-color-primary );
	border-bottom-color: var( --gg-color-primary );
}

.gg-booking-dashboard__panel--hidden {
	display: none;
}

/* ----------------------------------------------------------------------- */
/* Instructor Dashboard tabs + profile                                     */
/* ----------------------------------------------------------------------- */

.gg-booking-instructor-dashboard__tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	border-bottom: 2px solid var( --gg-color-border );
	margin-bottom: 24px;
}

.gg-booking-instructor-dashboard__tab {
	background: none;
	border: none;
	border-bottom: 2px solid transparent;
	margin-bottom: 6px;
	padding: 10px 20px;
	font-size: 14px;
	font-weight: 500;
	color: var( --gg-color-text-muted );
	cursor: pointer;
	transition: color 0.15s ease, border-color 0.15s ease;
}

.gg-booking-instructor-dashboard__tab:hover {
	color: var( --gg-color-text );
}

.gg-booking-instructor-dashboard__tab--active {
	color: var( --gg-color-primary );
	border-bottom-color: var( --gg-color-primary );
}

.gg-booking-instructor-dashboard__panel--hidden {
	display: none;
}

.gg-booking-instructor-profile-form {
	max-width: 560px;
}

.gg-booking-instructor-profile-form .gg-booking-profile-section + .gg-booking-profile-section {
	margin-top: 24px;
}

.gg-booking-instructor-profile-form .gg-booking-profile-field {
	margin-bottom: 16px;
}

.gg-booking-instructor-profile-form .gg-booking-profile-field label {
	display: block;
	font-size: 13px;
	font-weight: 500;
	color: var( --gg-color-text );
	margin-bottom: 6px;
}

.gg-booking-instructor-profile-form input[type="text"],
.gg-booking-instructor-profile-form textarea,
.gg-booking-instructor-profile-form select {
	width: 100%;
	padding: 8px 10px;
	border: 1px solid var( --gg-color-border );
	border-radius: 4px;
	font-size: 14px;
	font-family: inherit;
	background: var( --gg-color-background );
	color: var( --gg-color-text );
}

.gg-booking-instructor-profile-form .gg-booking-instructor-specialty {
	margin-bottom: 6px;
}

.gg-booking-instructor-profile-form .gg-booking-profile-actions {
	margin-top: 20px;
	display: flex;
	align-items: center;
	gap: 12px;
}

.gg-booking-instructor-profile-form .gg-booking-profile-feedback {
	font-size: 13px;
}

/* ----------------------------------------------------------------------- */
/* Instructor Dashboard — schedule panel + session cards                   */
/* Folded in from the former standalone assets/elementor/css/              */
/* instructor-dashboard.css at v1.1.65 — it was the ONLY widget with its    */
/* own separate stylesheet; every widget's CSS now lives in this one file.  */
/* Element-alignment vars default to flex-start; the Element Alignment      */
/* style controls set them via selectors_dictionary (rule 30).             */
/* ----------------------------------------------------------------------- */

.gg-booking-instructor-dashboard {
	--gg-header-align:         flex-start;
	--gg-session-header-align: flex-start;
	--gg-meta-align:           flex-start;
	--gg-logout-align:         flex-end;

	font-family: var( --gg-type-body );
	color: var( --gg-color-text );
	/* No max-width here — the widget's reading-width default is the standard
	   dashboard Widget Frame cap (--gg-widget-max-width, :root 64rem on
	   .gg-booking-widget-inner; rule 122), which the per-instance Max Width
	   control overrides. The old hard 680px inner cap fought the Frame:
	   above the cap the content stuck at that width and, having no auto-
	   margins, pinned left and ignored both Max Width and Alignment. Removed
	   v1.1.65 so the Frame is the single width+placement authority — matching
	   every other widget (Class Card, Schedule, etc.). */
}

.gg-booking-instructor-dashboard__header {
	display: flex;
	align-items: center;
	justify-content: var( --gg-header-align );
	gap: 12px;
	margin-bottom: 24px;
}

.gg-booking-instructor-dashboard__greeting {
	font-family: var( --gg-type-heading );
	font-size: 1.4rem;
	font-weight: 600;
	color: var( --gg-color-text );
	margin: 0;
}

.gg-booking-instructor-dashboard__window {
	font-size: 0.85rem;
	color: var( --gg-color-text-muted );
}

/* Self-serve schedule range filter — the window label is a <details> dropdown. */
.gg-booking-instructor-dashboard__range {
	position: relative;
	margin-left: auto; /* push to the far end of the header row */
}

.gg-booking-instructor-dashboard__range-trigger {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	cursor: pointer;
	list-style: none;
	user-select: none;
	padding: 4px 10px;
	border: 1px solid var( --gg-color-border );
	border-radius: 6px;
}

/* Remove the native disclosure triangle; supply our own caret. */
.gg-booking-instructor-dashboard__range-trigger::-webkit-details-marker {
	display: none;
}

.gg-booking-instructor-dashboard__range-trigger::after {
	content: "";
	width: 0;
	height: 0;
	border-left: 4px solid transparent;
	border-right: 4px solid transparent;
	border-top: 5px solid currentColor;
	transition: transform 0.15s ease;
}

.gg-booking-instructor-dashboard__range[open] .gg-booking-instructor-dashboard__range-trigger::after {
	transform: rotate( 180deg );
}

.gg-booking-instructor-dashboard__range-menu {
	position: absolute;
	right: 0;
	top: calc( 100% + 4px );
	z-index: 20;
	min-width: 220px;
	padding: 6px;
	background: var( --gg-color-background );
	border: 1px solid var( --gg-color-border );
	border-radius: 8px;
	box-shadow: 0 4px 16px rgba( 0, 0, 0, 0.12 );
}

.gg-booking-instructor-dashboard__range-option {
	display: block;
	padding: 8px 10px;
	border-radius: 5px;
	color: var( --gg-color-text );
	text-decoration: none;
	font-size: 0.9rem;
}

.gg-booking-instructor-dashboard__range-option:hover,
.gg-booking-instructor-dashboard__range-option:focus {
	background: var( --gg-color-surface, rgba( 0, 0, 0, 0.04 ) );
}

.gg-booking-instructor-dashboard__range-option--active {
	font-weight: 600;
	color: var( --gg-color-primary );
}

.gg-booking-instructor-dashboard__range-custom {
	margin-top: 6px;
	padding: 10px 10px 4px;
	border-top: 1px solid var( --gg-color-border );
}

.gg-booking-instructor-dashboard__range-custom-label {
	display: block;
	margin-bottom: 6px;
	font-size: 0.8rem;
	font-weight: 600;
	color: var( --gg-color-text-muted );
}

.gg-booking-instructor-dashboard__range-custom-row {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 8px;
}

.gg-booking-instructor-dashboard__range-date {
	flex: 1;
	min-width: 0;
	padding: 6px 8px;
	border: 1px solid var( --gg-color-border );
	border-radius: 6px;
	background: var( --gg-color-background );
	color: var( --gg-color-text );
	font: inherit;
}

.gg-booking-instructor-dashboard__range-sep {
	color: var( --gg-color-text-muted );
}

.gg-booking-instructor-dashboard__range-apply {
	width: 100%;
}

.gg-booking-instructor-dashboard__session {
	background: var( --gg-color-background );
	border: 1px solid var( --gg-color-border );
	border-radius: 10px;
	padding: 20px;
	margin-bottom: 16px;
	box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.06 );
}

.gg-booking-instructor-dashboard__session-header {
	display: flex;
	align-items: flex-start;
	justify-content: var( --gg-session-header-align );
	gap: 12px;
	margin-bottom: 10px;
}

.gg-booking-instructor-dashboard__class-name {
	font-family: var( --gg-type-heading );
	font-size: 1.1rem;
	font-weight: 600;
	color: var( --gg-color-text );
	margin: 0;
}

.gg-booking-instructor-dashboard__class-name a {
	color: inherit;
	text-decoration: none;
	border-bottom: 1px dotted currentColor;
}

.gg-booking-instructor-dashboard__class-name a:hover {
	color: var( --gg-color-primary );
	border-bottom-style: solid;
}

.gg-booking-instructor-dashboard__enrolled-badge {
	background: var( --gg-color-primary );
	color: var( --gg-color-background );
	font-size: 0.8rem;
	font-weight: 600;
	padding: 4px 10px;
	border-radius: 20px;
	white-space: nowrap;
	flex-shrink: 0;
}

.gg-booking-instructor-dashboard__meta {
	display: flex;
	flex-wrap: wrap;
	justify-content: var( --gg-meta-align );
	gap: 8px 16px;
	font-size: 0.9rem;
	color: var( --gg-color-text-muted );
	margin-bottom: 16px;
}

.gg-booking-instructor-dashboard__meta span::before {
	margin-right: 4px;
}

.gg-booking-instructor-dashboard__empty {
	text-align: center;
	padding: 40px 20px;
	color: var( --gg-color-text-muted );
}

/* Editor preview — sample dashboard */
.gg-booking-instructor-dashboard--editor {
	user-select: none;
}

/* Form fields + the roster <details> toggle stay inert so the sample can't be
   typed into or collapsed while styling (already disabled/readonly in markup;
   this also blocks the native <details> toggle). */
.gg-booking-instructor-dashboard--editor input,
.gg-booking-instructor-dashboard--editor textarea,
.gg-booking-instructor-dashboard--editor select,
.gg-booking-instructor-dashboard--editor summary {
	pointer-events: none;
}

/* Buttons + links stay hoverable so their Normal / Hover Style controls preview
   live in the canvas (matches the Client Dashboard). */
.gg-booking-instructor-dashboard--editor .gg-booking-btn {
	cursor: default;
}

@media ( max-width: 480px ) {
	.gg-booking-instructor-dashboard__session-header {
		flex-direction: column;
		align-items: flex-start;
	}
}

/* ----------------------------------------------------------------------- */
/* Instructor Dashboard — roster + check-in                                */
/* ----------------------------------------------------------------------- */

.gg-booking-instructor-dashboard__roster {
	margin-top: 12px;
	border-top: 1px solid var( --gg-color-border );
	padding-top: 12px;
}

.gg-booking-instructor-dashboard__roster-heading {
	font-size: 14px;
	font-weight: 600;
	color: var( --gg-color-text );
	cursor: pointer;
	list-style: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.gg-booking-instructor-dashboard__roster-heading::-webkit-details-marker {
	display: none;
}

.gg-booking-instructor-dashboard__roster-heading::before {
	content: "▸";
	font-size: 11px;
	color: var( --gg-color-text-muted );
	transition: transform 0.15s ease;
	display: inline-block;
}

.gg-booking-instructor-dashboard__roster[open] .gg-booking-instructor-dashboard__roster-heading::before {
	transform: rotate(90deg);
}

.gg-booking-instructor-dashboard__roster-count {
	color: var( --gg-color-text-muted );
	font-weight: 400;
}

.gg-booking-instructor-dashboard__roster-list {
	list-style: none;
	margin: 12px 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.gg-booking-roster-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-rows: auto auto;
	column-gap: 12px;
	row-gap: 6px;
	align-items: center;
	padding: 8px 10px;
	background: var( --gg-color-background );
	border: 1px solid var( --gg-color-border );
	border-radius: 4px;
	font-size: 14px;
}

.gg-booking-roster-row__name {
	grid-column: 1;
	grid-row: 1;
	font-weight: 500;
	color: var( --gg-color-text );
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.gg-booking-roster-row__status {
	/* Mobile: the status pill sits UNDER the name (left column, row 2) so the
	   action buttons get the whole right column. justify-self:start keeps it
	   pill-sized instead of stretching across the 1fr column. The ≥640px
	   block restores it to the inline name | status | actions row. */
	grid-column: 1;
	grid-row: 2;
	justify-self: start;
	font-size: 12px;
	font-weight: 500;
	padding: 3px 8px;
	border-radius: 999px;
	white-space: nowrap;
}

.gg-booking-roster-row__status--pending {
	background: color-mix( in srgb, var( --gg-color-text-muted ) 15%, transparent );
	color: var( --gg-color-text-muted );
}

.gg-booking-roster-row__status--attended {
	background: color-mix( in srgb, var( --gg-color-success ) 18%, transparent );
	color: var( --gg-color-success );
}

.gg-booking-roster-row__status--no_show {
	background: color-mix( in srgb, var( --gg-color-error ) 18%, transparent );
	color: var( --gg-color-error );
}

.gg-booking-roster-row__status--late_cancel {
	background: color-mix( in srgb, var( --gg-color-accent ) 20%, transparent );
	color: var( --gg-color-accent );
}

.gg-booking-roster-row__actions {
	/* Mobile: buttons stack vertically in the right column, spanning both
	   rows (alongside the name + status stack). align-items:stretch gives a
	   tidy equal-width button column. The ≥640px block flips this back to a
	   single horizontal row. */
	grid-column: 2;
	grid-row: 1 / -1;
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 4px;
}

/* Roster action buttons are deliberately more compact than the global
   .gg-booking-btn — they're inline row actions, not primary CTAs, so keep them
   from dominating the client-name column. Studios can still override via
   the Elementor "Row Action Buttons" style controls. */
.gg-booking-roster-row__action.gg-booking-btn {
	padding: 4px 8px;
	font-size: 11px;
	line-height: 1.2;
	min-height: 0;
	white-space: nowrap;
}

@media (min-width: 640px) {
	.gg-booking-roster-row {
		grid-template-columns: minmax(0, 1fr) auto auto;
		grid-template-rows: auto;
	}

	.gg-booking-roster-row__status {
		grid-column: 2;
		grid-row: 1;
	}

	.gg-booking-roster-row__actions {
		grid-column: 3;
		grid-row: 1;
		flex-direction: row;
		align-items: center;
		flex-wrap: nowrap;
	}
}

.gg-booking-instructor-dashboard__roster-empty {
	font-size: 13px;
	color: var( --gg-color-text-muted );
	margin: 8px 0 0;
	font-style: italic;
}

/* ----------------------------------------------------------------------- */
/* Walk-in form                                                            */
/* ----------------------------------------------------------------------- */

.gg-booking-walkin {
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px dashed var( --gg-color-border );
}

.gg-booking-walkin__toggle {
	font-size: 13px;
}

.gg-booking-walkin__form {
	margin-top: 12px;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/* HTML5 `hidden` defaults to display:none, but the rule above sets
   display:flex which silently overrides it. Restore the collapse. */
.gg-booking-walkin__form[hidden] {
	display: none;
}

.gg-booking-walkin__row {
	display: grid;
	grid-template-columns: 1fr;
	gap: 10px;
}

@media (min-width: 560px) {
	.gg-booking-walkin__row {
		grid-template-columns: 1fr 1fr;
	}
}

.gg-booking-walkin__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 13px;
	color: var( --gg-color-text );
}

.gg-booking-walkin__field span {
	font-weight: 500;
}

.gg-booking-walkin__field input {
	padding: 8px 10px;
	border: 1px solid var( --gg-color-border );
	border-radius: 4px;
	font-size: 14px;
	font-family: inherit;
	background: var( --gg-color-background );
	color: var( --gg-color-text );
}

.gg-booking-walkin__field input:focus {
	outline: none;
	border-color: var( --gg-color-primary );
	/* Brand-tracking focus ring (rule 46), aligned with the other form fields. */
	box-shadow: 0 0 0 3px rgba( 92, 122, 92, 0.15 );
	box-shadow: 0 0 0 3px color-mix( in srgb, var( --gg-color-primary ) 20%, transparent );
}

.gg-booking-walkin__override {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	color: var( --gg-color-error );
	padding: 8px 10px;
	border: 1px solid color-mix( in srgb, var( --gg-color-error ) 30%, transparent );
	border-radius: 4px;
	background: color-mix( in srgb, var( --gg-color-error ) 8%, transparent );
}

.gg-booking-walkin__actions {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
}

.gg-booking-walkin__feedback {
	font-size: 13px;
	display: none;
}

/* ----------------------------------------------------------------------- */
/* Dashboard logout                                                        */
/* ----------------------------------------------------------------------- */

.gg-booking-dashboard__logout,
.gg-booking-instructor-dashboard__logout {
	margin-top: 24px;
	padding-top: 20px;
	border-top: 1px solid var( --gg-color-border );
	display: flex;
	justify-content: flex-end;
}

/* ----------------------------------------------------------------------- */
/* Profile form                                                            */
/* ----------------------------------------------------------------------- */

.gg-booking-profile-form {
	max-width: 560px;
}

.gg-booking-profile-section {
	margin-bottom: 28px;
	padding-bottom: 28px;
	border-bottom: 1px solid var( --gg-color-border );
}

.gg-booking-profile-section:last-of-type {
	border-bottom: none;
}

.gg-booking-profile-section h4 {
	font-size: 13px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var( --gg-color-text-muted );
	margin: 0 0 16px;
}

.gg-booking-profile-photo {
	display: flex;
	align-items: center;
	gap: 20px;
	margin-bottom: 28px;
	padding-bottom: 28px;
	border-bottom: 1px solid var( --gg-color-border );
}

.gg-booking-profile-photo__preview {
	width: 80px;
	height: 80px;
	border-radius: 50%;
	overflow: hidden;
	background: var( --gg-surface );
	border: 2px solid var( --gg-color-border );
	flex-shrink: 0;
}

.gg-booking-profile-photo__preview img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.gg-booking-profile-photo__placeholder {
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var( --gg-color-text-muted );
	font-size: 32px;
}

.gg-booking-profile-photo__hint {
	font-size: 12px;
	color: var( --gg-color-text-muted );
	margin: 4px 0 0;
}

.gg-booking-profile-actions {
	display: flex;
	align-items: center;
	margin-top: 24px;
}

.gg-booking-field-hint {
	font-size: 12px;
	color: var( --gg-color-text-muted );
	margin: 4px 0 0;
}

/* ==========================================================================
   Calendar Widget — FullCalendar host
   ========================================================================== */

.gg-booking-calendar {
    --gg-cal-font: inherit;
    font-family: var( --gg-cal-font );
}

/* Month-range title = brand/palette accent by default. (0,2,0) beats Elementor's
   Kit `.elementor-kit-N h2` (0,1,1) — which otherwise repaints this <h2> with the
   Kit's sage-green secondary default — and FullCalendar's own `.fc-toolbar-title`
   (0,1,0). NOT !important, so the widget's "Title Color" control ({{WRAPPER}}…,
   higher specificity) still overrides it. Global (not the mobile-only block where
   this lived before, which never applied on desktop). */
.gg-booking-calendar .fc-toolbar-title {
    color: var( --gg-color-primary, var(--gg-color-primary) );
}

/* Calendar surface defaults — FullCalendar reads these --fc-* vars natively and
   injects its OWN `.fc { --fc-border-color: #ddd }` defaults at runtime (after
   this stylesheet on the live page), so the override must out-specify `.fc`
   (0,1,0). The container carries BOTH classes once FC boots, so
   `.gg-booking-calendar.fc` (0,2,0) wins regardless of load order — and matches
   in the editor too (real FC now renders there). Defaults the grid lines to the
   Gather Grove border token so the calendar matches the card/list surfaces out
   of the box; the Schedule widget's "Calendar Surface" style controls override
   it at the same (0,2,0) via {{WRAPPER}} (Elementor inline CSS loads later). */
.gg-booking-calendar.fc {
    --fc-border-color: var( --gg-color-border, #e8e3d8 );
}

/* Day-cell + week-column backgrounds (Schedule widget "Calendar Surface" +
   "Calendar Week" controls). The cells are transparent in FullCalendar, so any
   grey is the host theme showing through; these rules paint them from the
   widget's --gg-cal-* vars. (0,2,0) base via `.gg-booking-calendar.fc` keeps
   them authoritative; :not(.fc-day-today) leaves the Today highlight on top.
   The Week column-stripe falls back to --gg-cal-cell-bg on the non-striped
   parity so toggling even/odd never re-exposes the theme grey. Default unset =
   transparent (current look preserved until the studio picks a colour). */
.gg-booking-calendar.fc .fc-daygrid-day:not(.fc-day-today) {
    background-color: var( --gg-cal-cell-bg, transparent );
}
.gg-booking-calendar.fc .fc-timegrid-col:nth-child(even):not(.fc-day-today) {
    background-color: var( --gg-cal-week-stripe-even, var( --gg-cal-cell-bg, transparent ) );
}
.gg-booking-calendar.fc .fc-timegrid-col:nth-child(odd):not(.fc-day-today) {
    background-color: var( --gg-cal-week-stripe-odd, var( --gg-cal-cell-bg, transparent ) );
}

.gg-booking-calendar .fc-button,
.gg-booking-calendar .fc-button-primary {
    background-color: var( --gg-color-primary, var(--gg-color-primary) );
    border-color:     var( --gg-color-primary, var(--gg-color-primary) );
    color: var(--gg-color-surface);
    font-size: 0.85rem;
    padding: 0.35em 0.75em;
    border-radius: 4px;
    /* (0,2,0) text-transform:none beats Elementor's global Kit button rule
       `.elementor-kit-N button { text-transform:uppercase }` (0,1,1). Live FC
       loads its own button reset so this is a no-op there, but in the editor
       FC's CSS isn't enqueued (static mock), so without this the mock toolbar
       renders UPPERCASE while live stays lowercase. Studio typography controls
       (0,3,0) still override. See [[elementor-kit-button-bodymounted-gotcha]]. */
    text-transform: none;
    transition: background 0.2s;
}

.gg-booking-calendar .fc-button-primary:hover,
.gg-booking-calendar .fc-button-primary:focus {
    background-color: var( --gg-color-secondary, var(--gg-color-primary) );
    border-color:     var( --gg-color-secondary, var(--gg-color-primary) );
}

.gg-booking-calendar .fc-button-primary:not(:disabled).fc-button-active {
    background-color: var( --gg-color-secondary, var(--gg-color-primary) );
    border-color:     var( --gg-color-secondary, var(--gg-color-primary) );
}

/* Disabled (e.g. the Today button on the current period) — FC greys it on live;
   mirror that here so the editor placeholder mock (where FC's CSS isn't loaded)
   shows the same greyed state. */
.gg-booking-calendar .fc-button-primary:disabled {
    opacity: 0.65;
    cursor: default;
}

/* FullCalendar v6 INJECTS its own button stylesheet at runtime (padding +
   font-size:1em + font handling). That injected CSS exists only on the LIVE
   calendar (where FC initializes), never in the editor placeholder mock — so
   live toolbar buttons render bigger + a different size/font than the editor.
   Pin our sizing/font at (0,3,0) — every FC button carries BOTH .fc-button and
   .fc-button-primary — so our values win over FC's injected base on live and
   match the editor preview. The studio's Calendar Toolbar typography/padding
   controls ({{WRAPPER}} …, also ≥0,3,0, injected after this sheet) still
   override by source order. */
.gg-booking-calendar .fc-button.fc-button-primary {
    font-family: var( --gg-type-body );
    font-size: 0.85rem;
    /* font-weight + letter-spacing pinned too: without them the editor inherits
       Elementor's Kit `button { font-weight:600; letter-spacing:1.5px }` (no
       override there) → bold + spaced, while live FC's reset forces them normal
       → the "font looks different" mismatch. A deliberate medium weight here
       makes both agree; studio toolbar typography (≥0,3,0) still overrides. */
    font-weight: 500;
    letter-spacing: normal;
    line-height: 1.5;
    padding: 0.35em 0.75em;
}

/* Toolbar button spacing — single source of truth shared by live FullCalendar
   AND the editor placeholder mock (which reads the same var), so the toolbar
   looks identical in both. Driven by the "Button Spacing" control
   (--gg-cal-toolbar-button-gap on the widget wrapper). The headerToolbar config
   now uses SPACE-separated tokens (not comma), so FC renders every button
   standalone (no .fc-button-group welding) — they're all direct chunk children,
   so this flex `gap` spaces ALL of them into individual pills. (Comma grouping
   was the cause of "editor spaced, live touching"; fixed in the JS config.) */
.gg-booking-calendar .fc-toolbar-chunk {
    display: flex;
    align-items: center;
    gap: var( --gg-cal-toolbar-button-gap, 6px );
}

/* Neutralise FullCalendar v6's runtime-injected default margin between toolbar
   items (`.fc-toolbar > * > :not(:first-child) { margin-left: .75em }`). That
   margin stacks ON TOP of the flex `gap` above, so it acted as a ~12px floor:
   dragging "Button Spacing" to 0 still left the items ~12px apart on the LIVE
   calendar (the editor mock never had this margin, so editor↔live also drifted).
   Zeroing it makes --gg-cal-toolbar-button-gap the single source of truth, so 0
   means touching. Specificity (0,4,0) beats FC's injected (0,3,0) rule
   regardless of stylesheet load order; margin-right covers the RTL variant. */
.gg-booking-calendar.fc .fc-toolbar > * > :not(:first-child) {
    margin-left: 0;
    margin-right: 0;
}

/* Month view events — rendered as colored rectangles (one per class).
   Background-color + border-color are applied inline per-event by
   gg-booking-schedule-calendar.js in eventDidMount so the class color shows
   reliably across all views. This rule only handles typography + spacing. */
.gg-booking-calendar .fc-daygrid-event {
    border-radius: 3px;
    font-size: 0.72rem;
    font-weight: 500;
    padding: 1px 5px;
    margin: 1px 2px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var( --gg-class-event-text, var(--gg-color-surface) );
}

.gg-booking-calendar .fc-daygrid-event .fc-event-main,
.gg-booking-calendar .fc-daygrid-event .fc-event-title {
    color: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Hide the internal FullCalendar dot + time in Month view so the full block
   acts as the class-color rectangle (defensive against cached JS). */
.gg-booking-calendar .fc-daygrid-event .fc-daygrid-event-dot {
    display: none;
}

.gg-booking-calendar .fc-daygrid-event .fc-event-time {
    display: none;
}

/* Week view blocks — keep FullCalendar's block layout, inherit event text color. */
.gg-booking-calendar .fc-timegrid-event,
.gg-booking-calendar .fc-timegrid-event .fc-event-main {
    color: var( --gg-class-event-text, var(--gg-color-surface) );
}

.gg-booking-cal-event--full {
    opacity: 0.65;
}

.gg-booking-calendar .fc-today-button {
    text-transform: capitalize;
}

/* ==========================================================================
   Calendar Popover — desktop anchored
   ========================================================================== */

/* The calendar popover is body-mounted on the live frontend (appendChild to
   document.body in gg-booking-schedule-calendar.js), so it renders OUTSIDE the
   Elementor widget wrapper. The Style controls emit a paired selector
   ({{WRAPPER}} .x, .x); on live only the unscoped (0,1,0) half can match. To
   keep these defaults from tying that half on specificity (and winning on load
   order — the bug where live reverted to default padding/radius/colour while
   the editor looked correct), every control-targeted popover default is wrapped
   in :where() so it carries ZERO specificity. Defaults still apply when no
   control is set; any control — editor (0,2,0) or live (0,1,0) — always wins.
   Modifier rules (--open / --drawer / --preview) keep their real specificity so
   they still override the zeroed base. */
:where(.gg-booking-cal-popover) {
    position: absolute;
    z-index: 99999;
    width: 300px;
    background: var(--gg-color-surface);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba( 0,0,0,0.18 ), 0 2px 8px rgba( 0,0,0,0.10 );
    overflow: hidden;
    font-size: 0.9rem;
    /* Enter/exit handled via .gg-booking-cal-popover--open toggled by JS so the
       same transition plays on the way out. */
    opacity: 0;
    transform: translateY( 8px );
    transition: opacity 0.32s ease, transform 0.32s cubic-bezier( 0.16, 1, 0.3, 1 );
}

.gg-booking-cal-popover.gg-booking-cal-popover--open {
    opacity: 1;
    transform: translateY( 0 );
}

/* Class color strip — top edge of the popover. Always rendered (split
   out of the header to live above the optional featured image). */
.gg-booking-cal-popover__color-strip {
    height: 4px;
    width: 100%;
}

/* Featured image banner — only rendered when Show Featured Image is on
   and the class has a thumbnail. Defaults are tuned for a 300px-wide
   popover; studios override via Calendar Popover Style controls. */
.gg-booking-cal-popover__image {
    display: flex;
    justify-content: var( --gg-cal-popover-image-align, center );
    overflow: hidden;
}

:where(.gg-booking-cal-popover__image img) {
    display: block;
    width: var( --gg-cal-popover-image-size, 100% );
    max-width: none;
    aspect-ratio: var( --gg-cal-popover-image-ratio, 16 / 9 );
    height: var( --gg-cal-popover-image-height, auto );
    object-fit: var( --gg-cal-popover-image-fit, cover );
    object-position: var( --gg-cal-popover-image-position, center center );
}

.gg-booking-cal-popover__header {
    padding: 14px 14px 10px;
    border-bottom: 1px solid var(--gg-color-background);
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

:where(.gg-booking-cal-popover__title) {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
    color: var( --gg-color-heading, var(--gg-color-text) );
    flex: 1;
}

/* Container-scoped (0,2,0) base — `.gg-booking-cal-popover .…__close`, NOT a bare
   single class or `:where()`. The popover is body-mounted (`document.body`), so
   on the LIVE front end it inherits whatever the page's `<body>` carries — and
   the load-bearing villain turned out to be Elementor's OWN global Kit button
   style: `.elementor-kit-N button { background:var(--e-global-color-accent);
   padding:12px 24px; box-shadow; border-radius; text-transform:uppercase }` at
   specificity (0,1,1). A host theme's bare `button {}` reset (e.g. Hello
   Elementor, 0,0,1) is the lesser cousin. A 0,1,0 base (or `:where()` 0,0,0) is
   out-specified by (0,1,1) → the close button got repainted with the Kit's
   accent box + 24px padding (the "tan box"). The editor looked fine because there
   the IconButtonControls `{{WRAPPER}}` selector is (0,2,0) and wins — but on the
   body-mounted popover `{{WRAPPER}}` doesn't match, only the unscoped control
   (now also scoped to .gg-booking-cal-popover, 0,2,0) and this base do. (0,2,0)
   beats the Kit's (0,1,1); the control ties at (0,2,0) and wins by source order
   (Elementor's post CSS loads after this sheet) so studio overrides still win;
   `{{WRAPPER}}` (also 0,2,0) covers the in-widget editor preview. `appearance` +
   `min-*` + `box-shadow:none` + `border:none` + `border-radius:0` neutralize the
   full Kit/UA/theme button chrome. The (0,2,0) `--preview` reset below still
   governs the editor canvas's atomic baseline. */
.gg-booking-cal-popover .gg-booking-cal-popover__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    -webkit-appearance: none;
    appearance: none;
    min-width: 0;
    min-height: 0;
    background: var( --gg-popover-close-bg, none );
    border: none;
    border-radius: 0;
    box-shadow: none;
    cursor: pointer;
    font-size: var( --gg-popover-close-size, 1.2rem );
    line-height: 0;
    color: var( --gg-popover-close-color, var(--gg-color-text) );
    padding: 2px;
    flex-shrink: 0;
    transition: color 0.15s, background-color 0.15s;
}

/* SVG glyph (replaces the &times; text character). Sized in `em` so the Icon
   Size control (font-size) scales it; `currentColor` so the Icon Color control
   (color) drives the stroke. Unlike a text glyph it carries no font line-box
   whitespace, so at Padding 0 the box hugs the ✕ exactly (a bg + radius then
   reads as a clean circle, not a tall pill). Container-scoped (0,2,0) so it
   survives the Kit/theme button cascade on the body-mounted popover. */
.gg-booking-cal-popover .gg-booking-cal-popover__close-icon {
    width: 1em;
    height: 1em;
    display: block;
    flex-shrink: 0;
}

.gg-booking-cal-popover .gg-booking-cal-popover__close:hover,
.gg-booking-cal-popover .gg-booking-cal-popover__close:focus {
    color: var( --gg-popover-close-hover-color, var(--gg-color-text) );
    background: var( --gg-popover-close-hover-bg, var(--gg-color-border) );
}

/* Editor-only: the Elementor canvas e_atomic_elements baseline paints bare
   <button>s with an accent box (bg + border + radius + min-height), so the
   popover close "×" renders as a tall rounded box in the editor preview — even
   with Padding set to 0, since min-height/appearance drive the height, not
   padding. Live is always correct (no atomic baseline there). Scope the reset
   to the editor-only `--preview` popover (the live JS-built popover never carries
   `--preview`) so it can't touch the live body-mounted popover or a studio's
   IconButtonControls overrides. Specificity (0,2,0) beats the atomic baseline;
   the studio's controls ({{WRAPPER}} …, also (0,2,0), injected inline after this
   sheet) still win the tie by source order, so the preview stays WYSIWYG. Same
   root cause as the .gg-booking-btn brand-colour note above and the
   login/register toggle reset below. */
.gg-booking-cal-popover--preview .gg-booking-cal-popover__close {
    -webkit-appearance: none;
    appearance: none;
    min-height: 0;
    min-width: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    /* The atomic baseline also sets the button text COLOR (a muted gray), which
       the SVG ✕ inherits via currentColor — so pin the real default colour here
       too (0,2,0 beats the baseline; a studio's Icon Color control, {{WRAPPER}}
       … also 0,2,0 injected after this sheet, still wins by source order). */
    color: var( --gg-popover-close-color, var(--gg-color-text) );
}

.gg-booking-cal-popover__body {
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

:where(.gg-booking-cal-popover__badges) {
    display: flex;
    gap: var( --gg-cal-popover-badges-gap, 6px );
    flex-wrap: wrap;
}

:where(.gg-booking-cal-popover__when) {
    font-weight: 500;
    color: var( --gg-color-text, var(--gg-color-text-muted) );
    display: flex;
    align-items: center;
    gap: 8px;
}

:where(.gg-booking-cal-popover__duration) {
    font-size: 0.78rem;
    color: var(--gg-color-text-muted);
    font-weight: 400;
}

:where(.gg-booking-cal-popover__instructor) {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--gg-color-text-muted);
}

.gg-booking-cal-popover__photo {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

:where(.gg-booking-cal-popover__location) {
    color: var(--gg-color-text-muted);
    font-size: 0.85rem;
}

/* Linked instructor / location names in the popover (feedback #9) — inherit the
   row colour, underline on hover so they read as clickable. Body-mounted popover,
   so the selectors are unscoped (rule: paired/unscoped popover selectors). */
.gg-booking-cal-popover__instructor a,
.gg-booking-cal-popover__location a,
.gg-booking-cal-popover__room a {
    color: inherit;
    text-decoration: none;
}

.gg-booking-cal-popover__instructor a:hover,
.gg-booking-cal-popover__location a:hover,
.gg-booking-cal-popover__room a:hover {
    color: var(--gg-color-primary, #254032);
    text-decoration: underline;
}

/* Price — mirrors the card/list price weight; :where() so the Popover Price
   Style controls (paired selector) win on the live body-mounted popover. */
:where(.gg-booking-cal-popover__price) {
    font-weight: 600;
    color: var( --gg-color-text, var(--gg-color-text-muted) );
}

:where(.gg-booking-cal-popover__desc) {
    margin: 0;
    color: var(--gg-color-text-muted);
    font-size: 0.83rem;
    line-height: 1.5;
}

:where(.gg-booking-cal-popover__capacity) {
    margin-top: 2px;
}

.gg-booking-cal-popover__waitlist {
    font-size: 0.78rem;
    color: var(--gg-color-text-muted);
    margin-left: 6px;
}

.gg-booking-cal-popover__footer {
    padding: 10px 14px 14px;
    display: flex;
    align-items: center;
    gap: 12px;
    border-top: 1px solid var(--gg-color-background);
}

.gg-booking-cal-popover__book {
    flex: 1;
    text-align: center;
}

.gg-booking-cal-popover__view-link {
    font-size: 0.83rem;
    color: var( --gg-color-primary, var(--gg-color-primary) );
    text-decoration: none;
    white-space: nowrap;
}

.gg-booking-cal-popover__view-link:hover {
    text-decoration: underline;
}

/* ==========================================================================
   Calendar Popover — mobile bottom drawer
   ========================================================================== */

.gg-booking-cal-popover-backdrop {
    position: fixed;
    inset: 0;
    background: rgba( 0,0,0,0.45 );
    z-index: 99998;
    opacity: 0;
    transition: opacity 0.32s ease;
}

.gg-booking-cal-popover-backdrop.gg-booking-cal-popover-backdrop--open {
    opacity: 1;
}

.gg-booking-cal-popover--drawer {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-width: 100%;
    border-radius: 16px 16px 0 0;
    /* Drawer slides only — opacity stays at 1 to keep the surface opaque
       while it travels. The shared --open class still drives the toggle. */
    opacity: 1;
    transform: translateY( 100% );
    transition: transform 0.42s cubic-bezier( 0.32, 0.72, 0, 1 );
    z-index: 99999;
}

.gg-booking-cal-popover--drawer.gg-booking-cal-popover--open {
    transform: translateY( 0 );
}

.gg-booking-cal-popover--drawer::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    background: var(--gg-color-border);
    border-radius: 2px;
    margin: 10px auto 0;
}

/* ==========================================================================
   Calendar Toolbar — mobile stacking
   The default FullCalendar toolbar (prev/next + title + view-switcher) is
   too wide for phones; the title's date-range string overflows and folds
   awkwardly. Stacking puts the title on its own row above the controls.
   Paired with pickTitleFormat() in gg-booking-schedule-calendar.js which switches
   to a short "Apr 28 – May 4" format at the same 767px breakpoint.
   ========================================================================== */

@media (max-width: 767px) and (orientation: portrait) {
    /* Portrait-only stacking: landscape phones (iPhone SE 667px, etc.)
       fall through to FC's default row layout because their landscape
       width is enough to fit prev/title/view-switcher in one row.
       FullCalendar v6 mounts directly onto our `.gg-booking-calendar` wrapper and
       adds its `.fc` class to the SAME element rather than creating a child
       `.fc` div. Selectors of the form `.gg-booking-calendar .fc .fc-...` (descendant
       chain) therefore never match. Use `.gg-booking-calendar .fc-...` or
       `.gg-booking-calendar.fc .fc-...` instead. !important defends against FC's
       runtime-injected styles + theme h2 typography rules. */
    .gg-booking-calendar .fc-toolbar.fc-header-toolbar {
        display: flex !important;
        flex-direction: column !important;
        align-items: center !important;
        gap: 10px;
    }

    .gg-booking-calendar .fc-toolbar-chunk {
        display: flex !important;
        justify-content: center;
        flex-wrap: nowrap;
        gap: var( --gg-cal-toolbar-button-gap, 6px );
        width: 100% !important;
    }

    .gg-booking-calendar .fc-toolbar-title,
    .gg-booking-calendar h2.fc-toolbar-title {
        font-size: 1.05rem !important;
        line-height: 1.3 !important;
        margin: 0 !important;
        text-align: center;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .gg-booking-calendar .fc-button {
        padding: 6px 10px;
        font-size: 0.85rem;
    }
}

/* Schedule date-filter row stays compact on any small viewport — phones
   in landscape benefit from the same tightening even though the calendar
   toolbar above doesn't need to stack. Hence width-only, no orientation. */
@media (max-width: 767px) {
    .gg-booking-schedule-date-filter {
        gap: 8px;
    }

    .gg-booking-schedule-date-filter__buttons {
        width: 100%;
        justify-content: flex-start;
    }

    .gg-booking-date-btn {
        padding: 6px 12px;
        font-size: 12px;
    }

    .gg-booking-schedule-date-filter__picker {
        width: 100%;
    }
}

/* ==========================================================================
   Calendar Editor Placeholder (Elementor edit mode)
   --------------------------------------------------------------------------
   Popover-only since v1.1.27. The calendar GRID surface boots the real
   FullCalendar in the editor (WYSIWYG since v1.1.23), so the old static
   calendar-grid mock (.gg-booking-cal-mock__*) was removed. This placeholder
   now wraps just the always-visible calendar-popover preview, since the live
   popover is a JS-built, body-mounted element that the real calendar can't
   surface in the editor. The shared .gg-booking-cal-popover styles apply; the
   --preview modifier flattens its live absolute-positioning/transition state.
   ========================================================================== */

.gg-booking-calendar-editor-placeholder {
    border: 2px dashed var(--gg-color-success-soft);
    border-radius: 8px;
    padding: 16px;
    background: var(--gg-color-success-soft);
}

.gg-booking-calendar-editor-placeholder .gg-booking-editor-placeholder__header {
    margin-bottom: 12px;
}

/* Single full-width column wrapping the solo popover preview. (Pre-v1.1.27 this
   also hosted the static calendar-grid mock side-by-side; that mock is gone now
   that the grid surface boots the real FullCalendar.) */
.gg-booking-calendar-editor-placeholder__layout {
    display: block;
}

/* Solo popover surface: cap the width + centre it so the popover reads like the
   real overlay (the .gg-booking-cal-popover--preview base is width:100%, which
   would otherwise stretch the full editor width). */
.gg-booking-calendar-editor-placeholder__popover--solo {
    max-width: 360px;
    margin: 0 auto;
}

/* Popover preview — always-visible, statically positioned. The shared
   .gg-booking-cal-popover styles (color strip, image, header, badges, footer)
   apply automatically. The --preview modifier overrides the absolute
   positioning + transition state used on the live popover so the studio
   sees it laid out flat next to the calendar mock. */
.gg-booking-calendar-editor-placeholder__popover {
    min-width: 0;
}

.gg-booking-calendar-editor-placeholder__popover-label {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--gg-color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 6px;
}

.gg-booking-cal-popover.gg-booking-cal-popover--preview {
    position: relative;
    width: 100%;
    opacity: 1;
    transform: none;
    transition: none;
}

/* Generic preview-label used by editor placeholders (calendar popover
   preview, empty-state preview, etc.) — small caps muted header. */
.gg-booking-editor-placeholder__preview-label {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--gg-color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: 16px 0 6px;
}

/* Extra top gap to separate stacked sub-previews (e.g. the Log In vs Register
   panel labels in the LoginWidget form-state editor preview). Replaces an
   inline margin-top on the placeholder (rule 9). */
.gg-booking-editor-placeholder__preview-label--spaced {
    margin-top: 24px;
}

/* Empty-state preview wrapper — visually separates the always-rendered
   editor preview from the live mock above so studios know it's only
   shown on the frontend when a query returns 0 results. Same pattern
   used for any state-preview wrap in editor placeholders (disabled
   buttons, etc.). */
.gg-booking-editor-placeholder__empty-preview-wrap,
/* ==========================================================================
   Schedule results — loading state
   ========================================================================== */

.gg-booking-schedule-results {
    transition: opacity 0.15s ease;
    min-height: 60px;
}

.gg-booking-schedule-results[data-gg-booking-loading="true"] {
    opacity: 0.5;
    pointer-events: none;
    position: relative;
}

.gg-booking-schedule-results[data-gg-booking-loading="true"]::after {
    content: '';
    position: absolute;
    inset: 0;
    background: transparent;
    cursor: wait;
}

/* ============================================================================
   Membership-restricted class gate (BookingFormWidget)
   ============================================================================ */

.gg-booking-membership-gate {
    border: 2px solid var(--gg-color-border);
    border-radius: 12px;
    padding: 2rem 1.5rem;
    margin: 1rem 0;
    text-align: center;
    background-color: var(--gg-color-background);
    color: var(--gg-color-text);
    font-family: var(--gg-type-body, inherit);
}

.gg-booking-membership-gate--login {
    border-color: var(--gg-color-border);
    background-color: var(--gg-color-background);
}

.gg-booking-membership-gate--members {
    border-color: var(--gg-color-accent);
    background-color: color-mix(in srgb, var(--gg-color-accent) 8%, var(--gg-color-background));
}

.gg-booking-membership-gate__icon {
    font-size: 2.5rem;
    line-height: 1;
    margin-bottom: 0.75rem;
    display: block;
}

.gg-booking-membership-gate__title {
    color: var(--gg-color-text);
    margin: 0 0 0.5rem;
    font-size: 1.4rem;
    font-weight: 600;
    font-family: var(--gg-type-heading, inherit);
}

.gg-booking-membership-gate__message {
    color: var(--gg-color-text-muted);
    margin: 0 auto 1.25rem;
    max-width: 40rem;
    font-size: 1rem;
    line-height: 1.5;
}

.gg-booking-membership-gate__message strong {
    color: var(--gg-color-text);
}

/* Plan deep-link (rule 117 / membership-gate-signpost): each required plan
   links to the Memberships page anchored to that plan. Reads as emphasised
   in-sentence text, underlined on hover. */
.gg-booking-membership-gate__plan-link {
    color: var( --gg-color-primary, var(--gg-color-primary) );
    font-weight: 600;
    text-decoration: none;
}

.gg-booking-membership-gate__plan-link:hover,
.gg-booking-membership-gate__plan-link:focus {
    text-decoration: underline;
}

.gg-booking-membership-gate__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: center;
}

.gg-booking-membership-gate__actions .gg-booking-btn {
    display: inline-block;
    padding: 0.65rem 1.35rem;
    border-radius: 6px;
    text-decoration: none;
    font-weight: 500;
    line-height: 1.2;
    border: 2px solid var(--gg-color-primary);
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.gg-booking-membership-gate__actions .gg-booking-btn--primary {
    background-color: var(--gg-color-primary);
    color: var(--gg-color-surface);
}

.gg-booking-membership-gate__actions .gg-booking-btn--primary:hover,
.gg-booking-membership-gate__actions .gg-booking-btn--primary:focus {
    background-color: var(--gg-color-secondary);
    border-color: var(--gg-color-secondary);
    color: var(--gg-color-surface);
}

.gg-booking-membership-gate__actions .gg-booking-btn--secondary {
    background-color: transparent;
    color: var(--gg-color-primary);
}

.gg-booking-membership-gate__actions .gg-booking-btn--secondary:hover,
.gg-booking-membership-gate__actions .gg-booking-btn--secondary:focus {
    background-color: var(--gg-color-primary);
    color: var(--gg-color-surface);
}

/* Theme link-color defense. The gate CTAs are <a> elements, so a theme's
   global link color (`a { color: … }`) overrides our button text — the fill
   is unaffected because themes don't set link backgrounds, which is why the
   primary button showed a forest fill with dark text. Qualifying with the
   anchor element + link states raises specificity above typical theme link
   rules so our text color wins without !important. The <button>-based form
   submit (waitlist) never had this problem — themes don't style buttons. */
.gg-booking-membership-gate__actions a.gg-booking-btn--primary,
.gg-booking-membership-gate__actions a.gg-booking-btn--primary:link,
.gg-booking-membership-gate__actions a.gg-booking-btn--primary:visited,
.gg-booking-membership-gate__actions a.gg-booking-btn--primary:hover,
.gg-booking-membership-gate__actions a.gg-booking-btn--primary:focus {
    color: var(--gg-color-surface);
}

.gg-booking-membership-gate__actions a.gg-booking-btn--secondary,
.gg-booking-membership-gate__actions a.gg-booking-btn--secondary:link,
.gg-booking-membership-gate__actions a.gg-booking-btn--secondary:visited {
    color: var(--gg-color-primary);
}

/* Secondary on hover fills with --gg-color-primary, so its text flips to the
   surface color — same anchor + state qualification so the theme link
   color can't keep it dark on the fill. */
.gg-booking-membership-gate__actions a.gg-booking-btn--secondary:hover,
.gg-booking-membership-gate__actions a.gg-booking-btn--secondary:focus {
    color: var(--gg-color-surface);
}

@media (max-width: 540px) {
    .gg-booking-membership-gate {
        padding: 1.5rem 1rem;
    }

    .gg-booking-membership-gate__actions {
        flex-direction: column;
        align-items: stretch;
    }

    .gg-booking-membership-gate__actions .gg-booking-btn {
        width: 100%;
        text-align: center;
    }
}

/* ----------------------------------------------------------------------- */
/* Book Now Button widget                                                  */
/* ----------------------------------------------------------------------- */

.gg-booking-book-now-wrapper {
	display: block;
}

.gg-booking-book-now-button {
	display: inline-block;
	padding: 14px 28px;
	border: 1px solid transparent;
	border-radius: 4px;
	background-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

/* The Elementor editor's e_atomic_elements baseline paints native <a>/<button>
   with a block/full-width box that out-specifies our single-class (0,1,0)
   display rule above — the same baseline that forced the double-class
   brand-colour fix on .gg-booking-btn--primary. Now that the Book Now button
   also carries .gg-booking-btn, pin its default box model at (0,2,0) so the
   button hugs its content by default in the canvas too. The Full Width control
   (display:block; width:100%, {{WRAPPER}}-scoped + loaded later) stays the
   single source of truth for stretching (rule 117). inline-block (not the base
   inline-flex) keeps the class-name "inside" position stacked above the label. */
.gg-booking-btn.gg-booking-book-now-button {
	display: inline-block;
	width: auto;
}

.gg-booking-book-now-button:hover,
.gg-booking-book-now-button:focus {
	background-color: var(--gg-color-secondary);
	color: var(--gg-color-surface);
	text-decoration: none;
}

.gg-booking-book-now-button:focus {
	outline: 2px solid var(--gg-color-primary);
	outline-offset: 2px;
}

.gg-booking-book-now-button--disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

.gg-booking-book-now-button--disabled:hover,
.gg-booking-book-now-button--disabled:focus {
	background-color: var(--gg-color-primary);
	transform: none;
	box-shadow: none;
}

.gg-booking-book-now__class-name {
	display: block;
	font-weight: 600;
	color: var(--gg-color-text);
}

.gg-booking-book-now-button .gg-booking-book-now__class-name--inside {
	display: block;
	margin-bottom: 4px;
	font-size: 0.85em;
	font-weight: 400;
	opacity: 0.85;
	color: inherit;
}

.gg-booking-book-now-button .gg-booking-book-now__label {
	display: block;
}

@media (max-width: 767px) {
	.gg-booking-book-now-button {
		min-height: 44px;
		padding: 12px 24px;
	}
}

/* -----------------------------------------------------------------------
   Promo Code UI
   ----------------------------------------------------------------------- */
.gg-booking-promo-row { margin: 12px 0; }
.gg-booking-promo-input-wrap { display: flex; gap: 8px; align-items: center; }
.gg-booking-promo-input { flex: 1; }
.gg-booking-promo-apply-btn { white-space: nowrap; }
.gg-booking-promo-feedback { margin-top: 6px; font-size: 13px; min-height: 18px; }
.gg-booking-promo-summary {
	margin-top: 8px;
	padding: 8px 12px;
	background: var(--gg-color-success-soft);
	border: 1px solid var(--gg-color-success-soft);
	border-radius: 4px;
	font-size: 13px;
	color: var(--gg-color-success);
}
.gg-booking-promo-summary .gg-booking-promo-original {
	text-decoration: line-through;
	color: var(--gg-color-text-muted);
	margin-right: 6px;
}
.gg-booking-promo-summary .gg-booking-promo-final { font-weight: 600; }

.gg-booking-redirect-hint {
	display: block;
	margin-top: 6px;
	font-size: 0.875em;
	color: var(--gg-color-text-muted);
	font-style: italic;
}

/* -----------------------------------------------------------------------
   Waiver signing flow
   ----------------------------------------------------------------------- */
#gg-booking-waiver-flow {
	padding: 0;
}

.gg-booking-waiver-title {
	font-size: 1.1em;
	font-weight: 600;
	margin: 0 0 12px;
	color: var(--gg-color-text, var(--gg-color-text));
}

.gg-booking-waiver-content {
	max-height: 280px;
	overflow-y: auto;
	border: 1px solid var(--gg-color-border, var(--gg-color-border));
	border-radius: 6px;
	padding: 16px;
	margin-bottom: 16px;
	font-size: 0.875em;
	line-height: 1.65;
	background: var(--gg-color-background, var(--gg-color-surface));
}

.gg-booking-waiver-agree-label {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	margin-bottom: 16px;
	font-size: 0.875em;
	cursor: pointer;
}

.gg-booking-waiver-agree-checkbox {
	margin-top: 2px;
	flex-shrink: 0;
}

.gg-booking-waiver-sign-btn {
	width: 100%;
}

.gg-booking-waiver-sign-btn:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}


/* -----------------------------------------------------------------------
   Enrollment panel (BookingFormWidget enrollment-mode short-circuit)
   ----------------------------------------------------------------------- */
.gg-booking-enrollment-panel {
	background: var( --gg-card-bg, var(--gg-color-surface) );
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	padding: 24px;
	/* No hard max-width here (rule 122): the panel renders inside
	   .gg-booking-booking-form-wrapper, which is the BookingForm Frame element
	   (form_max_width / form_alignment, base cap 560px). A hard inner cap would
	   fight the Frame — pinning the panel narrow + left and ignoring the studio's
	   width/alignment, exactly like the booking form beside it. Let the wrapper
	   govern so both states share one width. */
}

.gg-booking-enrollment-panel__header {
	margin-bottom: 16px;
	padding-bottom: 16px;
	border-bottom: 1px solid var( --gg-color-border, var(--gg-color-border) );
}

.gg-booking-enrollment-panel__title {
	margin: 0 0 4px;
	font-size: 1.4em;
	font-weight: 600;
}

.gg-booking-enrollment-panel__subtitle {
	margin: 0;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
	font-size: 0.95em;
}

.gg-booking-enrollment-panel__price {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	margin-bottom: 16px;
	padding: 12px 16px;
	background: var( --gg-bg-subtle, var(--gg-color-muted-soft) );
	border-radius: 6px;
}

.gg-booking-enrollment-panel__price-label {
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
}

.gg-booking-enrollment-panel__price-value {
	font-size: 1.4em;
	font-weight: 600;
}

.gg-booking-enrollment-panel__note {
	margin: 0 0 16px;
	padding: 10px 12px;
	/* Explanatory note (e.g. "open enrollment …") — treated as chrome, so it
	   palette-tints with the widget rather than reading fixed info-blue. The
	   --gg-bg-info override still wins if a studio sets it. True success/error/
	   warning states keep their semantic colours. */
	background: var( --gg-bg-info, var(--gg-color-primary-soft, var(--gg-color-muted-soft)) );
	border-left: 3px solid var(--gg-color-primary);
	font-size: 0.9em;
}

.gg-booking-enrollment-panel__signed-in {
	margin: 0 0 16px;
	font-size: 0.9em;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
}

.gg-booking-enrollment-form .gg-booking-form-row {
	margin-bottom: 14px;
}

.gg-booking-enrollment-form .gg-booking-form-row label {
	display: block;
	margin-bottom: 4px;
	font-weight: 500;
}

.gg-booking-enrollment-form .gg-booking-form-row input[type="text"],
.gg-booking-enrollment-form .gg-booking-form-row input[type="email"] {
	width: 100%;
	padding: 8px 10px;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 4px;
	font-size: 1em;
}

.gg-booking-enrollment-form .gg-booking-card-element {
	padding: 10px 12px;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 4px;
	background: var(--gg-color-surface);
}

.gg-booking-enrollment-form .gg-booking-card-errors {
	margin-top: 6px;
	min-height: 1.2em;
	color: var( --gg-color-error, var(--gg-color-error) );
	font-size: 0.9em;
}

.gg-booking-enrollment-form__actions {
	margin-top: 18px;
}

.gg-booking-enrollment-form__actions .gg-booking-button {
	width: 100%;
	padding: 12px 16px;
	font-size: 1em;
	font-weight: 600;
	border: none;
	border-radius: 6px;
	background: var( --gg-color-primary, var(--gg-color-primary) );
	color: var(--gg-color-surface);
	cursor: pointer;
}

.gg-booking-enrollment-form__actions .gg-booking-button:hover:not(:disabled) {
	background: var( --gg-color-secondary, var(--gg-color-primary-strong) );
}

.gg-booking-enrollment-form__actions .gg-booking-button:disabled,
.gg-booking-enrollment-form__actions .gg-booking-button.is-busy {
	opacity: 0.6;
	cursor: wait;
}

.gg-booking-enrollment-form__feedback {
	margin-top: 12px;
	padding: 10px 12px;
	border-radius: 4px;
	min-height: 0;
}

.gg-booking-enrollment-form__feedback:empty {
	padding: 0;
}

.gg-booking-enrollment-form__feedback--error {
	background: var(--gg-color-error-soft);
	color: var( --gg-color-error, var(--gg-color-error) );
	border: 1px solid var( --gg-color-error, var(--gg-color-error) );
}

.gg-booking-enrollment-form__feedback--success {
	background: var(--gg-color-success-soft);
	color: var( --gg-color-success, var(--gg-color-primary) );
	border: 1px solid var( --gg-color-success, var(--gg-color-primary) );
}

/* -----------------------------------------------------------------------
   My Enrollments section (ClientDashboardWidget)
   ----------------------------------------------------------------------- */
.gg-booking-dashboard__enrollment-card {
	position: relative;
}

.gg-booking-dashboard__enrollment-actions {
	margin-top: 8px;
}

.gg-booking-cancel-my-enrollment-btn {
	background: none;
	border: none;
	padding: 0;
	color: var( --gg-color-error, var(--gg-color-error) );
	cursor: pointer;
	font-size: 0.9em;
	text-decoration: underline;
}

.gg-booking-cancel-my-enrollment-btn:hover:not(:disabled) {
	color: var(--gg-color-error);
}

.gg-booking-cancel-my-enrollment-btn:disabled {
	opacity: 0.6;
	cursor: wait;
}

/* ==========================================================================
   Login Widget — form, button, logged-in panel, modal
   All --gg-login-* vars are exposed through LoginWidget Style controls per
   rule 117's canonical-pattern (Element Alignment top, per-element sections).
   ========================================================================== */

.gg-booking-login {
	display: block;
	width: 100%;
}

/* --- Logged-out form ---------------------------------------------------- */

.gg-booking-login-form {
	display: flex;
	flex-direction: column;
	gap: 14px;
	/* Form Max Width control (default none = full width). When set, the
	   margin from the Layout "Form (Inline)" alignment control (margin: 0
	   auto …) places the narrowed card left / center / right. */
	max-width: var( --gg-login-form-max-width, none );
	background-color: var( --gg-login-form-bg, transparent );
	padding: var( --gg-login-form-padding, 0 );
	border-radius: var( --gg-login-form-radius, 0 );
}

/* The inactive auth panel carries the `hidden` attribute. Because the rule
   above sets display:flex, the UA `[hidden]{display:none}` (0,0,1) loses — so
   restate it here at (0,2,0) so the non-default Login/Register panel is truly
   hidden until the visitor switches (gg-booking-login.js toggles `hidden`).
   The editor preview renders both panels WITHOUT `hidden` (and without the
   .gg-booking-login-auth wrapper) so the register panel stays styleable. */
.gg-booking-login-form[hidden] {
	display: none;
}

.gg-booking-login-form__heading {
	margin: 0;
	font-family: var( --gg-type-heading );
	font-size: 1.4rem;
	font-weight: 600;
	color: var( --gg-color-text );
	line-height: 1.2;
}

.gg-booking-login-form__intro {
	margin: 0;
	color: var( --gg-color-text-muted );
	font-size: 0.95rem;
	line-height: 1.5;
}

.gg-booking-login-form__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.gg-booking-login-form__label {
	font-size: 13px;
	font-weight: 600;
	color: var( --gg-color-text );
}

.gg-booking-login-form__input {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var( --gg-color-border );
	border-radius: 4px;
	background-color: var( --gg-color-background );
	font-size: 14px;
	color: var( --gg-color-text );
	font-family: inherit;
}

.gg-booking-login-form__input:focus,
.gg-force-focus .gg-booking-login-form__input {
	outline: none;
	border-color: var( --gg-color-primary );
	/* Default focus ring tracks the Brand primary (rule 46). rgba fallback first,
	   color-mix where supported. Override via Focus Box Shadow control. */
	box-shadow: 0 0 0 3px rgba( 92, 122, 92, 0.15 );
	box-shadow: 0 0 0 3px color-mix( in srgb, var( --gg-color-primary ) 20%, transparent );
}

/* Editor preview is non-interactive. LoginWidget + PasswordResetWidget render
   the LIVE form in the canvas (not a disabled mock), so without this a click
   would focus a real input instead of selecting the widget. pointer-events:none
   keeps the inputs looking exactly like the live page (no disabled dimming)
   while letting clicks fall through to widget selection. The "Preview:
   Interactive State" control is the intended way to preview hover/focus.
   `!important` (editor-only) beats the Elementor editor's own click handling on
   real form fields — same justified-override pattern as the editor mock above.
   Scoped to the --editor class, which never renders on the live page. */
.gg-booking-login--editor .gg-booking-login-form,
.gg-booking-login--editor .gg-booking-login-form__input,
.gg-booking-login--editor .gg-booking-login-form__checkbox,
.gg-booking-login--editor .gg-booking-login-form__link,
.gg-booking-login--editor .gg-booking-btn {
	pointer-events: none !important;
}

.gg-booking-login-form__row {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	color: var( --gg-color-text-muted );
}

.gg-booking-login-form__checkbox {
	width: 16px;
	height: 16px;
	accent-color: var( --gg-color-primary );
	cursor: pointer;
}

.gg-booking-login-form__submit {
	width: 100%;
	margin-top: 4px;
}

.gg-booking-login-form__links {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 12px;
	font-size: 13px;
}

.gg-booking-login-form__link {
	color: var( --gg-color-primary );
	text-decoration: none;
}

.gg-booking-login-form__link:hover,
.gg-booking-login-form__link:focus {
	text-decoration: underline;
}

/* The login/register toggle reuses the link styling on a <button> so it sits
   inline with "Forgot password?" — strip native + Elementor atomic-element
   button chrome so it reads as a text link, not a filled box. The double-class
   selector (0,2,0) beats the e_atomic_elements <button> baseline that otherwise
   paints it with the accent bg + shadow + white text (rule 117). */
button.gg-booking-login-form__link,
.gg-booking-login-form__link.gg-booking-auth__switch {
	-webkit-appearance: none;
	appearance: none;
	display: inline;
	width: auto;
	min-height: 0;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	box-shadow: none;
	color: var( --gg-color-primary );
	font: inherit;
	line-height: inherit;
	text-align: left;
	cursor: pointer;
}

.gg-booking-login-form__link.gg-booking-auth__switch:hover,
.gg-booking-login-form__link.gg-booking-auth__switch:focus {
	background: none;
	box-shadow: none;
	color: var( --gg-color-primary );
	text-decoration: underline;
}

/* Password requirement hint under the register password field. */
.gg-booking-login-form__hint {
	margin-top: -8px;
	font-size: 12px;
	color: var( --gg-color-text-muted );
}

/* In-modal auth (GGLogin login + register states, rule 148). Each view is a
   panel; only one is visible at a time (toggled via [hidden]). */
.gg-booking-auth__panel[hidden] {
	display: none;
}

/* Chained login modal (GGLogin, Modal Arc PR-B) — the form is built in JS and
   mounted in the generic GGModal body, so it inherits the base form styles
   above. Just align the remember-me row tidily. */
.gg-booking-login-form--modal .gg-booking-login-form__remember {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-booking-login-form__error {
	display: none;
	padding: 10px 12px;
	background-color: var( --gg-bg-info, var(--gg-color-error-soft) );
	border: 1px solid var( --gg-color-error, var(--gg-color-error) );
	border-radius: 4px;
	color: var( --gg-color-error, var(--gg-color-error) );
	font-size: 13px;
	line-height: 1.4;
}

.gg-booking-login-form__error.is-visible {
	display: block;
}

.gg-booking-login-form__success {
	display: none;
	padding: 10px 12px;
	background-color: var(--gg-color-success-soft);
	border: 1px solid var( --gg-color-success, var(--gg-color-primary) );
	border-radius: 4px;
	color: var( --gg-color-success, var(--gg-color-primary) );
	font-size: 14px;
	line-height: 1.5;
}

.gg-booking-login-form__success.is-visible {
	display: block;
}

.gg-booking-login-form__submit.is-loading {
	opacity: 0.7;
	cursor: wait;
}

/* --- Button mode (Log In trigger) --------------------------------------- */

/* Block wrapper so the Layout "Login / Account Button" alignment control can
   text-align the inline-flex button left / center / right within its row. */
.gg-booking-login-button-wrap {
	display: block;
}

/* Button mode is just a trigger button (often an icon-only "My Account" glyph
   in a header) — shrink the widget to the button instead of letting the Frame
   chain (.gg-booking-widget-inner → .gg-booking-login { width:100% } → block
   wrap) reserve the whole container with dead space beside a tiny icon. Scoped
   to `--button` so inline FORM mode keeps its full-width card + alignment.
   The `:has()` rule relaxes the rule-122 Frame stretch so a vertical container
   can't re-expand the widget; (0,2,0) but a studio's Advanced → Align Self
   inline style still wins. Alignment within the row becomes a no-op once the
   widget shrink-wraps — the right trade for a compact header button. */
.gg-booking-login--button {
	width: auto;
}

.gg-booking-login--button .gg-booking-login-button-wrap {
	display: inline-flex;
}

.elementor-widget-gg_login:has( .gg-booking-login--button ) {
	align-self: center;
}

.gg-booking-login-button {
	display: inline-flex;
	align-items: center;
	/* Icon Spacing control drives the icon↔label gap (default 8px). */
	gap: var( --gg-login-btn-icon-gap, 8px );
}

.gg-booking-login-button__avatar {
	width: 24px;
	height: 24px;
	border-radius: 50%;
	object-fit: cover;
}

/* Account-button icon (Elementor ICONS control). Sized via the Icon Size
   control (font-size); SVG glyphs follow it through the 1em width/height. The
   glyph inherits the button text colour via currentColor. */
.gg-booking-login-button__icon {
	display: inline-flex;
	align-items: center;
	line-height: 0;
}

/* Size BOTH a nested glyph svg (FontAwesome) AND an uploaded SVG icon, where
   Elementor's Icons_Manager puts the passed class directly ON the <svg> rather
   than a wrapper span — without the `svg.__icon` selector that case has no
   width and collapses to nothing ("the icon disappears" in icon-only mode). */
.gg-booking-login-button__icon svg,
svg.gg-booking-login-button__icon {
	width: 1em;
	height: 1em;
	fill: currentColor;
}

/* --- Logged-in panel ---------------------------------------------------- */

.gg-booking-login-panel {
	display: flex;
	flex-direction: column;
	gap: 12px;
	background-color: var( --gg-login-panel-bg, var( --gg-bg-subtle, var(--gg-color-muted-soft) ) );
	padding: var( --gg-login-panel-padding, 16px );
	border-radius: var( --gg-login-panel-radius, 6px );
	border: 1px solid var( --gg-color-border );
}

.gg-booking-login-panel__header {
	display: flex;
	align-items: center;
	gap: 12px;
}

.gg-booking-login-panel__avatar {
	width: var( --gg-login-avatar-size, 48px );
	height: var( --gg-login-avatar-size, 48px );
	border-radius: 50%;
	object-fit: cover;
	flex-shrink: 0;
}

.gg-booking-login-panel__greeting {
	margin: 0;
	font-size: 1rem;
	font-weight: 600;
	color: var( --gg-color-text );
}

.gg-booking-login-panel__actions {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.gg-booking-login-panel__cta {
	display: inline-block;
}

.gg-booking-login-panel__links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.gg-booking-login-panel__link {
	display: block;
	padding: 4px 0;
	color: var( --gg-color-primary );
	font-size: 0.9rem;
	text-decoration: none;
}

.gg-booking-login-panel__link:hover,
.gg-booking-login-panel__link:focus {
	text-decoration: underline;
}

.gg-booking-login-panel__logout {
	color: var( --gg-color-text-muted );
	font-size: 0.85rem;
	text-decoration: none;
	align-self: flex-start;
}

.gg-booking-login-panel__logout:hover,
.gg-booking-login-panel__logout:focus {
	color: var( --gg-color-error );
	text-decoration: underline;
}

/* --- Modal (button-mode form host) -------------------------------------- */
/* The button-mode login form now opens in the shared GGModal primitive
   (GGModal owns the overlay, header, title, and close X). The live dialog
   carries a `gg-booking-login-modal` co-class so the widget's Modal Container +
   close Style controls (targeting `.gg-modal.gg-booking-login-modal …`) reach
   it, and the auth-switch delegation can scope to it. Only the in-modal form
   reset + the editor mock are widget-specific here. */

/* The login form inside the modal drops its own card chrome — GGModal's dialog
   already provides it. Covers both the live dialog and the editor mock. */
.gg-modal.gg-booking-login-modal .gg-booking-login-form,
.gg-booking-login-modal--preview .gg-booking-login-form {
	background: none;
	padding: 0;
}

/* Editor-only modal mock: flow GGModal's dialog in place so the Modal Container
   style controls preview in-canvas. The live modal never carries `--preview`.
   `--preview` (0,2,0) beats GGModal's `.gg-modal` closed-state transform by
   specificity. No inline style on the placeholder (the 0.7.7 lesson). */
.gg-booking-login-modal-mock {
	display: flex;
	justify-content: center;
}

.gg-modal.gg-booking-login-modal--preview {
	position: relative;
	max-height: none;
	transform: none;
	width: 100%;
}

/* =============================================================================
 * Appointment Booking Widget (Appointments arc Stage 3.F).
 * Hooks into the shared --gg-* vars (rule 46/115). Scoped to .gg-appointment-*
 * so it can't bleed into other widgets.
 * ========================================================================== */

.gg-booking-appointment-widget {
	max-width: 720px;
	margin: 0 auto;
}

/* --- Appointment widget inside GGModal (modal-host) ---------------------- */
/* The appointment widget fetched into GGModal: the DIALOG is the single styleable
   card — its chrome comes from the widget's paired card-chrome controls
   (`.gg-modal.gg-booking-appointment-modal …`, set in AppointmentBookingWidget).
   Strip the widget's OWN frame inside the modal so it doesn't double the dialog
   (and drop the centering max-width/margin) AND so the body lines up with
   GGModal's header. Anchored on `.gg-modal__body` (ALWAYS present), NOT
   `.elementor-element` — so it fires whether or not an AppointmentBooking
   modal-host exists on the page (the `--modal` co-class is on the fragment in
   both cases). The two widget classes give (0,4,0), beating the per-instance
   styleScope rule (`.elementor-element.elementor-element-{id}
   .gg-booking-appointment-widget` = 0,3,0) without !important. */
.gg-modal .gg-modal__body .gg-booking-appointment-widget.gg-booking-appointment-widget--modal {
	max-width: none;
	margin: 0;
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	box-shadow: none;
}

/* Defensive: the fragment already suppresses the service title server-side
   (show_service_title='no') and GGModal's header shows it — this guards against a
   duplicate title if that fragment default changes. */
.gg-modal .gg-booking-appointment-title {
	display: none;
}

.gg-booking-appointment-title {
	font-family: var( --gg-type-heading, inherit );
	color: var( --gg-color-text, var(--gg-color-text) );
	margin: 0 0 8px;
	font-size: 1.6em;
	line-height: 1.25;
}

.gg-booking-appointment-description {
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
	margin: 0 0 16px;
	line-height: 1.55;
}

.gg-booking-appointment-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 12px 18px;
	margin: 0 0 20px;
	font-size: 0.95em;
	/* Follows the master Content Alignment (Layout); per-element Meta override
	   sets justify-content directly. */
	justify-content: var( --gg-appt-meta-justify, flex-start );
}

.gg-booking-appointment-price {
	color: var( --gg-color-text, var(--gg-color-text) );
	font-weight: 600;
}

.gg-booking-appointment-duration {
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
}

/* Service picker (A2) — a dropdown that loads the chosen service's booking form
   into the mount below it (inline) or in the popup (modal). */
.gg-booking-appointment-picker-label {
	display: block;
	font-weight: 600;
	margin: 0 0 6px;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-booking-appointment-picker-select {
	width: 100%;
}

.gg-booking-appointment-picker-mount:not( :empty ) {
	margin-top: 16px;
}

.gg-booking-appointment-picker-empty {
	margin: 8px 0 0;
	color: var( --gg-color-text-muted, var(--gg-color-text-light) );
	font-style: italic;
}

.gg-booking-appointment-date-strip {
	display: flex;
	gap: 6px;
	overflow-x: auto;
	padding: 4px 0 8px;
	margin: 0 0 16px;
	border-bottom: 1px solid var( --gg-color-border, var(--gg-color-border) );
}

/* Scoped to `.gg-booking-appointment-widget` (always the render root, inline
   AND modal-fragment) for (0,2,0) specificity. Bare <button>s in the
   body-mounted modal otherwise inherit Elementor's global kit rule
   `.elementor-kit-N button` (0,1,1) — which paints them the studio accent
   ("button look") and out-specifies a single-class (0,1,0) base. The (0,2,0)
   scope makes the intended transparent "modern strip" look win on the popup
   too. (Memory: elementor-kit-button-bodymounted-gotcha / rule 117.) */
.gg-booking-appointment-widget .gg-booking-appointment-day {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	min-width: 70px;
	padding: 8px 10px;
	background: transparent;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	color: var( --gg-color-text, var(--gg-color-text) );
	font-family: inherit;
	font-size: 0.95em;
	cursor: pointer;
	/* Reset native / atomic <button> chrome (white face + shadow). */
	-webkit-appearance: none;
	appearance: none;
	box-shadow: none;
	transition: filter 0.15s ease, border-color 0.15s ease;
}

/* Background-agnostic hover (see slot note) — readable under any override. */
.gg-booking-appointment-widget .gg-booking-appointment-day:hover {
	filter: brightness( 0.95 );
	border-color: var( --gg-color-primary, var(--gg-color-primary) );
}

/* Hover FILL: the rule above sets no background, so Elementor's Kit `button:hover`
   paints a stray fill (the off-brand green). Re-assert an on-brand soft tint at
   (0,4,0) so the Kit can't win; excludes the selected day (keeps its --gg-color-primary).
   Palette-tinted in palette'd contexts (incl. body-mounted modals, which inherit
   the dialog's --gg-color-primary-soft); neutral fallback otherwise. */
.gg-booking-appointment-widget .gg-booking-appointment-day:hover:not( .is-active ) {
	background-color: var( --gg-color-primary-soft, var(--gg-color-muted-soft) );
	/* Re-assert dark text: the Kit's `button:hover` sets white, which is lost on
	   the light tint. Only the SELECTED state (excluded above) keeps white-on-primary. */
	color: var( --gg-color-text, var(--gg-color-text) );
}

/* Radius lock: the Elementor kit's `button:hover/:focus` rule (0,2,1) sets its
   own border-radius and out-specifies the (0,2,0) base, snapping the corners on
   hover. (0,3,0) re-asserts the resting 8px across the kit-targeted states; a
   per-instance radius override (higher specificity) still wins. */
.gg-booking-appointment-widget .gg-booking-appointment-day:hover,
.gg-booking-appointment-widget .gg-booking-appointment-day:focus {
	border-radius: 8px;
}

/* Strip day shadow neutralize at (0,2,0) — see slot note. (Calendar cells get
   their own (0,2,0) neutralize under .gg-booking-appointment-cal-grid.) */
.gg-booking-appointment-date-strip .gg-booking-appointment-day,
.gg-booking-appointment-date-strip .gg-booking-appointment-day:hover {
	box-shadow: none;
}

.gg-booking-appointment-widget .gg-booking-appointment-day.is-active {
	background-color: var( --gg-color-primary, var(--gg-color-primary) );
	border-color: var( --gg-color-primary, var(--gg-color-primary) );
	color: var(--gg-color-surface);
}

.gg-booking-appointment-day-name {
	font-size: 0.75em;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	opacity: 0.85;
}

.gg-booking-appointment-day-date {
	font-weight: 600;
	margin-top: 2px;
}

/* ------------------------------------------------------------------------- */
/* Appointment date picker — Calendly-style month grid (rule 147 A1b).        */
/* The calendar reuses `.gg-booking-appointment-day` buttons (Day Button Kit  */
/* styles them) so the slot machinery + styling are shared with the strip.    */
/* In calendar mode the strip is hidden on desktop and, when Mobile Fallback  */
/* is on, swaps back in on phones (the `--mobile-strip` modifier + media q).  */
/* ------------------------------------------------------------------------- */
.gg-booking-appointment-dates--calendar .gg-booking-appointment-date-strip {
	display: none;
}

.gg-booking-appointment-calendar {
	/* Left/right margin follow the master Content Alignment vars (default center
	   via the master's center default); bottom margin stays fixed so alignment
	   never eats the gap to the times. Per-element Calendar override sets
	   margin-left/right directly. */
	margin: 0 var( --gg-appt-cal-mr, 0 ) 16px var( --gg-appt-cal-ml, 0 );
	/* Cap the width so the day cells stay compact (Calendly-sized) instead of
	   ballooning to 7 full-width squares. The side-by-side layout sets
	   max-width:none so it fills its column. */
	max-width: 22rem;
}

.gg-booking-appointment-cal-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 10px;
}

.gg-booking-appointment-cal-title {
	font-weight: 600;
	font-size: 1.05em;
	color: var( --gg-color-text, var(--gg-color-text) );
}

/* Scoped to .gg-booking-appointment-calendar (0,2,0) so it beats the Elementor
   editor `e_atomic_elements` / Kit `button` baseline (~0,1,1) that otherwise
   paints these bare <button>s with a white box + drop-shadow + radius on hover
   (rule 117 — the recurring bare-button gotcha). box-shadow / appearance are
   nulled for the same reason; no !important. */
.gg-booking-appointment-calendar .gg-booking-appointment-cal-nav {
	flex: 0 0 auto;
	width: 34px;
	height: 34px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	/* Arrow colour via a var both states read, so the hover rule below can hold
	   it (default OR studio-set) against the Elementor Kit's `button:hover`
	   colour — which otherwise turns the ‹ › glyph white and it vanishes into
	   the hover background. The cal_nav_color control sets this var. */
	--gg-cal-nav-color: var( --gg-color-text, var(--gg-color-text) );
	color: var( --gg-cal-nav-color );
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	box-shadow: none;
	-webkit-appearance: none;
	appearance: none;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}

.gg-booking-appointment-calendar .gg-booking-appointment-cal-nav:hover:not( :disabled ) {
	background-color: var( --gg-surface-hover, var(--gg-color-background) );
	border-color: var( --gg-color-primary, var(--gg-color-primary) );
	/* Hold the glyph colour on hover (beats the Kit's white button:hover). */
	color: var( --gg-cal-nav-color );
	box-shadow: none;
}

.gg-booking-appointment-calendar .gg-booking-appointment-cal-nav:disabled {
	opacity: 0.4;
	cursor: default;
}

.gg-booking-appointment-cal-weekdays,
.gg-booking-appointment-cal-grid {
	display: grid;
	/* minmax(0, 1fr) lets each track shrink to its 1/7 share even if a cell's
	   content (or an inherited padding) is wider — so the grid can never
	   overflow into the times column. */
	grid-template-columns: repeat( 7, minmax( 0, 1fr ) );
	gap: 2px;
}

.gg-booking-appointment-cal-weekdays {
	margin-bottom: 4px;
}

.gg-booking-appointment-cal-weekday {
	text-align: center;
	font-size: 0.72rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var( --gg-color-text-muted, var(--gg-color-text-light) );
}

/* Calendar day cells inherit the Day Button Kit's COLOUR/state styling (shared
   `.gg-booking-appointment-day`) but NOT its box-model: a padding / min-width
   sized for a horizontal strip pill would bloat a grid cell (and the studio's
   Day Button "Padding" applies to both surfaces). So the cell's box-model is
   decoupled here at (0,3,0) — beating the Kit's {{WRAPPER}} padding control
   (0,2,0), no !important — and the cell sizes itself to the grid track, square.
   Pair with minmax(0,1fr) above so every cell is a uniform square regardless of
   the inherited padding. */
.gg-booking-appointment-calendar .gg-booking-appointment-cal-grid .gg-booking-appointment-cal-day {
	flex-direction: row;
	min-width: 0;
	width: 100%;
	padding: 0;
	aspect-ratio: 1 / 1;
	justify-content: center;
}

.gg-booking-appointment-cal-day .gg-booking-appointment-day-date {
	margin-top: 0;
}

/* Kill the Elementor editor atomic-<button> drop-shadow that leaks onto the
   bare day cells, in BOTH normal and hover states (editor-only; live is already
   clean). At (0,2,0)/(0,2,1) it beats the atomic baseline but ties the Day
   Button Kit's own Box Shadow control (injected later) — so a studio-set shadow
   still wins. Shadow only: doesn't touch background / the .is-active fill. */
.gg-booking-appointment-cal-grid .gg-booking-appointment-cal-day,
.gg-booking-appointment-cal-grid .gg-booking-appointment-cal-day:hover {
	box-shadow: none;
}

.gg-booking-appointment-cal-cell {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1 / 1;
	font-size: 0.95em;
}

.gg-booking-appointment-cal-day--muted {
	color: var( --gg-color-text-muted, var(--gg-color-text-light) );
	opacity: 0.45;
}

.gg-booking-appointment-cal-cell--blank {
	visibility: hidden;
}

@media ( max-width: 767px ) {
	.gg-booking-appointment-dates--calendar.gg-booking-appointment-dates--mobile-strip .gg-booking-appointment-calendar {
		display: none;
	}
	.gg-booking-appointment-dates--calendar.gg-booking-appointment-dates--mobile-strip .gg-booking-appointment-date-strip {
		display: flex;
	}
}

/* Side-by-side layout (Calendly: month left, times right). Only the --split
   modifier triggers the 2-col grid, and only on desktop; phones always stack
   (the strip fallback or a stacked calendar sits above the times). The
   "Available times" heading shows only when the times form their own column. */
.gg-booking-appointment-slot-heading {
	display: none;
	margin: 0 0 8px;
	font-weight: 600;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-booking-appointment-scheduler--split .gg-booking-appointment-slot-heading {
	display: block;
}

@media ( min-width: 768px ) {
	.gg-booking-appointment-scheduler--split {
		display: grid;
		grid-template-columns: minmax( 0, 22rem ) 1fr;
		gap: 24px;
		align-items: start;
	}
	.gg-booking-appointment-scheduler--split .gg-booking-appointment-calendar {
		margin-bottom: 0;
		max-width: none; /* fill its grid column */
	}
	.gg-booking-appointment-scheduler--split .gg-booking-appointment-slot-grid {
		margin: 0;
	}
}

.gg-booking-appointment-slot-grid {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( 140px, 1fr ) );
	gap: 8px;
	margin: 0 0 20px;
	min-height: 60px;
}

.gg-booking-appointment-widget .gg-booking-appointment-slot {
	/* Flex-centred + wrapping so the "(N left)" seats label sits centred with
	   the time and drops to a second line on narrow slots instead of spilling
	   past the right edge. min-width:0 lets the grid item shrink below its
	   content's min-content width. */
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	column-gap: 4px;
	min-width: 0;
	padding: 10px 12px;
	background: var( --gg-surface, var(--gg-color-surface) );
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 6px;
	font-family: inherit;
	font-size: 0.95em;
	color: var( --gg-color-text, var(--gg-color-text) );
	cursor: pointer;
	/* (0,2,0) scope — same body-mounted-modal kit-override fix as the day
	   buttons above: a bare single-class .gg-booking-appointment-slot (0,1,0)
	   loses to `.elementor-kit-N button` (0,1,1) in the popup. */
	-webkit-appearance: none;
	appearance: none;
	box-shadow: none;
	transition: filter 0.15s ease, border-color 0.15s ease;
}

/* Background-agnostic hover: a brightness nudge + border emphasis works under
   ANY studio bg/text override (no fixed light bg to clash with white text).
   `filter` isn't a property the Kit sets, so it layers cleanly on top of a
   studio-set hover. */
.gg-booking-appointment-slot:hover:not( :disabled ) {
	filter: brightness( 0.95 );
	border-color: var( --gg-color-primary, var(--gg-color-primary) );
}

/* Hover FILL (see day-button note): re-assert an on-brand soft tint so the Kit's
   `button:hover` can't paint the off-brand green; excludes the selected slot
   (keeps its --gg-color-primary fill). (0,5,0) beats the Kit. */
.gg-booking-appointment-slot-grid .gg-booking-appointment-slot:hover:not( :disabled ):not( .is-selected ) {
	background-color: var( --gg-color-primary-soft, var(--gg-color-muted-soft) );
	/* Dark text: the Kit's button:hover forces white, lost on the light tint. */
	color: var( --gg-color-text, var(--gg-color-text) );
}

/* Radius lock — same kit `button:hover/:focus` (0,2,1) override as the day
   buttons; re-assert the resting 6px so slot corners don't shift on hover. */
.gg-booking-appointment-widget .gg-booking-appointment-slot:hover,
.gg-booking-appointment-widget .gg-booking-appointment-slot:focus {
	border-radius: 6px;
}

/* The base (0,1,0) box-shadow reset loses to Elementor's atomic `button` shadow
   rule; scope under the grid to (0,2,0)/(0,2,1) so it wins in BOTH states. Ties
   the Slot Button Kit's own Box Shadow control (also 0,2,0, injected later) so a
   studio-set shadow still wins. */
.gg-booking-appointment-slot-grid .gg-booking-appointment-slot,
.gg-booking-appointment-slot-grid .gg-booking-appointment-slot:hover {
	box-shadow: none;
}

.gg-booking-appointment-slot.is-selected {
	background-color: var( --gg-color-primary, var(--gg-color-primary) );
	border-color: var( --gg-color-primary, var(--gg-color-primary) );
	color: var(--gg-color-surface);
}

.gg-booking-appointment-slot-seats {
	font-size: 0.85em;
	opacity: 0.8;
	/* Spacing from the time now comes from the slot's flex column-gap; on a
	   narrow slot this label wraps to its own centred line. */
	white-space: nowrap;
}

.gg-booking-appointment-slot-status {
	grid-column: 1 / -1;
	margin: 0;
	padding: 16px;
	text-align: center;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
	font-style: italic;
}

.gg-booking-appointment-slot-status.is-error {
	color: var( --gg-color-error, var(--gg-color-error) );
	font-style: normal;
}

.gg-booking-appointment-book-panel {
	padding: 16px;
	background: var( --gg-surface-alt, var(--gg-color-muted-soft) );
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	/* Insulate the form card from the master Content Alignment — labels read as a
	   conventional left-aligned form rather than inheriting the header's centring
	   (directly-set text-align beats the inherited master). A dedicated Book Panel
	   alignment override + full card styling land in v1.1.48. */
	text-align: left;
}

.gg-booking-appointment-selected-slot {
	font-weight: 600;
	color: var( --gg-color-text, var(--gg-color-text) );
	margin: 0 0 12px;
}

.gg-booking-appointment-payment {
	margin: 0 0 12px;
}

.gg-booking-appointment-payment label {
	display: block;
	margin: 0 0 4px;
	font-weight: 600;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-booking-appointment-payment .gg-booking-select {
	width: 100%;
	padding: 8px 10px;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 6px;
	background: var(--gg-color-surface);
	font-family: inherit;
	font-size: 0.95em;
}

.gg-booking-appointment-deposit-note {
	margin: 6px 0 0;
	padding: 8px 10px;
	background: var(--gg-color-warning-soft);
	border-left: 3px solid var(--gg-color-warning);
	border-radius: 0 4px 4px 0;
	font-size: 0.85em;
	color: var(--gg-color-warning);
}

.gg-booking-appointment-card-wrapper {
	margin: 0 0 12px;
}

.gg-booking-appointment-card-wrapper #gg-booking-appt-card-element {
	padding: 10px 12px;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 6px;
	background: var(--gg-color-surface);
}

.gg-booking-appointment-card-errors {
	margin-top: 6px;
	color: var( --gg-color-error, var(--gg-color-error) );
	font-size: 0.85em;
}

.gg-booking-appointment-notes-label {
	display: block;
	margin: 0 0 4px;
	font-weight: 600;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-booking-appointment-notes {
	width: 100%;
	padding: 8px 10px;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 6px;
	font-family: inherit;
	font-size: 0.95em;
	margin: 0 0 12px;
	resize: vertical;
}

/* Guest name / email fields — full-width like the notes textarea + payment
   select (they had no CSS, so they fell back to the browser's default narrow
   <input> width). The label wraps the input, so the label is block and the
   input fills below it. Appearance is overridable via the Book Panel → Inputs
   controls (they target .gg-booking-appointment-guest-fields input). */
.gg-booking-appointment-guest-fields {
	margin: 0 0 12px;
}

.gg-booking-appointment-guest-label {
	display: block;
	margin: 0 0 12px;
}

.gg-booking-appointment-guest-name,
.gg-booking-appointment-guest-email {
	display: block;
	width: 100%;
	margin-top: 4px;
	padding: 8px 10px;
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 6px;
	font-family: inherit;
	font-size: 0.95em;
}

/* Scoped to the widget (0,2,0) so it beats Elementor's Kit `.elementor-kit-N
   button` rule (0,1,1) — otherwise an un-armored single-class button gets
   repainted with the Kit's button colour (the brand/palette --gg-color-primary then
   never shows). Matches the .gg-booking-appointment-slot armor pattern. */
.gg-booking-appointment-widget .gg-booking-appointment-book-btn {
	width: 100%;
	padding: 12px 16px;
	background: var( --gg-color-primary, var(--gg-color-primary) );
	color: var(--gg-color-surface);
	border: 0;
	border-radius: 6px;
	font-family: inherit;
	font-size: 1em;
	font-weight: 600;
	cursor: pointer;
	/* Reset native / atomic <button> chrome (white face + shadow). */
	-webkit-appearance: none;
	appearance: none;
	box-shadow: none;
	transition: filter 0.15s ease, background-color 0.15s ease;
}

/* Background-agnostic hover so a studio-overridden fill stays correct. */
.gg-booking-appointment-book-btn:hover:not( :disabled ) {
	filter: brightness( 0.95 );
}

/* Shadow neutralize at (0,2,0) — see slot note. */
.gg-booking-appointment-book-panel .gg-booking-appointment-book-btn,
.gg-booking-appointment-book-panel .gg-booking-appointment-book-btn:hover {
	box-shadow: none;
}

.gg-booking-appointment-book-btn:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

.gg-booking-appointment-feedback {
	margin-top: 8px;
	padding: 0;
	font-size: 0.9em;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-booking-appointment-feedback.is-error {
	color: var( --gg-color-error, var(--gg-color-error) );
}

.gg-booking-appointment-policy {
	margin: 12px 0 0;
	padding: 10px 12px;
	background: var(--gg-color-background);
	border-radius: 6px;
	font-size: 0.9em;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
	line-height: 1.5;
}

.gg-booking-appointment-success {
	padding: 24px;
	background: var(--gg-color-success-soft);
	border: 1px solid var(--gg-color-success-soft);
	border-radius: 8px;
	text-align: center;
}

.gg-booking-appointment-success h3 {
	margin: 0 0 8px;
	color: var(--gg-color-success);
	font-size: 1.2em;
}

.gg-booking-appointment-success p {
	margin: 4px 0;
	color: var(--gg-color-text);
}

.gg-booking-appointment-success-id {
	font-size: 0.85em;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
}

.gg-booking-appointment-gate {
	padding: 20px;
	background: var(--gg-color-background);
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	text-align: center;
}

.gg-booking-appointment-gate p {
	margin: 0 0 12px;
}

.gg-booking-appointment-gate ul {
	margin: 0 0 12px;
	padding: 0;
	list-style: none;
}

.gg-booking-appointment-gate ul li {
	padding: 4px 0;
	color: var( --gg-color-text, var(--gg-color-text) );
}

/* Membership gate plan deep-links (membership-gate-signpost decision) — each
   qualifying plan links to the Memberships page anchored to that plan; the
   View Memberships button is the primary CTA below the list. Pure navigation,
   never a stacked purchase modal over the booker. */
.gg-booking-appointment-plan-link {
	color: var( --gg-color-primary, var(--gg-color-primary) );
	font-weight: 600;
	text-decoration: none;
}

.gg-booking-appointment-plan-link:hover,
.gg-booking-appointment-plan-link:focus {
	text-decoration: underline;
}

.gg-booking-appointment-memberships-btn {
	margin-top: 4px;
}

/* Actionable waiver gate (rule 73/74) — each unsigned waiver is a row with a
   "Review & Sign" button wired to the shared core-JS waiver modal. */
.gg-booking-appointment-waiver-list {
	list-style: none;
	margin: 0 0 12px;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.gg-booking-appointment-waiver-item {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 12px;
	background: var( --gg-surface, var(--gg-color-surface) );
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 6px;
	text-align: left;
}

.gg-booking-appointment-waiver-name {
	font-weight: 600;
	color: var( --gg-color-text, var(--gg-color-text) );
}

/* Login-gate buttons now carry the shared `.gg-booking-btn` primary/secondary
   classes (v1.1.49 Gates pass), so the brand look + the Gates Style controls
   style them. Only the inter-button spacing is bespoke here. */
.gg-booking-appointment-register-btn {
	margin-left: 8px;
}

/* Reset the native / Elementor-atomic <button>/<a> chrome (shadow + appearance)
   on the gate buttons so the default is clean and the Gate Button Kit controls
   (incl. the new secondary Box Shadow) are authoritative. The (0,3,0) double-
   class shadow reset beats the atomic baseline but ties the Kit controls, so a
   studio-set shadow still wins. No !important. */
.gg-booking-appointment-gate .gg-booking-btn {
	-webkit-appearance: none;
	appearance: none;
}

.gg-booking-appointment-gate .gg-booking-btn.gg-booking-btn--primary,
.gg-booking-appointment-gate .gg-booking-btn.gg-booking-btn--secondary {
	box-shadow: none;
}

@media ( max-width: 600px ) {
	.gg-booking-appointment-slot-grid {
		grid-template-columns: repeat( 2, 1fr );
	}
	.gg-booking-appointment-day {
		min-width: 60px;
	}
}

/* Appointment widget inside GGModal — the date strip scrolls horizontally
   in the narrower modal viewport rather than wrapping awkwardly. */
.gg-booking-appointment-widget--modal .gg-booking-appointment-date-strip {
	overflow-x: auto;
	flex-wrap: nowrap;
}

/* Modal-host editor preview (rule 9) — explains the headless role. */
.gg-booking-appointment-host-preview {
	padding: 20px;
	border: 1px dashed var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	background: var(--gg-color-background);
}

/* BookingForm modal-host editor note (rule 9) — the host is invisible on the
   live page; the note tells the studio it only skins the "Book" popup. */
.gg-booking-host-note {
	margin: 0 0 16px;
	padding: 10px 14px;
	border: 1px dashed var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
	background: var(--gg-color-background);
	color: var(--gg-color-text-muted, var(--gg-color-text-light));
	font-size: 13px;
	line-height: 1.5;
}

/* =====================================================================
   Services Showcase widget (Modal Arc PR-A2).
   Card grid that opens the appointment modal via the event bus. Hooks the
   shared --gg-* tokens (rule 46/115); all visual surfaces are also
   Elementor-overridable via ServicesShowcaseWidget style controls.
   ===================================================================== */

.gg-services-showcase {
	display: grid;
	gap: 24px;
}

.gg-services-showcase--grid {
	grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
}

.gg-services-showcase--list {
	grid-template-columns: 1fr;
}

.gg-services-showcase--list .gg-service-card {
	flex-direction: row;
}

.gg-services-showcase--list .gg-service-card__media {
	flex: 0 0 38%;
}

/* List image side (rule 117 — positioning). Default is image-left (the base
   `row` above). `--img-right` flips every row; `--img-alt` zigzags, starting
   image-left (odd rows stay `row`, even rows reverse). */
.gg-services-showcase--list.gg-services-showcase--img-right .gg-service-card {
	flex-direction: row-reverse;
}

.gg-services-showcase--list.gg-services-showcase--img-alt .gg-service-card:nth-child( even ) {
	flex-direction: row-reverse;
}

.gg-services-showcase--featured,
.gg-services-showcase--single {
	grid-template-columns: 1fr;
}

.gg-service-card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--gg-color-surface);
	border: 1px solid var( --gg-color-border, var(--gg-color-border) );
	border-radius: 10px;
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.gg-service-card__media {
	width: 100%;
	display: flex;
	/* justify-content follows the master Content Alignment var (default center);
	   the per-element Image alignment control overrides it. Only visible once the
	   Image Size is < 100%. */
	justify-content: var( --gg-svc-img-align, center );
}

.gg-service-card__img {
	display: block;
	width: 100%;
	max-width: none;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

.gg-service-card__img--placeholder {
	width: 100%;
	aspect-ratio: 16 / 9;
	background: linear-gradient(
		135deg,
		var( --gg-color-primary, var(--gg-color-primary) ) 0%,
		var( --gg-color-accent, var(--gg-color-primary) ) 100%
	);
	opacity: 0.18;
}

.gg-service-card__body {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	gap: 8px;
	padding: 18px;
}

.gg-service-card__name {
	margin: 0;
	font-family: var( --gg-type-heading, inherit );
	font-size: 1.15em;
	color: var( --gg-color-text, var(--gg-color-text) );
}

.gg-service-card__meta {
	font-size: 0.9em;
	font-weight: 600;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
}

.gg-service-card__desc {
	margin: 0;
	font-size: 0.92em;
	line-height: 1.5;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
}

.gg-service-card__cta {
	/* Fill, padding, radius, and hover come from the shared
	   .gg-booking-btn / .gg-booking-btn--primary base (rule 117 — additive
	   class on the markup). This rule keeps only the card-specific
	   positioning: push the CTA to the bottom of the flex-column card body. */
	margin-top: auto;
}

/* Card CTA defaults to NOT stretching (align-self:flex-start), so the Layout
   "Book Button Width" control governs full vs content width: its default
   (Full Width → width:100%) keeps the button edge-to-edge; switching to Auto
   shrinks it to content, and the Book Button alignment control then positions
   it. Scoped to the card body so the single-CTA hero (its own centered model)
   is untouched. */
.gg-service-card__body .gg-service-card__cta {
	/* Follows the master Content Alignment var (default flex-start); the
	   per-element Book Button alignment control overrides it. Only visible once
	   Book Button Width is Auto (Full Width spans regardless). */
	align-self: var( --gg-svc-cta-align, flex-start );
}

.gg-service-card__cta--single {
	margin: 0 auto;
	padding: 14px 28px;
	font-size: 1.05em;
}

.gg-services-showcase__empty {
	padding: 28px;
	text-align: center;
	color: var( --gg-color-text-muted, var(--gg-color-text-muted) );
	border: 1px dashed var( --gg-color-border, var(--gg-color-border) );
	border-radius: 8px;
}

/* Grid collapse is handled by the Columns control's mobile_default (rule 117 /
   GridControls). The old `.gg-services-showcase--grid` rules here (768px → 2col,
   480px → 1col) were DEAD — the per-instance control out-specifies them — and
   were removed v1.1.66. What remains is the list-view card stacking, normalized
   to the canonical 767px phone breakpoint (rule 117). */
@media ( max-width: 767px ) {
	.gg-services-showcase--list .gg-service-card,
	.gg-services-showcase--list.gg-services-showcase--img-right .gg-service-card,
	.gg-services-showcase--list.gg-services-showcase--img-alt .gg-service-card:nth-child( even ) {
		flex-direction: column;
	}
}

/* =====================================================================
   Client Dashboard — Notifications panel grouping (v0.7.112)

   Indeterminate state + power-user disclosure for the group-rollup UX
   in `ClientDashboardWidget::render_notifications_panel()`. Layout still
   rides on inline styles in PHP (matching the surrounding panels), but
   the colours were moved onto --gg-* tokens (v1.1.34 Phase 3b) so the
   panel inherits the studio's brand cascade; only :indeterminate styling
   and the <details> marker rotation need real CSS hooks.
   ===================================================================== */

.gg-booking-notif-group-toggle:indeterminate {
	background-image: linear-gradient(
		to bottom,
		transparent 35%,
		var( --gg-color-primary, #4a7c4a ) 35%,
		var( --gg-color-primary, #4a7c4a ) 65%,
		transparent 65%
	);
	background-color: var( --gg-color-primary, #4a7c4a );
}

/* WebKit's UA stylesheet draws the indeterminate dash by default, but the
   color follows accent-color when set. Pin to the GG primary so the dash
   reads as on-brand in both states. */
.gg-booking-notif-groups input[type="checkbox"],
.gg-booking-notif-list input[type="checkbox"] {
	accent-color: var( --gg-color-primary, #4a7c4a );
}

.gg-booking-notif-details > summary {
	list-style: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	user-select: none;
}

.gg-booking-notif-details > summary::-webkit-details-marker {
	display: none;
}

.gg-booking-notif-details > summary::before {
	content: "▸";
	display: inline-block;
	transition: transform 150ms ease;
	font-size: 11px;
}

.gg-booking-notif-details[open] > summary::before {
	transform: rotate( 90deg );
}

/* =====================================================================
   Client Dashboard — waiver signing modal (v1.1.36)

   Opened via GGModal from the dashboard "Waivers" section; the waiver
   text scrolls, an agree checkbox gates the Sign button. Tokens only.
   ===================================================================== */

.gg-booking-waiver-modal__content {
	max-height: 50vh;
	overflow-y: auto;
	margin-bottom: 16px;
	line-height: 1.6;
	color: var(--gg-color-text);
}

.gg-booking-waiver-modal__agree {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	cursor: pointer;
	margin-bottom: 16px;
	color: var(--gg-color-text);
}

.gg-booking-waiver-modal__agree input {
	accent-color: var(--gg-color-primary);
	margin-top: 2px;
}

.gg-booking-waiver-modal__actions {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
}

.gg-booking-waiver-modal__feedback {
	font-size: 14px;
}

.gg-booking-dashboard__waivers-intro {
	margin: 0 0 16px;
	color: var(--gg-color-text-muted);
	line-height: 1.5;
}

/* Editor-only secondary-button hover fix. In the Elementor editor canvas the
   e_atomic_elements <a>/<button> baseline keeps its (dark) text colour through
   :hover, beating the base `.gg-booking-btn--secondary:hover` colour (0,3,0) —
   so a filled green hover reads dark-on-dark. Live has no atomic baseline and
   is already correct, so this is scoped to the editor placeholder wrapper
   (`--editor`) and raised to (0,4,1) to win in the canvas without touching the
   published page. No !important (atomic doesn't use it — same as the
   brand-colour fix). */
.gg-booking-dashboard--editor a.gg-booking-btn.gg-booking-btn--secondary:hover,
.gg-booking-dashboard--editor a.gg-booking-btn.gg-booking-btn--secondary:focus,
.gg-booking-dashboard--editor button.gg-booking-btn.gg-booking-btn--secondary:hover,
.gg-booking-dashboard--editor button.gg-booking-btn.gg-booking-btn--secondary:focus {
	background-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

/* =====================================================================
   PR 4 — Container styling pass (v0.7.95)

   Foundation conventions any widget or starter page can opt into. Tokens
   defined in the :root block above. The per-widget walkthrough rolls
   each widget onto these incrementally — landing the foundations here
   means the per-widget passes are surgical (swap a value for a token,
   not invent a new convention).

   Layered top to bottom:
     1. Utility classes (.gg-page-section, .gg-prose, .gg-card-lift)
     2. Universal hover-lift sweep over the 5 frontend card classes
     3. Focus-visible accessibility outlines on interactive elements
     4. Touch-target floor on .gg-booking-btn
   ===================================================================== */

/* --- 1. Utilities -------------------------------------------------- */

/* Page-section wrapper for starter pages and any standalone widget
   container that needs to breathe with the viewport. Use as
   `<section class="gg-page-section">…</section>` around content blocks.
   The clamp() values scale smoothly from mobile (3rem block) to desktop
   (6rem block) with no breakpoint jumps. Inline padding lets content
   touch the edge on narrow screens and pull comfortably away on wide. */
.gg-page-section {
	padding-block:  var(--gg-section-padding-block);
	padding-inline: var(--gg-section-padding-inline);
	max-width:      72rem;       /* ~1152px content cap on wide displays */
	margin-inline:  auto;
	box-sizing:     border-box;
}

/* Variant: full-width section that still breathes vertically but lets
   inner content fill horizontally (for hero rows, dark bands, etc.). */
.gg-page-section--full {
	max-width: none;
	margin-inline: 0;
}

/* Prose container — caps text width at the comfortable reading measure.
   Drop inside .gg-page-section or any container for long-form copy. */
.gg-prose {
	max-width: var(--gg-color-text-measure);
	margin-inline: auto;
	font-size:   var(--gg-fluid-body);
	line-height: var(--gg-type-leading-normal, 1.55);
}

.gg-prose h1 { font-size: var(--gg-fluid-h1); line-height: var(--gg-type-leading-tight, 1.2);  margin-block-end: 0.4em; }
.gg-prose h2 { font-size: var(--gg-fluid-h2); line-height: var(--gg-type-leading-tight, 1.2);  margin-block-end: 0.45em; }
.gg-prose h3 { font-size: var(--gg-fluid-h3); line-height: var(--gg-type-leading-snug, 1.4);   margin-block-end: 0.5em; }
.gg-prose h4 { font-size: var(--gg-fluid-h4); line-height: var(--gg-type-leading-snug, 1.4);   margin-block-end: 0.6em; }
.gg-prose p  { margin-block: 0 1em; }
.gg-prose p:last-child { margin-block-end: 0; }

/* --- 2. Card hover-lift sweep ------------------------------------- */

/* Subtle elevation on hover for the 5 frontend content cards. Tokens
   keep direction (`--gg-hover-lift`) and timing (`--gg-duration-fast`,
   `--gg-ease-out`) consistent — and reduced-motion users get a 0px
   lift with 0ms duration automatically via the @media block above.
   Existing `:hover` rules on individual cards (e.g.
   .gg-booking-package-card at line 1531) are preserved; the
   transform layer composes additively. */
.gg-booking-schedule-card,
.gg-booking-class-card,
.gg-booking-sessions-card,
.gg-booking-package-card,
.gg-booking-membership-card {
	transition:
		transform   var(--gg-duration-fast) var(--gg-ease-out),
		box-shadow  var(--gg-duration-fast) var(--gg-ease-out),
		border-color var(--gg-duration-fast) var(--gg-ease-out);
	will-change: transform;
}

.gg-booking-schedule-card:hover,
.gg-booking-class-card:hover,
.gg-booking-sessions-card:hover,
.gg-booking-package-card:hover,
.gg-booking-membership-card:hover {
	transform:  translateY( var(--gg-hover-lift) );
	box-shadow: var(--gg-shadow-md);
}

/* Don't lift cards that are visually disabled or marked complete. */
.gg-booking-class-card--empty:hover,
.gg-booking-package-card--owned:hover {
	transform: none;
}

/* --- 3. Focus-visible accessibility outlines ---------------------- */

/* Every interactive element inside a GG widget wrapper gets a
   consistent focus ring on keyboard focus. Mouse-click focus stays
   suppressed (`:focus-visible` only), so the page doesn't look like
   it's screaming at studios who navigate with a cursor. Outline
   color routes through the token cascade — studios who customized
   their Studio Style primary color get a matching focus ring. */
.gg-booking-widget-inner :is(
	a,
	button,
	input,
	select,
	textarea,
	[tabindex]:not([tabindex="-1"])
):focus-visible {
	outline:        2px solid var(--gg-color-focus, var(--gg-color-primary));
	outline-offset: 2px;
	border-radius:  var(--gg-radius-sm);
	box-shadow:     var(--gg-shadow-focus, 0 0 0 3px var(--gg-color-focus-ring));
}

/* --- 4. Touch-target floor ---------------------------------------- */

/* WCAG 2.5.5 — primary interactive elements should be at least 44×44.
   Applied to the canonical button class. Padding stays unchanged
   (existing buttons read clean); min-height kicks in only when
   intrinsic content height is below the floor. */
.gg-booking-btn {
	min-height: var(--gg-touch-target);
}

/* --- 5. Starter page card --------------------------------------- */

/* Styled card wrapper applied to the 7 one-click `StarterPageImporter`
   pages (Schedule, Book a Class, My Account, Instructor Dashboard,
   Packages & Memberships, Login, Password Reset).

   ──────────────────────────────────────────────────────────────────
   The cascade in three layers:

   1. Body class detection — `Frontend::add_starter_page_body_class`
      reads the `_gg_starter_page_key` postmeta the importer stamps
      on each page, and appends `gg-starter-page` plus
      `gg-starter-page--{slug}` to <body>. Every rule below is
      scoped under those classes so non-starter pages stay untouched.
      NOTE: the DOM-structural selectors (`.e-parent > .e-con-inner`
      and `.e-con-inner > .e-con.e-child`) are ALSO anchored under
      `[data-elementor-type="wp-page"]` — the Theme Builder header and
      footer are Elementor containers too, so without that anchor these
      rules painted the header/footer sub-containers with the card's
      bg/border/shadow/padding + `align-items:center` on every starter
      page. The anchor confines them to the page-content tree.

   2. Two parallel target selectors for the card itself:
        a. `.gg-starter-page-card` — set by
           `StarterPageImporter::card_container()` via Elementor's
           container `css_classes` setting.
        b. `.e-con-inner > .e-con.e-child` — DOM-structural fallback
           that matches the inner nested container by position alone,
           in case the class route is stripped by a future Elementor
           renderer change.
      Either selector reaches the same rule body.

   3. Three centering mechanisms, one for each layout layer:
        a. PARENT — `body.gg-starter-page .e-parent > .e-con-inner`
           gets `align-items: center` so the card centres on the
           cross-axis of the outer container's flex column. The
           direct-child `>` is critical — without it the card's own
           inner wrapper would also inherit align-items: center,
           which shrinks the widget inside.
        b. CARD — `.gg-starter-page-card` itself gets `max-width` (per
           tier below) + `margin-inline: auto` as belt-and-suspenders
           in case any future structure breaks the parent path.
        c. WIDGET — `.gg-booking-widget-inner > [class^="gg-booking-"]`
           gets `margin-inline: auto` so the widget's outermost class
           centres inside the card. The direct-child `>` confines
           the rule to the top-level widget class only — nested
           element classes (.gg-booking-dashboard__tab etc.) keep
           the widget's own internal alignment.

   ── Per-page width tiers (via the body class modifier):
        wide    min(80rem, 98%) — Schedule
        medium  min(72rem, 95%) — My Account, Instructor Dashboard, Memberships
        narrow  min(60rem, 92%) — Booking, Login, Password Reset
   Fluid via `min()` so cards scale with viewport — the rem term caps
   on very-wide monitors, the percentage makes cards fill nearly the
   full container on typical 1200-1440px desktops.

   ── Each widget's own width default stands untouched: the content widgets
   (dashboards/profile, schedule, grids) self-cap via the Widget Frame
   per-type caps on .gg-booking-widget-inner (rule 122 — dashboards/profile
   56rem, grids/schedule 80rem, etc.), and the form widgets cap their own
   form card (.gg-booking-booking-form-wrapper 560px, etc.). The widget keeps
   its content-appropriate width; the card centres it. (The dashboards no
   longer carry hard inner max-widths — removed v1.1.65 so the Frame governs;
   see "Per-widget-type content caps".) */

body.gg-starter-page [data-elementor-type="wp-page"] .e-parent > .e-con-inner {
	/* !important breaks the cascade tie with Elementor's
	   `align-items: var(--align-items)` rule which has equal
	   property-level specificity but loads later.
	   The `[data-elementor-type="wp-page"]` anchor confines this to the
	   page-content tree — without it, this matched the Theme Builder
	   header/footer containers too (they're Elementor containers as
	   well), distorting them on every starter page. */
	align-items: center !important;
}

/* (Retired in the Widget Frame standard.) This rule used to force-centre
   the widget's top-level element inside the starter card with
   `margin-inline: auto !important`. Every widget now owns its position via
   the universal Frame's Alignment control (Kit gg_register_layout_controls
   `frame`, on .gg-booking-widget-inner — or the form card for the form/auth
   widgets). The !important here OVERRODE that per-instance Alignment on
   starter pages (a right-aligned form snapped back to centre), so it's gone.
   Widgets still centre by default: content widgets via widget-inner's base
   margin-inline:auto + the Frame Alignment default (Center); the form/auth
   widgets via their Frame Alignment default (Center). The card itself still
   centres + caps via the rule below. */

body.gg-starter-page .gg-starter-page-card,
body.gg-starter-page [data-elementor-type="wp-page"] .e-con-inner > .e-con.e-child {
	/* All carded pages (Booking, Login, Password Reset) use the
	   narrow tier — they're forms with a focused, focal feel. Self-
	   contained content widgets (Schedule, My Account, Instructor
	   Dashboard, Memberships) render directly on the page background
	   without a card, so their old wide/medium variants were
	   retired in v0.7.111. */
	--gg-starter-card-max-width: min(60rem, 92%);

	/* Element-level !important breaks the cascade tie with
	   Elementor's `.e-con { width: var(--width); margin-inline:
	   var(--margin-*); }` rules — same specificity, later load
	   order. */
	max-width:        var(--gg-starter-card-max-width) !important;
	width:            100% !important;
	margin-inline:    auto !important;

	/* Translucent white so the cream page background bleeds through
	   subtly. Softer than a hard panel — more "layered glass" feel.
	   The cascade fallback (--gg-color-surface defaults to pure
	   white) preserves the original treatment if a studio
	   overrides the surface token. */
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: rgba(255, 255, 255, 0.6);
	/* Subtle hairline reinforces card edge against the page bg even
	   when the studio has matched their page background to white via
	   Studio Style — shadow alone gets washed out on white-on-white. */
	border:           1px solid var(--gg-color-border);
	border-radius:    var(--gg-radius-lg, 16px);
	/* Stronger shadow now that only the 3 form pages (Booking, Login,
	   Password Reset) keep the card — they're focal points that
	   benefit from a slightly more prominent panel. */
	box-shadow:       var(--gg-shadow-lg, 0 8px 32px rgba(28, 26, 22, 0.12));
	padding:          var(--gg-space-7, 2.5rem);
	box-sizing:       border-box;
}

/* Mobile: tighten card padding so the layout doesn't feel cramped
   on phones. */
@media ( max-width: 600px ) {
	body.gg-starter-page .gg-starter-page-card,
	body.gg-starter-page [data-elementor-type="wp-page"] .e-con-inner > .e-con.e-child {
		padding: var(--gg-space-5, 1.5rem);
	}
}

/* ── Leveled-up public-page scaffold bands ────────────────────────────
   The three marketing-adjacent starter pages (Schedule, Memberships,
   Services) ship a full hero → context → widget → supporting → CTA
   scaffold (StarterPageImporter::get_leveled_up_page_elements). Every
   band's chrome lives here, token-driven so it inherits the studio brand
   (rules 132 + 150) — the importer bakes NO inline color. Each band is a
   plain Elementor container the studio can restyle or delete.

   color-mix() lets the soft brand tints track the studio's primary; the
   plain declaration directly above each is the pre-color-mix fallback. */

/* HERO — full-bleed soft-tint band; the H1 + subtitle sit centred in a
   boxed inner container. Shared by starter PAGES (`gg-starter-page`) and
   Theme Builder TEMPLATE singles (`gg-starter-template`, §7.2) — the
   template hero carries the same chrome but rides the CPT-single body
   class so it styles class/instructor singles without the page-only card
   rules. */
body.gg-starter-page .gg-starter-hero,
body.gg-starter-template .gg-starter-hero {
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-background, #fbf9f4);
	background-color: color-mix( in srgb, var(--gg-color-primary) 7%, var(--gg-color-background, #fbf9f4) );
	padding-block: var(--gg-space-9, 4rem);
	text-align: center;
}

body.gg-starter-page .gg-starter-hero__inner,
body.gg-starter-template .gg-starter-hero__inner {
	max-width: 46rem;
	margin-inline: auto;
	/* The inner is an Elementor flex column; without this its children size
	   to content and sit at flex-start (left). Centering the items lets the
	   short subtitle line sit centred under the heading instead of hugging
	   the left edge. !important beats Elementor's later-loading
	   `align-items: var(--align-items)` container rule (same pattern as the
	   card-centering block above). */
	align-items: center !important;
	text-align: center;
}

body.gg-starter-page .gg-starter-hero__sub,
body.gg-starter-template .gg-starter-hero__sub {
	margin-top: var(--gg-space-3, 0.75rem);
	font-size: 1.2rem;
	line-height: var(--gg-type-leading-snug, 1.4);
	color: var(--gg-color-text-muted, #6b6357);
	text-align: center;
}

/* HOME hero CTA — extra breathing room under the subtitle so the button
   doesn't crowd the tagline (P10; the hero already centres its children). */
body.gg-starter-page--home .gg-starter-hero .elementor-widget-button {
	margin-top: var(--gg-space-5, 1.5rem);
}

/* TEMPLATE HERO META — inline row of dynamic-tag chips under the H1
   (class level/duration/instructor/next-date; instructor specialties).
   Each chip is a native Heading widget bound to one dynamic tag, so an
   empty value collapses the chip entirely via the `:has(:empty)` rule
   below — the designed empty state (a brand-new class with no level set
   shows no stray pill). */
body.gg-starter-template .gg-starter-hero__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--gg-space-2, 0.5rem) var(--gg-space-3, 0.75rem);
	justify-content: center;
	align-items: center;
	margin-top: var(--gg-space-4, 1rem);
}

body.gg-starter-template .gg-starter-hero__meta-item .elementor-heading-title {
	display: inline-block;
	padding: 0.3em 0.85em;
	font-size: 0.95rem;
	font-weight: 500;
	line-height: 1.3;
	color: var(--gg-color-text, #2c2722);
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-surface, #fff);
	background-color: color-mix( in srgb, var(--gg-color-primary) 9%, var(--gg-color-background, #fbf9f4) );
	border: 1px solid var(--gg-color-border, #e6e1d8);
	border-radius: 999px;
}

/* Hide a meta chip whose dynamic tag resolved to nothing. Covers both the
   empty-heading-title case and Elementor's early-return empty container.
   No-`:has` browsers degrade to an empty (zero-content) flex slot — the
   `gap` keeps it from looking broken. */
body.gg-starter-template .gg-starter-hero__meta-item:has( .elementor-heading-title:empty ),
body.gg-starter-template .gg-starter-hero__meta-item:has( > .elementor-widget-container:empty ) {
	display: none;
}

/* LOCATION single body (T6) — the one tag-composed template (Location has no
   self-resolving display widget). Stacks photo → description → directions
   button → phone, centred in a readable column. Each child is a native widget
   bound to a Location dynamic tag, so an unset field collapses to nothing via
   the empty-state rules below (a brand-new location with no photo/phone reads
   as intentional, not broken). Token-driven; no inline color. */
body.gg-starter-template .gg-starter-location {
	max-width: 48rem;
	margin-inline: auto;
	text-align: center;
}

body.gg-starter-template .gg-starter-location__photo img {
	width: 100%;
	height: auto;
	border-radius: var(--gg-radius-lg, 16px);
}

body.gg-starter-template .gg-starter-location__desc {
	margin-top: var(--gg-space-5, 1.5rem);
	color: var(--gg-color-text-muted, #6b6357);
	line-height: var(--gg-type-leading-relaxed, 1.6);
}

body.gg-starter-template .gg-starter-location__directions {
	margin-top: var(--gg-space-5, 1.5rem);
}

body.gg-starter-template .gg-starter-location__phone {
	margin-top: var(--gg-space-4, 1rem);
	font-weight: 500;
	color: var(--gg-color-text, #2c2722);
}

/* Empty-field collapse: hide the photo when the dynamic image resolved to
   nothing (no <img> rendered), and hide a text block whose dynamic tag came
   back empty. Mirrors the hero-meta `:has(:empty)` pattern. No-`:has`
   browsers keep the (empty) widget box — harmless, just a little extra gap. */
body.gg-starter-template .gg-starter-location__photo:not( :has( img ) ),
body.gg-starter-template .gg-starter-location__desc:has( > .elementor-widget-container:empty ),
body.gg-starter-template .gg-starter-location__phone:has( > .elementor-widget-container:empty ),
body.gg-starter-template .gg-starter-location__directions:not( :has( a[href]:not( [href=""] ) ) ) {
	display: none;
}

/* INSTRUCTOR loop card (T4 archive) — the compact tag-composed card the Loop
   Grid repeats once per instructor: round photo → linked name → specialties.
   Card chrome is token-driven; the grid columns/gaps come from Elementor's own
   loop-grid stylesheet, so this only styles the card interior. `height: 100%`
   lets the Loop Grid's Equal-Height option line cards up. */
body.gg-starter-template .gg-starter-loop-instructor {
	height: 100%;
	padding: var(--gg-space-5, 1.5rem);
	text-align: center;
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-surface, #fff);
	background-color: color-mix( in srgb, var(--gg-color-primary) 4%, var(--gg-color-surface, #fff) );
	border: 1px solid var(--gg-color-border, #e6e1d8);
	border-radius: var(--gg-radius-lg, 16px);
}

body.gg-starter-template .gg-starter-loop-instructor__photo img {
	width: 120px;
	height: 120px;
	object-fit: cover;
	border-radius: 999px;
	margin-inline: auto;
}

body.gg-starter-template .gg-starter-loop-instructor__name {
	margin-top: var(--gg-space-3, 0.75rem);
}

body.gg-starter-template .gg-starter-loop-instructor__name a {
	color: var(--gg-color-text, #2c2722);
	text-decoration: none;
}

body.gg-starter-template .gg-starter-loop-instructor__name a:hover {
	color: var(--gg-color-primary, #254032);
}

body.gg-starter-template .gg-starter-loop-instructor__specialties .elementor-heading-title {
	font-size: 0.95rem;
	color: var(--gg-color-text-muted, #6b6357);
}

/* Collapse the photo when no instructor photo is set (designed empty state). */
body.gg-starter-template .gg-starter-loop-instructor__photo:not( :has( img ) ) {
	display: none;
}

/* CLASS ARCHIVE tag cloud (T3) — the Pro taxonomy-filter widgets (Category /
   Type / Level) rendered as a clickable pill cloud above the loop grid. Three
   widgets stack into one tag area; each emits `<search class="e-filter">` with
   `<button class="e-filter-item" aria-pressed>` pills. Styled here (overrides
   Elementor's default filter-bar look) as wrapping, brand-tinted pills; the
   selected state (aria-pressed) fills with the brand colour. Token-driven. */
body.gg-starter-template .gg-starter-tag-cloud {
	padding-block: var(--gg-space-6, 2rem);
	text-align: center;
}

body.gg-starter-template .gg-starter-tag-cloud .elementor-widget-taxonomy-filter {
	margin-block: var(--gg-space-1, 0.25rem);
}

body.gg-starter-template .gg-starter-tag-cloud .e-filter {
	display: flex;
	flex-wrap: wrap;
	gap: var(--gg-space-2, 0.5rem);
	justify-content: center;
	padding: 0;
	border: 0;
}

body.gg-starter-template .gg-starter-tag-cloud .e-filter-item {
	padding: 0.35em 0.95em;
	font-size: 0.9rem;
	line-height: 1.3;
	color: var(--gg-color-text, #2c2722);
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-background, #fbf9f4);
	background-color: color-mix( in srgb, var(--gg-color-primary) 7%, var(--gg-color-background, #fbf9f4) );
	border: 1px solid var(--gg-color-border, #e6e1d8);
	border-radius: 999px;
	cursor: pointer;
	transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}

body.gg-starter-template .gg-starter-tag-cloud .e-filter-item:hover {
	border-color: var(--gg-color-primary, #254032);
}

body.gg-starter-template .gg-starter-tag-cloud .e-filter-item[aria-pressed="true"] {
	color: #fff;
	background-color: var(--gg-color-primary, #254032);
	border-color: var(--gg-color-primary, #254032);
}

/* ROOM single body — same tag-composed pattern as the Location single:
   photo → description → equipment → "View location" button. */
body.gg-starter-template .gg-starter-room {
	max-width: 48rem;
	margin-inline: auto;
	text-align: center;
}

body.gg-starter-template .gg-starter-room__photo img {
	width: 100%;
	height: auto;
	border-radius: var(--gg-radius-lg, 16px);
}

body.gg-starter-template .gg-starter-room__desc,
body.gg-starter-template .gg-starter-room__equipment {
	margin-top: var(--gg-space-5, 1.5rem);
	color: var(--gg-color-text-muted, #6b6357);
	line-height: var(--gg-type-leading-relaxed, 1.6);
}

body.gg-starter-template .gg-starter-room__location-link {
	margin-top: var(--gg-space-5, 1.5rem);
}

body.gg-starter-template .gg-starter-room__photo:not( :has( img ) ),
body.gg-starter-template .gg-starter-room__desc:has( > .elementor-widget-container:empty ),
body.gg-starter-template .gg-starter-room__equipment:has( > .elementor-widget-container:empty ),
body.gg-starter-template .gg-starter-room__location-link:not( :has( a[href]:not( [href=""] ) ) ) {
	display: none;
}

/* LOCATION + ROOM loop cards (archives) — share the instructor loop card's
   chrome but use a rectangular image instead of a round headshot. */
body.gg-starter-template .gg-starter-loop-location,
body.gg-starter-template .gg-starter-loop-room {
	height: 100%;
	padding: var(--gg-space-5, 1.5rem);
	text-align: center;
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-surface, #fff);
	background-color: color-mix( in srgb, var(--gg-color-primary) 4%, var(--gg-color-surface, #fff) );
	border: 1px solid var(--gg-color-border, #e6e1d8);
	border-radius: var(--gg-radius-lg, 16px);
}

body.gg-starter-template .gg-starter-loop-location__photo img,
body.gg-starter-template .gg-starter-loop-room__photo img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--gg-radius-md, 10px);
}

body.gg-starter-template .gg-starter-loop-location__name,
body.gg-starter-template .gg-starter-loop-room__name {
	margin-top: var(--gg-space-3, 0.75rem);
}

body.gg-starter-template .gg-starter-loop-location__name a,
body.gg-starter-template .gg-starter-loop-room__name a {
	color: var(--gg-color-text, #2c2722);
	text-decoration: none;
}

body.gg-starter-template .gg-starter-loop-location__name a:hover,
body.gg-starter-template .gg-starter-loop-room__name a:hover {
	color: var(--gg-color-primary, #254032);
}

body.gg-starter-template .gg-starter-loop-location__address .elementor-heading-title,
body.gg-starter-template .gg-starter-loop-room__capacity .elementor-heading-title,
body.gg-starter-template .gg-starter-loop-room__location .elementor-heading-title {
	font-size: 0.95rem;
	color: var(--gg-color-text-muted, #6b6357);
}

body.gg-starter-template .gg-starter-loop-location__photo:not( :has( img ) ),
body.gg-starter-template .gg-starter-loop-room__photo:not( :has( img ) ) {
	display: none;
}

/* STEPS — "how it works" row of equal cards. */
body.gg-starter-page .gg-starter-steps {
	padding-block: var(--gg-space-7, 2.5rem);
	text-align: center;
}

body.gg-starter-page .gg-starter-steps__row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--gg-space-5, 1.5rem);
	justify-content: center;
	margin-top: var(--gg-space-5, 1.5rem);
}

body.gg-starter-page .gg-starter-step {
	flex: 1 1 220px;
	max-width: 22rem;
	padding: var(--gg-space-5, 1.5rem);
	text-align: center;
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-surface, #fff);
	background-color: color-mix( in srgb, var(--gg-color-primary) 4%, var(--gg-color-surface, #fff) );
	border: 1px solid var(--gg-color-border, #e6e1d8);
	border-radius: var(--gg-radius-lg, 16px);
}

body.gg-starter-page .gg-starter-step p {
	margin-top: var(--gg-space-2, 0.5rem);
	color: var(--gg-color-text-muted, #6b6357);
}

/* FAQ — stacked question/answer pairs with hairline dividers. */
body.gg-starter-page .gg-starter-faq {
	padding-block: var(--gg-space-7, 2.5rem);
	max-width: 48rem;
	margin-inline: auto;
}

body.gg-starter-page .gg-starter-faq__item {
	padding-block: var(--gg-space-4, 1rem);
	border-top: 1px solid var(--gg-color-border, #e6e1d8);
}

body.gg-starter-page .gg-starter-faq__item p {
	margin-top: var(--gg-space-2, 0.5rem);
	color: var(--gg-color-text-muted, #6b6357);
}

/* CTA — contained rounded panel with a stronger brand tint; the studio's
   kit primary button stands out against it (no button override, so the
   Elementor-kit button specificity gotcha never comes into play). */
body.gg-starter-page .gg-starter-cta {
	margin-block: var(--gg-space-7, 2.5rem);
	padding: var(--gg-space-8, 3rem) var(--gg-space-6, 2rem);
	text-align: center;
	border-radius: var(--gg-radius-lg, 16px);
	/* stylelint-disable-next-line declaration-property-value-disallowed-list */
	background-color: var(--gg-color-background, #fbf9f4);
	background-color: color-mix( in srgb, var(--gg-color-primary) 12%, var(--gg-color-background, #fbf9f4) );
}

body.gg-starter-page .gg-starter-cta__sub {
	margin-top: var(--gg-space-2, 0.5rem);
	margin-bottom: var(--gg-space-5, 1.5rem);
	color: var(--gg-color-text-muted, #6b6357);
}

/* Mobile: ease hero/CTA vertical rhythm and stack the steps row. */
@media ( max-width: 600px ) {
	body.gg-starter-page .gg-starter-hero,
	body.gg-starter-template .gg-starter-hero {
		padding-block: var(--gg-space-7, 2.5rem);
	}

	body.gg-starter-page .gg-starter-cta {
		padding: var(--gg-space-6, 2rem) var(--gg-space-5, 1.5rem);
	}
}

/* =========================================================================
   Elementor-Kit armor — scoped to .gg-booking--gg (compose-mode marker)
   =========================================================================
   The render seam (core PaletteControls::gg_widget_wrapper_open) stamps
   .gg-booking--gg on a widget's OUTER wrapper ONLY when a palette is resolved
   — i.e. for the GG-default + named palettes, NEVER for "Inherit". Host
   Elementor themes inject `.elementor-kit-{N} button | a | h1..h6` rules at
   specificity (0,1,1); these out-rank Booking's single-class (0,1,0) brand
   rules and repaint buttons / headings / links with the host Kit's chrome even
   after a GG palette is chosen — so on a Kit-themed site Inherit and a chosen
   palette can look identical. That gap is what these rules close.

   CONTRACT — purely a SPECIFICITY layer, never a value change:
   • `.gg-booking--gg .<class>` is (0,2,0), which BEATS the Kit's (0,1,1).
   • Each rule re-asserts the SAME var/value the element's existing (losing)
     rule already declares (compose-mode defines `--gg-*` on the wrapper).
   • Because the marker is ABSENT on Inherit, Inherit stays bare and keeps
     composing with the page/Kit; only a chosen palette wins here.
   • NO `!important`: Elementor's per-widget Style controls emit
     `{{WRAPPER}} .<class>` (also (0,2,0)) and load AFTER this sheet, so they
     TIE these rules and win on source order — widgets stay fully customizable
     ("beautiful by default AND customizable").

   Body-mounted surfaces (GGModal, FullCalendar, the calendar popover) are NOT
   descendants of the wrapper and carry their own armor elsewhere; the one
   popover link below is scoped to .gg-booking-cal-popover, not the marker.

   KNOWN RESIDUAL (deliberate): genuinely class-less <h3>/<h4> sub-headings
   inside a few widgets can only be reached by an element-scoped selector, which
   is at most (0,1,1) under the single marker — that TIES the Kit and loses on
   source order — or (0,2,1) with a doubled marker, which would over-rank the
   (0,2,0) per-widget Heading Color controls above and break customizability.
   Neither is acceptable, so class-less headings are left to compose with the
   Kit this pass (add a class in PHP if a specific one proves distracting).
   ========================================================================= */

/* --- A. Buttons: box-model + bare-button families ------------------------ */
/* Button COLOUR is already armored via the double-class .gg-booking-btn--primary
   / --secondary rules. The bit that loses to the Kit `button`/`a` (0,1,1) is the
   box model + flat chrome: re-assert padding / radius / weight and neutralise the
   Kit's uppercasing + shadow. */
.gg-booking--gg .gg-booking-btn {
	padding: 10px 18px;
	border-radius: 4px;
	font-weight: 600;
	text-transform: none;
	box-shadow: none;
}

.gg-booking--gg .gg-booking-btn--outline {
	color: var(--gg-color-primary);
	border: 1px solid var(--gg-color-primary);
	border-radius: 6px;
	padding: 10px 20px;
	text-transform: none;
	box-shadow: none;
}

.gg-booking--gg .gg-booking-btn--outline:hover {
	background: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

/* Client dashboard tabs — bare <button>s the Kit repaints + adds chrome to. */
.gg-booking--gg .gg-booking-dashboard__tab {
	background: none;
	border: none;
	border-bottom: 2px solid transparent;
	color: var(--gg-color-text-muted);
	text-transform: none;
	box-shadow: none;
}

.gg-booking--gg .gg-booking-dashboard__tab:hover {
	color: var(--gg-color-text);
}

.gg-booking--gg .gg-booking-dashboard__tab--active {
	color: var(--gg-color-primary);
	border-bottom-color: var(--gg-color-primary);
}

/* Discovery filter pills (resting + hover; .is-active is already double-class). */
.gg-booking--gg .gg-booking-discovery-pill {
	background-color: transparent;
	border: 1px solid var(--gg-color-border);
	color: var(--gg-color-text);
	text-transform: none;
	box-shadow: none;
}

.gg-booking--gg .gg-booking-discovery-pill:hover {
	border-color: var(--gg-color-primary);
	color: var(--gg-color-primary);
}

/* Date-filter buttons (resting + hover + active). */
.gg-booking--gg .gg-booking-date-btn {
	background: var(--gg-color-background);
	border: 1px solid var(--gg-color-border);
	color: var(--gg-color-text);
	text-transform: none;
	box-shadow: none;
}

.gg-booking--gg .gg-booking-date-btn:hover {
	border-color: var(--gg-color-primary);
	color: var(--gg-color-primary);
}

.gg-booking--gg .gg-booking-date-btn--active,
.gg-booking--gg .gg-booking-date-btn--active:hover {
	background: var(--gg-color-primary);
	border-color: var(--gg-color-primary);
	color: var(--gg-color-surface);
}

/* Schedule pagination chips (.is-active is already double-class). */
.gg-booking--gg .gg-booking-schedule-pagination__page {
	border: 1px solid var(--gg-color-border);
	color: var(--gg-color-text);
	text-transform: none;
	box-shadow: none;
}

/* Login/register toggle rendered as a bare <button> link: the existing
   `button.gg-booking-login-form__link` arm is only (0,1,1) and TIES the Kit
   `button` (losing on source order); the marker lifts it to (0,2,1). */
.gg-booking--gg button.gg-booking-login-form__link {
	background: none;
	border: 0;
	box-shadow: none;
	color: var(--gg-color-primary);
	text-transform: none;
}

/* Log-in trigger / account button — colours come from the .gg-booking-btn
   classes it also carries (armored above); just hold off the Kit chrome. */
.gg-booking--gg .gg-booking-login-button {
	text-transform: none;
	box-shadow: none;
}

/* --- B. Headings: re-assert each heading's own colour -------------------- */
/* Single-class `color: var(--gg-color-text)` (etc.) loses to the Kit `h1..h6`
   (0,1,1); the marker lifts each to (0,2,0). Values re-asserted verbatim; the
   per-widget Heading Color controls ({{WRAPPER}} …, also (0,2,0), loaded after)
   still override. */
.gg-booking--gg .gg-booking-dashboard__section-title,
.gg-booking--gg .gg-booking-dashboard__client-name,
.gg-booking--gg .gg-booking-class-card__title,
.gg-booking--gg .gg-booking-instructor-profile__name,
.gg-booking--gg .gg-booking-instructor-profile__schedule-title,
.gg-booking--gg .gg-booking-package-card__title,
.gg-booking--gg .gg-booking-instructor-dashboard__greeting,
.gg-booking--gg .gg-booking-instructor-dashboard__class-name,
.gg-booking--gg .gg-booking-membership-gate__title,
.gg-booking--gg .gg-booking-login-form__heading,
.gg-booking--gg .gg-booking-login-panel__greeting,
.gg-booking--gg .gg-booking-appointment-title,
.gg-booking--gg .gg-service-card__name {
	color: var(--gg-color-text, var(--gg-color-text));
}

.gg-booking--gg .gg-booking-enrollment-panel__title {
	color: var(--gg-color-text-muted, var(--gg-color-text-muted));
}

/* These two titles carry NO colour of their own — they inherit their card's
   text colour; re-assert `inherit` so a Kit h* rule can't hijack them. */
.gg-booking--gg .gg-booking-schedule-card__title,
.gg-booking--gg .gg-booking-booking-form__title {
	color: inherit;
}

/* --- C. Links: standalone brand-coloured anchors ------------------------- */
/* Single-class `color: var(--gg-color-primary)` loses to the Kit `a` (0,1,1). */
.gg-booking--gg .gg-booking-login-form__link,
.gg-booking--gg .gg-booking-login-panel__link,
.gg-booking--gg .gg-booking-appointment-plan-link,
.gg-booking--gg .gg-booking-membership-gate__plan-link {
	color: var(--gg-color-primary, var(--gg-color-primary));
}

/* De-emphasised links keep their muted colour. */
.gg-booking--gg .gg-booking-login-panel__logout,
.gg-booking--gg .gg-booking-discovery-cloud__clear {
	color: var(--gg-color-text-muted);
}

/* Body-mounted: the calendar popover mounts on <body>, outside the wrapper —
   arm its view-link under its own container marker, matching the popover-close
   armor above. */
.gg-booking-cal-popover .gg-booking-cal-popover__view-link {
	color: var(--gg-color-primary, var(--gg-color-primary));
}
