/* Urwebsol LMS Elementor Addon — frontend styles for the widget library and template builder */

.jrl-course-grid {
	--jrl-grid-columns: 4;
	--jrl-grid-gap: 24px;
	display: grid;
	grid-template-columns: repeat(var(--jrl-grid-columns), 1fr);
	gap: var(--jrl-grid-gap);
}

.jrl-course-grid--compact-list {
	grid-template-columns: 1fr;
}

.jrl-course-card {
	display: flex;
	flex-direction: column;
	border-radius: 8px;
	overflow: hidden;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.jrl-course-grid--compact-list .jrl-course-card {
	flex-direction: row;
	align-items: center;
}

.jrl-course-grid--overlay .jrl-course-card {
	position: relative;
}

.jrl-course-grid--overlay .jrl-course-card__body {
	position: absolute;
	inset: auto 0 0 0;
	background: linear-gradient(0deg, rgba(0, 0, 0, 0.7), transparent);
	color: #fff;
}

.jrl-course-card__thumb img {
	width: 100%;
	height: auto;
	display: block;
}

.jrl-course-card__body {
	padding: 16px;
}

.jrl-course-card__title {
	margin: 0 0 8px;
	font-size: 1.05em;
}

.jrl-course-card__title a {
	color: inherit;
	text-decoration: none;
}

.jrl-course-grid__pagination {
	margin-top: 24px;
	display: flex;
	gap: 8px;
	justify-content: center;
}

.jrl-cat-nav {
	position: relative;
}

.jrl-cat-nav__hamburger {
	position: relative;
	background: transparent;
	border: 0;
	cursor: pointer;
	padding: 8px;
	z-index: 1001;
}

/* Override Hello Elementor's reset.css `button:hover,:focus{background-color:#c36;color:#fff}`.
   The `color` half of that rule is the real culprit behind "button disappears on hover/tap,
   reappears once you move the mouse/tap elsewhere" reported on Safari/Chrome/Edge alike —
   the icon uses `currentColor`, so flipping to white text made it invisible against a
   light background for as long as :hover/:focus stayed active. */
.jrl-cat-nav__hamburger:hover,
.jrl-cat-nav__hamburger:focus {
	background-color: transparent;
	color: inherit;
}

/* The icon span itself had no visual styling at all — button rendered but was
   effectively invisible (transparent, empty). 3-bar hamburger via box-shadow trick. */
.jrl-cat-nav__hamburger-icon {
	display: block;
	width: 20px;
	height: 2px;
	background: currentColor;
	box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor;
}

/* Separate, static "X" glyph — swapped in place of the bars via plain display:none/block
   (no transform/transition morph). A CSS-transition-driven pseudo-element morph proved
   unreliable in this project's test environment (delayed repaint until an unrelated
   interaction), so two plain elements toggled by display is used instead for reliability. */
.jrl-cat-nav__close-icon {
	display: none;
	font-size: 26px;
	line-height: 1;
}

.jrl-cat-nav--mobile-open .jrl-cat-nav__hamburger-icon {
	display: none;
}

.jrl-cat-nav--mobile-open .jrl-cat-nav__close-icon {
	display: block;
}

/* Row wrapper for the scrollable category list + its prev/next arrows. A separate
   flex context from `.jrl-cat-nav__list` itself (which stays its own flex row, laid
   out via the `list_display` Elementor control) so the arrows can sit beside the list
   rather than above/below it — `.jrl-cat-nav__list` needs `min-width: 0` below so it
   can actually shrink and scroll inside this row instead of stretching it. */
.jrl-cat-nav__list-wrap {
	display: flex;
	align-items: center;
}

.jrl-cat-nav__list {
	list-style: none;
	margin: 0;
	padding: 0;
	gap: 24px;
	min-width: 0;
	overflow-x: auto;
	scroll-behavior: smooth;
	scrollbar-width: none;
}

.jrl-cat-nav__list::-webkit-scrollbar {
	display: none;
}

.jrl-cat-nav__item {
	position: relative;
	flex: 0 0 auto;
}

.jrl-cat-nav__link {
	background: none;
	border: 0;
	font: inherit;
	cursor: pointer;
	padding: 8px 0;
	white-space: nowrap;
}

/* Same look as .jrl-cat-nav__arrow (submenu scroll buttons) — kept as a distinct
   class since these live in a different DOM context (beside .jrl-cat-nav__list,
   not inside a .jrl-cat-nav__panel), toggled the same way: hidden by default,
   shown via JS (cat-nav.js) only when the list actually overflows. */
.jrl-cat-nav__list-arrow {
	flex: 0 0 auto;
	border: 0;
	background: rgba( 0, 0, 0, .05 );
	cursor: pointer;
	display: none;
}

/* Override Hello Elementor's reset.css `button:hover{background-color:#c36}` —
   this widget's hover feedback comes only from the Style tab's Hover Color control. */
.jrl-cat-nav__link:hover,
.jrl-cat-nav__link:focus {
	background-color: transparent;
}

.jrl-cat-nav__empty {
	margin: 0;
	padding: 8px 16px;
	white-space: nowrap;
	cursor: default;
	opacity: .6;
}

/* Desktop full-width hover panel — full-bleed edge-to-edge, same negative-margin/100vw
   trick as the theme's own .alignfull (assets/css/theme.css), adapted for an
   absolutely-positioned element (needs left:50%+margin-left instead of margin-inline). */
.jrl-cat-nav__panels {
	display: none;
	position: absolute;
	top: 100%;
	left: 50%;
	margin-left: -50vw;
	width: 100vw;
	max-width: 100vw;
	z-index: 20;
	background: #1c1d1f;
	box-sizing: border-box;
}

.jrl-cat-nav--panel-open > .jrl-cat-nav__panels {
	display: block;
}

.jrl-cat-nav__panel {
	display: none;
	max-width: 1140px;
	margin-inline: auto;
	padding: 24px 20px;
	text-align: center;
}

.jrl-cat-nav__panel--active {
	display: block;
}

.jrl-cat-nav__pointer {
	position: absolute;
	top: -8px;
	left: var(--jrl-cat-nav-pointer-x, 0px);
	width: 0;
	height: 0;
	border-left: 8px solid transparent;
	border-right: 8px solid transparent;
	border-bottom: 8px solid #1c1d1f;
	transform: translateX(-50%);
	pointer-events: none;
}

.jrl-cat-nav__submenu {
	display: flex;
	justify-content: center;
	list-style: none;
	margin: 0;
	padding: 4px 0;
	gap: 32px;
	overflow-x: auto;
	scroll-behavior: smooth;
	scrollbar-width: none;
}

.jrl-cat-nav__submenu::-webkit-scrollbar {
	display: none;
}

.jrl-cat-nav__subcat {
	flex: 0 0 auto;
}

.jrl-cat-nav__subcat-link {
	white-space: nowrap;
}

.jrl-cat-nav__arrow {
	flex: 0 0 auto;
	border: 0;
	background: rgba( 0, 0, 0, .05 );
	cursor: pointer;
	display: none;
}

/* Mobile-only in-flow copy of the same submenu body — nested inside its own <li> so the
   accordion can stack trigger + body vertically per category; never full-bleed, never
   position:absolute, so it needs none of the desktop panel's positioning rules. */
.jrl-cat-nav__mobile-submenu {
	display: none;
}

.jrl-cat-nav--mobile-open .jrl-cat-nav__item--open > .jrl-cat-nav__mobile-submenu {
	display: flex;
	flex-direction: column;
	/* Padding Top/Bottom (Submenu Item section) also targets this element and defaults
	   to 24px — that extra space sits only ABOVE the first row (nothing "extra" exists
	   between subsequent rows), making the first row look taller than the rest even
	   after the gap/border fix above. Zeroed here so every row's spacing comes only
	   from .jrl-cat-nav__subcat-link's own uniform padding.
	   !important is required: Elementor's own control selector for this same property
	   is `{{WRAPPER}} .jrl-cat-nav__mobile-submenu` (3 class selectors, specificity 0,3,0),
	   equal to or higher than any plain override here, so without !important the control's
	   value (default 24px) silently wins and this reset never actually applies. */
	padding-top: 0 !important;
	padding-bottom: 0 !important;
}

.jrl-cat-nav--mobile-open .jrl-cat-nav__submenu {
	flex-direction: column;
	overflow: visible;
	padding: 0;
	/* `gap` only adds space BETWEEN items, so with a border on each item the first row
	   (no preceding gap) always reads as a different height than the rest (gap + content).
	   Zeroed here — vertical rhythm between mobile rows comes from the link's own
	   top/bottom padding below instead, which is uniform for every item including the first.
	   !important is required: Elementor's "Submenu Item Spacing" control targets
	   `{{WRAPPER}} .jrl-cat-nav__submenu`, which expands to 3 class selectors
	   (specificity 0,3,0) — higher than this rule's 2 classes (0,2,0), so the control's
	   gap value (default 32px) always won here and this reset was silently never applied. */
	gap: 0 !important;
}

.jrl-cat-nav--mobile-open .jrl-cat-nav__subcat-link {
	display: block;
	/* Padding now owned by the "Item Padding" widget control (submenu_item_padding) —
	   its generated selector includes {{WRAPPER}}, which always out-specifies this plain
	   rule, so no default is set here to avoid a dead/duplicate declaration. */
}

.jrl-cat-nav--mobile-open .jrl-cat-nav__arrow {
	display: none;
}

.jrl-cat-nav__backdrop {
	display: none;
}

/* Off-canvas drawer (mobile/tablet only). `display:flex` stays on at every breakpoint
   now (list_display control) so the "hidden" state below can be a transform the browser
   can actually animate — display:none can't be transitioned. Scoped to Elementor's
   default tablet breakpoint (1024px); if the site's breakpoints are ever customized in
   Elementor Site Settings, this value should be updated to match. */
@media (max-width: 1024px) {
	.jrl-cat-nav__list {
		position: fixed;
		top: 0;
		left: 0;
		flex-direction: column;
		width: min(85vw, 320px);
		height: 100vh;
		margin: 0;
		padding: 24px 20px;
		background: #ffffff;
		box-shadow: 2px 0 16px rgba(0, 0, 0, .2);
		overflow-y: auto;
		z-index: 1000;
		transform: translateX(-100%);
		transition: transform .3s ease;
	}

	.jrl-cat-nav--mobile-open .jrl-cat-nav__list {
		transform: translateX(0);
	}

	/* The drawer scrolls vertically at this breakpoint (see .jrl-cat-nav__list above) —
	   the horizontal scroll arrows are desktop-only, JS already skips showing them here
	   via isMobileMode(), this is just a CSS safety net against a flash of the button
	   before JS runs. */
	.jrl-cat-nav__list-arrow {
		display: none !important;
	}

	/* Closed state deliberately stays untouched (follows wherever Elementor's own Container
	   layout places it). Only while the drawer is OPEN does the button move to a fixed spot
	   just past the drawer's right edge, over the dimmed backdrop — "beside" the drawer,
	   not inside its white panel. */
	.jrl-cat-nav--mobile-open .jrl-cat-nav__hamburger {
		position: fixed;
		top: 20px;
		left: calc(min(85vw, 320px) + 12px);
		z-index: 1001;
	}

	.jrl-cat-nav__backdrop {
		display: block;
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, .5);
		opacity: 0;
		pointer-events: none;
		transition: opacity .3s ease;
		z-index: 999;
	}

	.jrl-cat-nav--mobile-open .jrl-cat-nav__backdrop {
		opacity: 1;
		pointer-events: auto;
	}
}

.jrl-course-search {
	display: flex;
}

.jrl-course-search__field {
	position: relative;
	display: flex;
	align-items: stretch;
	flex: 1;
	overflow: hidden; /* clips input/button to the field's own border-radius */
}

.jrl-course-search__input {
	flex: 1;
	width: 100%;
	padding: 8px 12px;
	border: 0;
	outline: none;
	/* `type="search"` gets native OS/browser chrome (-webkit-appearance: searchfield) by
	   default — its focus ring is baked into that native rendering, not a normal CSS
	   `outline`, so `outline: none` alone can't remove it (finding 2026-07-08). Turning
	   off native appearance makes the input a plain box fully controlled by our own CSS;
	   the trade-off is Chrome/Safari's native "x" clear-icon disappears too. */
	-webkit-appearance: none;
	appearance: none;
}

.jrl-course-search__submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 8px 16px;
	border: 0;
	color: #fff;
	cursor: pointer;
	outline: none;
}

/* Browser default focus outline on the <input>/<button> gets clipped square by
   .jrl-course-search__field's overflow:hidden, breaking the pill shape (see finding
   2026-07-08). Replaced with a focus ring on the field itself, which respects the
   field's own border-radius and only shows for keyboard navigation. */
.jrl-course-search__field:focus-within {
	box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.5);
}

.jrl-course-search__submit-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}

/* Icon Position: On Button (default, or no icon at all) — button stays a separate block
   after the input, matching the original layout before icon support was added. */
.jrl-course-search--icon-button .jrl-course-search__field,
.jrl-course-search--icon-none .jrl-course-search__field {
	gap: 8px;
}

/* Icon Position: Inside Input (left/right) — the button overlays the input itself,
   icon-only. Background is NOT stripped here — Button Background (Style tab) applies
   normally, so it becomes the colored block behind the icon merged into the pill (see
   reference screenshot). Field's own overflow:hidden + border-radius clips the button's
   outer corner to match; the inner corner (against the input) stays square by design. */
.jrl-course-search--icon-input-left .jrl-course-search__submit,
.jrl-course-search--icon-input-right .jrl-course-search__submit {
	position: absolute;
	top: 0;
	bottom: 0;
	padding: 0 12px;
}

.jrl-course-search--icon-input-left .jrl-course-search__submit {
	left: 0;
}

.jrl-course-search--icon-input-right .jrl-course-search__submit {
	right: 0;
}

/* Reserved space = icon size + the overlay button's own 12px horizontal padding on each
   side (see .jrl-course-search__submit above). Was a flat 44px, which only matched the
   16px default Icon Size — any larger value made the button wider than the reserved gap
   and it started covering the input's own text (bug found 2026-07-08, screenshot with
   Icon Size ~32px). --jrl-search-icon-size is set by the Icon Size control itself.
   Left variant gets +8px extra breathing room past the icon block — typed text started
   flush against the icon otherwise (finding 2026-07-08); right variant has no such
   complaint since text there ends before reaching the icon, not up against it. */
.jrl-course-search--icon-input-left .jrl-course-search__input {
	padding-left: calc(var(--jrl-search-icon-size, 16px) + 32px);
}

.jrl-course-search--icon-input-right .jrl-course-search__input {
	padding-right: calc(var(--jrl-search-icon-size, 16px) + 24px);
}

/* Responsive column counts per breakpoint are generated by Elementor itself
   (add_responsive_control on --jrl-grid-columns) — no manual media queries needed here. */

.jrl-course-sort {
	display: flex;
	align-items: center;
	gap: 8px;
}

.jrl-course-sort__label {
	white-space: nowrap;
}

.jrl-course-sort__select {
	padding: 8px 12px;
	border: 1px solid #dcdcde;
	border-radius: 4px;
}

/* Horizontal/Dropdown layout switch — both `.jrl-course-category__nav` and
   `.jrl-course-category__dropdown` always render (Course_Category.php); which
   one is actually visible per device comes entirely from these two CSS
   custom properties, set by the widget's "Layout" control
   (`add_responsive_control`, real Desktop/Tablet/Mobile device values using
   Elementor's own breakpoints — see that control's `selectors_dictionary`).
   One Elementor control can only resolve to ONE value per device, but two
   elements need OPPOSITE display states, so the control sets both variables
   in a single declaration block instead of one control driving one element
   each — the defaults here (nav shown, dropdown hidden) match the control's
   own 'horizontal' default so the page looks right even before Elementor's
   generated CSS loads. */
.jrl-course-category__nav {
	display: var(--jrl-cat-nav-display, flex);
	flex-wrap: nowrap;
	align-items: center;
	gap: var(--jrl-cat-gap, 10px);
	overflow-x: auto;
	overflow-y: hidden;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
}

.jrl-course-category__item {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	gap: 6px;
	text-decoration: none;
	transition: background-color 0.2s, color 0.2s;
	white-space: nowrap;
}

.jrl-course-category__count {
	opacity: 0.7;
	font-size: 0.9em;
}

.jrl-course-category__dropdown {
	display: var(--jrl-cat-dropdown-display, none);
	width: 100%;
	max-width: 320px;
	padding: 8px 12px;
	border: 1px solid #dcdcde;
	border-radius: 4px;
}

/* Breadcrumb, Course Category and Course Sort are commonly placed side by
   side in one horizontal Container row (e.g. an archive page's toolbar row).
   Confirmed by reading the actual generated CSS (Elementor's own
   `.elementor-element{ align-self: var(--align-self, initial); ... }` rule
   in elementor/assets/css/frontend.min.css, and a real page's post-{id}.css):
   a row Container with no explicit "Align Items" set never emits an
   `align-items` declaration for itself at all, so each child widget's
   `align-self: auto` (Elementor's own default) falls through to the
   flexbox spec's native default cross-axis behavior — effectively stretch
   — rather than anything Elementor authored. That stretches each widget's
   own wrapper to the row's full height while the widget's actual markup
   still sits at the TOP of that stretched box (plain block flow), not
   vertically centered. Elementor's own core stylesheet is enqueued/printed
   near the very end of the document (confirmed in the actual rendered page
   HTML), i.e. AFTER this plugin's own frontend.css — so a same-specificity
   override here loses purely on cascade order, not selector specificity.
   `!important` is the fix, same lesson as the Global Colors cascade fight
   elsewhere in this plugin (see CLAUDE.md): confirmed live, by diffing the
   computed style, that a plain non-`!important` override here had zero
   effect regardless of source order. No-op when one of these widgets is
   used outside a flex/grid parent. */
.elementor-widget-jrl-breadcrumb,
.elementor-widget-jrl-course-category,
.elementor-widget-jrl-course-sort {
	align-self: center !important;
}

/* Elementor's own Container child already defaults EVERY widget to
   `flex-shrink: 1` + `min-width: 0` (elementor/assets/css/frontend.min.css:
   `.elementor-widget{min-width:0}` and `.elementor-element{flex-shrink:var(
   --flex-shrink)}`, the variable resolving to the browser's own initial `1`
   whenever a widget has no explicit per-instance flex override). That means
   ALL THREE widgets in a Breadcrumb / Course Category / Course Sort row
   shrink together when the row overflows — including Breadcrumb and Course
   Sort, whose own markup has no `overflow`/`white-space:nowrap` handling for
   being squeezed, so their text just visually overflows past their own
   shrunk box instead of wrapping or scrolling. That, not the category list's
   own width, is what actually produced the screenshot: "Courses" overlapping
   "All Categories" and Course Sort getting shoved rightward. Fix: pin
   Breadcrumb + Course Sort to their natural content width (`flex-shrink: 0`)
   and let Course Category alone absorb the row's remaining space
   (`flex: 1 1 0%`), so only ITS OWN internal `overflow-x: auto` (above) ever
   has to deal with too many categories.
   `!important` is required on every property here, not just some of them —
   same lesson as the `align-self` rule right above and the Global Colors
   cascade fight documented in CLAUDE.md: Elementor's own frontend.min.css is
   enqueued in the footer, i.e. AFTER this plugin's stylesheet, and its
   `.elementor-element{flex-basis:...;flex-grow:...;flex-shrink:...}` rule is
   the SAME specificity (one class) as the selectors below — so without
   `!important` Elementor's later same-specificity rule silently re-wins and
   the whole fix below is a visible no-op, confirmed live (the first version
   of this fix, without `!important`, produced zero visual change even after
   a hard refresh). No-op when these widgets aren't inside a flex/grid
   parent. */
.elementor-widget-jrl-breadcrumb,
.elementor-widget-jrl-course-sort {
	flex-shrink: 0 !important;
}

.elementor-widget-jrl-course-category {
	flex: 1 1 0% !important;
	min-width: 0 !important;
}

.jrl-course-category {
	min-width: 0;
	width: 100%;
}

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

.jrl-breadcrumb__link {
	text-decoration: none;
}

.jrl-breadcrumb__link:hover {
	text-decoration: underline;
}

.jrl-account-menu {
	position: relative;
	display: inline-flex;
	align-items: center;
}

.jrl-account-menu--guest {
	text-decoration: none;
}

.jrl-account-menu__trigger {
	display: inline-flex;
	align-items: center;
	background: none;
	border: 0;
	font: inherit;
	cursor: pointer;
	padding: 0;
}

/* Override Hello Elementor's reset.css `button:hover,:focus{background-color:#c36;color:#fff}` —
   same fix already applied to .jrl-cat-nav__hamburger/.jrl-cat-nav__link; this widget's
   hover feedback comes only from the Style tab's Hover Color control. */
.jrl-account-menu__trigger:hover,
.jrl-account-menu__trigger:focus {
	background-color: transparent;
}

.jrl-account-menu__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}

.jrl-account-menu__dropdown {
	display: none;
	flex-direction: column;
	position: absolute;
	top: 100%;
	right: 0;
	margin-top: 8px;
	min-width: 160px;
	z-index: 100;
	background: #ffffff;
}

.jrl-account-menu--open .jrl-account-menu__dropdown {
	display: flex;
}

.jrl-account-menu__dropdown-link {
	white-space: nowrap;
	text-decoration: none;
}

.jrl-page-link {
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

.jrl-page-link__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}

/* Site Nav Menu — same hamburger/off-canvas-drawer shape as the Udemy Style
   Nav Menu widget (.jrl-cat-nav), but for a plain wp_nav_menu() list: one
   shared <ul> reused for both the desktop row and the mobile drawer via
   CSS repositioning. Click-to-toggle dropdowns for items with children —
   see the "Dropdown" rules further down and Site_Nav_Menu's docblock. */

.jrl-site-nav {
	position: relative;
}

.jrl-site-nav__hamburger {
	position: relative;
	background: transparent;
	border: 0;
	cursor: pointer;
	padding: 8px;
	z-index: 1001;
}

.jrl-site-nav__hamburger:hover,
.jrl-site-nav__hamburger:focus {
	background-color: transparent;
	color: inherit;
}

.jrl-site-nav__hamburger-icon {
	display: block;
	width: 20px;
	height: 2px;
	background: currentColor;
	box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor;
}

.jrl-site-nav__close-icon {
	display: none;
	font-size: 26px;
	line-height: 1;
}

.jrl-site-nav--mobile-open .jrl-site-nav__hamburger-icon {
	display: none;
}

.jrl-site-nav--mobile-open .jrl-site-nav__close-icon {
	display: block;
}

.jrl-site-nav__list {
	list-style: none;
	margin: 0;
	padding: 0;
	align-items: center;
}

.jrl-site-nav__list .menu-item {
	position: relative;
}

.jrl-site-nav__list .menu-item a {
	display: inline-block;
	text-decoration: none;
}

/* Dropdown (sub-menu) support — wp_nav_menu()'s default walker already marks
   parent items `.menu-item-has-children` and nests children in their own
   `<ul class="sub-menu">` at any depth; assets/js/site-nav.js toggles
   `.jrl-site-nav__item--open` on click. Chevron is a plain CSS-drawn
   triangle (no icon font dependency), rotates on open. */
.jrl-site-nav__list .menu-item-has-children > a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.jrl-site-nav__list .menu-item-has-children > a::after {
	content: '';
	width: 7px;
	height: 7px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	margin-top: -4px;
	flex: 0 0 auto;
	transition: transform 200ms ease;
}

.jrl-site-nav__item--open > a::after {
	transform: rotate(-135deg);
	margin-top: 3px;
}

/* Top-level dropdown panel — floats below the trigger. */
.jrl-site-nav__list > .menu-item > .sub-menu {
	list-style: none;
	margin: 0;
	padding: 8px 0;
	display: none;
	position: absolute;
	top: 100%;
	left: 0;
	min-width: 200px;
	background: #ffffff;
	box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
	z-index: 100;
}

.jrl-site-nav__list > .menu-item.jrl-site-nav__item--open > .sub-menu {
	display: block;
}

.jrl-site-nav__list .sub-menu li {
	position: relative;
}

.jrl-site-nav__list .sub-menu a {
	display: block;
	padding: 8px 20px;
	white-space: nowrap;
}

/* A sub-menu nested inside another sub-menu ("Deep Dropdown") renders as an
   inline, indented accordion row within the already-open panel instead of a
   flyout — simpler to use on both desktop and the mobile drawer alike. */
.jrl-site-nav__list .sub-menu .sub-menu {
	position: static;
	display: none;
	box-shadow: none;
	padding: 0;
	background: transparent;
}

.jrl-site-nav__list .sub-menu li.jrl-site-nav__item--open > .sub-menu {
	display: block;
}

.jrl-site-nav__list .sub-menu .sub-menu a {
	padding-left: 36px;
	white-space: normal;
}

/* Account Item (optional leading menu entry, see Site_Nav_Menu::render_account_item()).
   `display:none` by default here as a pre-JS/CSS-not-yet-loaded safety net — the
   authoritative show/hide per breakpoint is account_item_display (Elementor responsive
   control, {{WRAPPER}}-scoped so it always wins on specificity). Rendered first in the
   list (not last), with its own bottom padding/border so it reads as a separate block
   above the regular menu items — border color/width themselves are the
   account_item_divider_* controls; this is only the space the border needs to not sit
   flush against the avatar/text above it. */
.jrl-site-nav__account-item {
	display: none;
	padding-bottom: 16px;
	margin-bottom: 4px;
	width: 100%;
}

/* Avatar+name gap/alignment already comes free from the existing
   `.jrl-site-nav__list .menu-item-has-children > a` rule above (this item reuses that
   class so the dropdown-toggle JS picks it up) — only the avatar image itself needs a
   size/shape rule. */
.jrl-site-nav__avatar {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	flex: 0 0 auto;
}

.jrl-site-nav__backdrop {
	display: none;
}

/* Off-canvas drawer (mobile/tablet only), slides in from the left.
   Scoped to Elementor's default tablet breakpoint (1024px); if the site's
   breakpoints are ever customized in Elementor Site Settings, this value
   should be updated to match — same convention as the Udemy Style Nav
   Menu widget's own off-canvas drawer. */
@media (max-width: 1024px) {
	.jrl-site-nav__list {
		position: fixed;
		top: 0;
		left: 0;
		flex-direction: column;
		align-items: flex-start;
		width: min(85vw, 320px);
		height: 100vh;
		margin: 0;
		padding: 24px 20px;
		background: #ffffff;
		box-shadow: 2px 0 16px rgba(0, 0, 0, .2);
		overflow-y: auto;
		z-index: 1000;
		transform: translateX(-100%);
		transition: transform .3s ease;
	}

	.jrl-site-nav--mobile-open .jrl-site-nav__list {
		transform: translateX(0);
	}

	/* Closed state deliberately stays untouched (follows wherever Elementor's own
	   Container layout places it). Only while the drawer is OPEN does the button
	   move to a fixed spot just past the drawer's right edge, over the dimmed
	   backdrop — "beside" the drawer, not inside its white panel. Same convention
	   as the Udemy Style Nav Menu widget's own hamburger/close button. */
	.jrl-site-nav--mobile-open .jrl-site-nav__hamburger {
		position: fixed;
		top: 20px;
		left: calc(min(85vw, 320px) + 12px);
		z-index: 1001;
	}

	/* Inside the narrow drawer, even the top-level dropdown becomes an
	   inline/indented accordion row instead of a floating panel — the
	   absolute-positioned desktop version would overflow a 320px-wide drawer. */
	.jrl-site-nav__list > .menu-item > .sub-menu {
		position: static;
		display: none;
		box-shadow: none;
		padding: 0;
		width: 100%;
		min-width: 0;
	}

	.jrl-site-nav__list > .menu-item.jrl-site-nav__item--open > .sub-menu {
		display: block;
	}

	.jrl-site-nav__list .sub-menu a {
		white-space: normal;
	}

	.jrl-site-nav__backdrop {
		display: block;
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, .5);
		opacity: 0;
		pointer-events: none;
		transition: opacity .3s ease;
		z-index: 999;
	}

	.jrl-site-nav--mobile-open .jrl-site-nav__backdrop {
		opacity: 1;
		pointer-events: auto;
	}
}

/* Cart */

.jrl-cart {
	position: relative;
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

.jrl-cart__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}

.jrl-cart__badge {
	position: absolute;
	top: -6px;
	right: -8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	line-height: 1;
	font-weight: 600;
	padding: 0 3px;
}

.jrl-cart__badge--zero {
	display: none;
}

/* Toggle Trigger — generic click-to-reveal, content-agnostic (see
   Toggle_Trigger widget docblock). `.jrl-toggle-panel` is a reserved class
   an admin attaches to ANY element (via Elementor's native Advanced > CSS
   Classes) to make it a togglable target. */

.jrl-toggle-trigger {
	background: none;
	border: 0;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px;
}

.jrl-toggle-trigger:hover,
.jrl-toggle-trigger:focus {
	background-color: transparent;
}

.jrl-toggle-trigger:focus {
	outline: none;
}

.jrl-toggle-trigger:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

.jrl-toggle-trigger__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}

/* !important: Elementor's own frontend.min.css ships an unconditional
   `.e-con`/`.e-flex` base rule (display:flex) that loads AFTER this
   stylesheet with equal-or-higher specificity, so a bare `display:none`
   here silently loses when the target is an Elementor Container — see
   feedback_elementor_econ_cascade memory. Only force the closed state;
   the open state deliberately falls back to the target's own natural
   display (flex for a Container, block for most other elements) instead
   of hardcoding `block`, so a Container's internal flex layout isn't
   broken when revealed. `:not(.jrl-toggle-panel--editing)` is the same
   "suspend the closed state inside Elementor's own editor" escape hatch
   `jrl-hero-slideshow--editing` uses below — toggle-trigger.js adds that
   class while `elementorFrontend.isEditMode()` is true so an admin can see
   and select a panel's contents on canvas without having to click the
   Toggle Trigger first; see that file's docblock. */
.jrl-toggle-panel:not(.jrl-toggle-open):not(.jrl-toggle-panel--editing) {
	display: none !important;
}

/* Opt-in overlay mode for `.jrl-toggle-panel` — add BOTH `jrl-toggle-panel`
   AND this modifier class (Elementor's native Advanced > CSS Classes field,
   space-separated) to make an OPEN panel float above whatever comes after
   it on the page instead of pushing that content down, which is what plain
   `jrl-toggle-panel` alone does (its open state deliberately falls back to
   the target's own natural `display`, still fully in normal flow — see the
   comment above). A search bar revealed under a header's nav row is the
   motivating case: without this, opening it pushes the page's actual
   content (e.g. a breadcrumb bar) further down every time it's toggled.
   `top: 100%` anchors it to the BOTTOM edge of its own parent element, so
   this reads correctly when the panel is its parent's last child sitting
   directly below whatever it should visually overlay (true for the search
   bar case: an Elementor Container's own `.e-con` base rule already
   defaults to `position: relative` — see elementor/assets/css/frontend.css
   — so the panel's parent already qualifies as a positioning context with
   no extra setup needed when that parent is a normal Container, which
   covers the common case; toggle-trigger.js's `open()` also sets
   `position: relative` on the parent as a defensive fallback for any other
   kind of parent element that isn't). !important throughout for the same
   `.e-con` cascade-fight reason as the closed-state rule above — this
   panel is itself almost always another Container, so it inherits `.e-con`'s
   own `position`/`z-index` declarations unless every property here beats
   them explicitly. */
.jrl-toggle-panel--overlay.jrl-toggle-open {
	position: absolute !important;
	top: 100% !important;
	left: 0 !important;
	right: 0 !important;
	z-index: 999 !important;
}

/* Reserved hook class — an admin attaches this to any row-level Container
   (e.g. a header's main nav row) via Elementor's native Advanced > CSS
   Classes field to make that whole row stick to the top of the viewport on
   scroll.
   JS-driven, not native CSS `position: sticky` — see assets/js/sticky-bar.js
   for why (native sticky was confirmed, via live DevTools testing, to not
   engage at all on this site's actual theme/plugin stack despite every
   static diagnostic — computed style, ancestor position/overflow/transform,
   cascade specificity — coming back clean; the exact cause was never
   isolated). `.jrl-sticky-bar` itself carries no positioning; the JS toggles
   `.jrl-sticky-bar--fixed` once the element's natural position would
   scroll above the viewport, and inserts `.jrl-sticky-bar__placeholder`
   right before it to reserve its normal-flow space so content doesn't jump
   when it switches to `position: fixed`. */
.jrl-sticky-bar--fixed {
	position: fixed !important;
	top: 0 !important;
	left: 0 !important;
	width: 100% !important;
	/* !important on every property here, not just position/top — same
	   Elementor `.e-con{...}` base-rule cascade fight documented above:
	   z-index (and left/width) are single-class-selector rules there too,
	   loaded after this stylesheet, so leaving any one of them un-important
	   lets Elementor's default silently win it back. Caught this one only
	   after it shipped (content stacking above the "stuck" header instead
	   of the header staying on top) — the earlier position/top fix wasn't
	   actually the full pattern to copy from itself. */
	z-index: 999 !important;
}

.jrl-sticky-bar__placeholder {
	display: none;
}

.jrl-sticky-bar__placeholder--active {
	display: block;
}

/* Opt-in modifier alongside `jrl-sticky-bar` (Container_Sticky_Controls'
   "Shrink Logo on Scroll" switch) — shrinks a Site Logo widget
   (Widgets/Site_Logo.php's `.jrl-site-logo`/`.jrl-site-logo-text` markup)
   nested anywhere inside this Container once it's actually fixed. Ratio
   (~2/3) and transition length (200ms) copied directly from the "Unicat"
   reference template's own `.header.scrolled .logo`/`.logo_text` rules
   (see reference_unicat_source memory) — not independently chosen. The
   transition lives on the base (non-`--fixed`) rule so it animates
   smoothly in both directions; `transform-origin: left center` assumes
   the common left-aligned header logo placement, same assumption the
   Unicat reference itself makes. `transform: scale()` is used instead of
   shrinking `width`/`font-size` directly so this works unconditionally
   regardless of whatever px/% the widget's own Max Width control (or a
   custom logo's native size) already resolved to. */
.jrl-sticky-bar--shrink-logo .jrl-site-logo img,
.jrl-sticky-bar--shrink-logo .jrl-site-logo-text {
	transition: transform 200ms ease;
	transform-origin: left center;
}

.jrl-sticky-bar--fixed.jrl-sticky-bar--shrink-logo .jrl-site-logo img,
.jrl-sticky-bar--fixed.jrl-sticky-bar--shrink-logo .jrl-site-logo-text {
	transform: scale(0.667);
}

/* Reserved hook: an admin turns "Enable Hero Slideshow" on (Advanced tab)
   for any native Elementor Container — `Container_Hero_Controls` — to get
   a full-screen rotating slideshow behind whatever the admin builds inside
   it. Each slide is itself a plain native Elementor Container, a direct
   child tagged `jrl-hero-slide` (Advanced > CSS Classes) — its background
   image/color/overlay use Elementor's OWN native Background + Background
   Overlay controls (already built into every Container), and its own
   widgets (Heading, Button…) are dropped inside it as usual. There is no
   separate custom "Slides" data list any more (an earlier iteration tried
   that — a repeater of Background Image + Overlay Color kept as a second,
   separately-ordered list from the actual `jrl-hero-slide` content
   Containers — and it was confusing to keep the two in sync; see
   progress.md 2026-09-01). One Container now *is* one full slide: number
   of `jrl-hero-slide` children = number of slides, their DOM order = slide
   order. PHP (`Container_Hero_Controls`) only attaches this class +
   data-jrl-hero-* attributes for the rotation mechanics (transition,
   autoplay/speed, arrows/dots) to the outer wrapper — no slide data.
   assets/js/hero-slideshow.js reads the real `jrl-hero-slide` children
   directly and drives the rotation.
   position/overflow/height/min-height all need !important — Elementor's
   own unconditional `.e-con{...}` base rule (frontend.min.css, loaded
   after this stylesheet) sets each of those via var() at the same
   class-selector specificity and silently wins ties otherwise (see
   feedback_elementor_econ_cascade memory / the jrl-sticky-bar z-index
   lesson above — audit every competing property, not just the ones a
   prior fix happened to need).
   `height`/`min-height: 100vh` here are only the no-JS fallback — a flat
   100vh would make hero + header taller than the actual screen whenever
   anything (a header template, the WP admin bar) sits above the hero.
   `HeroSlideshow.prototype.applyHeight()` in hero-slideshow.js measures
   how much that is and overrides both properties inline with
   `calc(100vh - <measured>px)`, `!important` (via `style.setProperty(...,
   'important')`, needed to beat this stylesheet's own !important) as soon
   as it runs. */
.jrl-hero-slideshow {
	position: relative !important;
	overflow: hidden !important;
	height: 100vh !important;
	min-height: 100vh !important;
}

/* Each slide Container is stacked full-bleed on top of the others —
   `width`/`height` need !important for the same `.e-con` var()-cascade
   reason as `.jrl-hero-slideshow` above (a Container's own native
   Background/Background Overlay paint within this same box, so nothing
   extra is needed for those; the Container's own real widget children
   already render on top of its own background by normal CSS box
   painting order — no separate z-index rule required for them).
   Scoped under `.jrl-hero-slideshow` (not a bare `.jrl-hero-slide`
   selector) deliberately: `jrl-hero-slideshow` only ever gets attached by
   PHP (`Container_Hero_Controls::apply_attributes()`), and Elementor's
   Container editing canvas is 100% client-side JS — it never calls PHP
   mid-edit (confirmed via `assets/js/editor.js`: a Container's
   `getTemplateType()` always returns `'js'`, never `'remote'`, so
   `elementor/frontend/container/before_render` never fires until an
   actual reload/Update). Typing the `jrl-hero-slide` class into a
   Container's CSS Classes field, by contrast, DOES apply immediately —
   it's a native Elementor field, not gated on our PHP. Scoping this rule
   under the ancestor class means a `jrl-hero-slide` Container tagged
   before its ancestor's "Enable Hero Slideshow" has actually been saved
   stays in Elementor's own normal visible/editable state instead of
   disappearing — the slideshow positioning/hiding only takes over once
   `jrl-hero-slideshow` is genuinely present (a real render pass). */
.jrl-hero-slideshow .jrl-hero-slide {
	position: absolute !important;
	inset: 0;
	width: 100% !important;
	height: 100% !important;
	z-index: 0;
	opacity: 0;
	visibility: hidden;
}

.jrl-hero-slideshow .jrl-hero-slide--active {
	z-index: 1;
}

.jrl-hero-slideshow--fade .jrl-hero-slide {
	transition: opacity 0.6s ease;
}

.jrl-hero-slideshow--fade .jrl-hero-slide--active {
	opacity: 1;
	visibility: visible;
}

/* Slide transition — direction is always "new slide enters from the right,
   outgoing slide exits to the left" regardless of Prev/Next; a fully
   direction-aware slide (tracking last navigation direction) was left out
   as unnecessary complexity for a hero background. */
.jrl-hero-slideshow--slide .jrl-hero-slide {
	opacity: 1;
	visibility: visible;
	transition: transform 0.6s ease;
	transform: translateX(100%);
}

.jrl-hero-slideshow--slide .jrl-hero-slide--active {
	transform: translateX(0);
}

.jrl-hero-slideshow--slide .jrl-hero-slide--prev {
	transform: translateX(-100%);
}

/* Editor-only override — added by hero-slideshow.js via
   `elementorFrontend.isEditMode()` (Elementor's own standard client-side
   way for a widget/Container enhancement to detect it's running inside the
   editor's preview iframe, not the live frontend). Outside the editor,
   only the active slide is visible (rules above) — correct for the
   rotating frontend, but it makes every other slide's Container invisible
   and therefore unselectable/unclickable on canvas while editing. Here,
   every `jrl-hero-slide` stacks fully visible in normal flow instead, so
   an admin can click into and edit any of them directly. `height: auto` on
   the outer Container (not the usual 100vh) is what lets that stack
   actually show instead of being clipped by `overflow: hidden` above —
   `HeroSlideshow.prototype.applyHeight()` also skips its own inline
   `calc(100vh - …)` `!important` override while editing, since an inline
   style would otherwise beat this rule regardless of `!important` here. */
.jrl-hero-slideshow--editing {
	height: auto !important;
	min-height: 100vh !important;
	overflow: visible !important;
}

.jrl-hero-slideshow--editing .jrl-hero-slide {
	position: static !important;
	width: 100% !important;
	height: auto !important;
	min-height: 40vh !important;
	opacity: 1 !important;
	visibility: visible !important;
	transform: none !important;
	transition: none !important;
}

.jrl-hero-slideshow__arrow {
	position: absolute;
	top: 50%;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	transform: translateY(-50%);
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.85);
	color: #1f2937;
	font-size: 24px;
	line-height: 1;
	cursor: pointer;
}

.jrl-hero-slideshow__arrow:hover,
.jrl-hero-slideshow__arrow:focus {
	background: #ffffff;
}

.jrl-hero-slideshow__arrow--prev {
	left: 24px;
}

.jrl-hero-slideshow__arrow--next {
	right: 24px;
}

.jrl-hero-slideshow__dots {
	position: absolute;
	left: 50%;
	bottom: 24px;
	z-index: 2;
	display: flex;
	gap: 10px;
	transform: translateX(-50%);
}

.jrl-hero-slideshow__dot {
	width: 10px;
	height: 10px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.5);
	cursor: pointer;
}

.jrl-hero-slideshow__dot--active {
	background: #ffffff;
}

/* Course Reviews — quote-bubble review cards. Responsive column count is
 * generated by Elementor itself (see the comment near .jrl-course-sort
 * above) via --jrl-review-columns, written on the outer .jrl-review-grid and
 * consumed one level down by .jrl-review-grid__list so the "Load More"
 * button can sit as a non-grid sibling of the card list.
 */
.jrl-review-grid {
	--jrl-review-columns: 3;
	--jrl-review-gap: 32px;
}

.jrl-review-grid__list {
	display: grid;
	grid-template-columns: repeat(var(--jrl-review-columns), 1fr);
	gap: var(--jrl-review-gap);
}

.jrl-review-grid__empty {
	margin: 0;
}

.jrl-review-grid__load-more-wrap {
	margin-top: 32px;
	text-align: center;
}

.jrl-review-grid__load-more {
	display: inline-block;
	padding: 12px 32px;
	border: 0;
	border-radius: 4px;
	background-color: #222222;
	color: #ffffff;
	font-size: 0.95em;
	cursor: pointer;
}

.jrl-review-grid__load-more:hover,
.jrl-review-grid__load-more:focus {
	opacity: 0.85;
}

.jrl-review-grid__load-more:disabled {
	cursor: default;
	opacity: 0.6;
}

.jrl-review-card {
	display: flex;
	flex-direction: column;
	gap: 32px;
}

/* The bubble owns the card's only background color — the footer below stays
 * transparent so it blends into whatever section/page background sits
 * behind the widget, per the reference design. --jrl-review-bubble-bg is set
 * here (defaulted below, overridden by the widget's own Style tab control)
 * and re-read by .jrl-review-card__tail so the tail always matches the
 * bubble's current color without a second color control. A box-shadow (not
 * just the background color) is what keeps the bubble visually distinct even
 * when its background happens to be close in tone to the page/section
 * background behind the widget.
 */
.jrl-review-card__bubble {
	--jrl-review-bubble-bg: #ffffff;
	position: relative;
	background-color: var(--jrl-review-bubble-bg);
	border-radius: 16px;
	padding: 40px 32px 28px;
	box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
}

/* Decorative curly quote marks in the bubble's top-left/bottom-right
 * corners. Positioned (not static), so — per normal stacking-context paint
 * order — they'd otherwise paint OVER the stars/text below them despite
 * coming first in the DOM; .jrl-review-card__stars/__text get their own
 * `position: relative` + higher z-index below specifically to sit above
 * these instead.
 */
.jrl-review-card__quote {
	position: absolute;
	z-index: 0;
	font-family: Georgia, 'Times New Roman', serif;
	font-size: 4em;
	line-height: 1;
	color: rgba(0, 0, 0, 0.1);
	pointer-events: none;
	user-select: none;
}

.jrl-review-card__quote--open {
	top: 4px;
	left: 20px;
}

.jrl-review-card__quote--close {
	bottom: -18px;
	right: 20px;
}

.jrl-review-card__stars {
	position: relative;
	z-index: 1;
	display: flex;
	gap: 2px;
	margin-bottom: 14px;
}

.jrl-review-card__star {
	font-size: 1.1em;
	line-height: 1;
}

.jrl-review-card__star--filled {
	color: #f5b301;
}

.jrl-review-card__star--empty {
	color: #d8d8d8;
}

.jrl-review-card__text {
	position: relative;
	z-index: 1;
	margin: 0;
	font-size: 1.05em;
	font-style: italic;
	line-height: 1.6;
}

.jrl-review-card__tail {
	position: absolute;
	left: 40px;
	bottom: -18px;
	width: 0;
	height: 0;
	border-style: solid;
	border-width: 18px 18px 0 0;
	border-color: var(--jrl-review-bubble-bg) transparent transparent transparent;
	filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.06));
}

.jrl-review-card__footer {
	display: flex;
	align-items: center;
	gap: 14px;
	background: transparent;
}

.jrl-review-card__avatar {
	--jrl-review-avatar-size: 56px;
	--jrl-review-avatar-bg: #4a5cf5;
	flex: 0 0 auto;
	width: var(--jrl-review-avatar-size);
	height: var(--jrl-review-avatar-size);
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	overflow: hidden;
	background-color: var(--jrl-review-avatar-bg);
}

.jrl-review-card__avatar img {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

.jrl-review-card__avatar-initials {
	font-weight: 600;
	color: #ffffff;
	text-transform: uppercase;
}

.jrl-review-card__meta {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.jrl-review-card__name {
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.02em;
}

.jrl-review-card__course {
	font-size: 0.9em;
	opacity: 0.75;
}

/* Instructor Carousel — card layout/style ported from the "Unicat" static
 * HTML reference's `.team_item` (source at
 * ~/Documents/Project/Wordpress/Convert HTML to WP/unicat-master,
 * styles/main_styles.css `.team_*`/`.social_list`), same reference the Site
 * Nav Menu widget's own defaults (#384158 text, #14bdee hover) come from.
 * The reference itself is a plain grid; the sliding behavior here is new.
 *
 * Paging (see assets/js/instructor-carousel.js for the full explanation):
 * --jrl-instructor-slide-count is written inline by PHP (actual instructor
 * count), --jrl-instructor-items is the responsive "per view" Elementor
 * control (same technique as .jrl-course-grid's --jrl-grid-columns) — both
 * combine via calc() so every slide's on-screen width is always exactly
 * 1/items-per-view of the viewport, without any per-slide JS-set widths.
 */
.jrl-instructor-carousel {
	--jrl-instructor-items: 4;
	--jrl-instructor-gap: 24px;
	position: relative;
}

.jrl-instructor-carousel__empty {
	margin: 0;
}

.jrl-instructor-carousel__viewport {
	overflow: hidden;
}

.jrl-instructor-carousel__track {
	display: flex;
	width: calc(var(--jrl-instructor-slide-count, 1) * 100% / var(--jrl-instructor-items));
	transition: transform 400ms ease;
}

.jrl-instructor-carousel__slide {
	flex: 0 0 calc(100% / var(--jrl-instructor-slide-count, 1));
	box-sizing: border-box;
	padding: 6px calc(var(--jrl-instructor-gap) / 2) 0;
}

.jrl-instructor-card {
	width: 100%;
}

.jrl-instructor-card__image {
	--jrl-instructor-image-w: 180px;
	--jrl-instructor-image-h: 160px;
	position: relative;
	z-index: 2;
	width: var(--jrl-instructor-image-w);
	height: var(--jrl-instructor-image-h);
	margin: 0 auto -86px;
	border-radius: 6px;
	overflow: hidden;
}

.jrl-instructor-card__image img {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

.jrl-instructor-card__body {
	background-color: #ffffff;
	border-radius: 6px;
	box-shadow: 0 1px 10px rgba(29, 34, 47, 0.1);
	text-align: center;
	padding: 108px 20px 24px;
	transition: box-shadow 200ms ease;
}

.jrl-instructor-card:hover .jrl-instructor-card__body {
	box-shadow: 0 5px 40px rgba(29, 34, 47, 0.15);
}

.jrl-instructor-card__name {
	margin: 0;
	font-family: 'Roboto Slab', serif;
	font-size: 20px;
	font-weight: 700;
}

.jrl-instructor-card__name a {
	color: #384158;
	text-decoration: none;
	transition: color 200ms ease;
}

.jrl-instructor-card__name a:hover {
	color: #14bdee;
}

.jrl-instructor-card__subtitle {
	margin-top: 6px;
	font-size: 14px;
	color: #76777a;
}

.jrl-instructor-card__socials {
	display: flex;
	justify-content: center;
	gap: 10px;
	margin: 16px 0 0;
	padding: 0;
	list-style: none;
}

.jrl-instructor-card__social-link {
	display: inline-flex;
	color: #76777a;
	transition: color 200ms ease;
}

.jrl-instructor-card__social-link:hover {
	color: #14bdee;
}

.jrl-instructor-card__social-link svg {
	width: 18px;
	height: 18px;
	fill: currentColor;
}

.jrl-instructor-carousel__arrow {
	position: absolute;
	top: 40%;
	transform: translateY(-50%);
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border: 0;
	border-radius: 50%;
	background: #ffffff;
	box-shadow: 0 1px 10px rgba(29, 34, 47, 0.15);
	color: #384158;
	cursor: pointer;
}

.jrl-instructor-carousel__arrow[hidden] {
	display: none;
}

.jrl-instructor-carousel__arrow--prev {
	left: -20px;
}

.jrl-instructor-carousel__arrow--next {
	right: -20px;
}

.jrl-instructor-carousel__dots {
	display: flex;
	justify-content: center;
	gap: 8px;
	margin-top: 24px;
}

.jrl-instructor-carousel__dots[hidden] {
	display: none;
}

.jrl-instructor-carousel__dot {
	width: 10px;
	height: 10px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: #d8d8d8;
	cursor: pointer;
}

.jrl-instructor-carousel__dot--active {
	background: #14bdee;
}
