/* Menu Sync default styles — override these in your theme or LayerSlider
   layer's custom CSS to match each board's design, or (recommended) create
   a Style Preset under Menu Sync > Style Presets and add style="your-slug"
   to the shortcode. Presets work by setting the --msc-* custom properties
   below on a .msc-style-{slug} wrapper; every value here has a var() with
   a sane fallback, so shortcodes with no style="" attribute are completely
   unaffected. */

.msc-menu-item,
.msc-menu-table,
.msc-menu-stacked {
	font-family: var(--msc-font-family, inherit) !important;
}

/* Board Frame (canvas): the outer element. Think of this as the "body
 * background" of wherever a board renders — the full-bleed layer every
 * other layer sits on top of. On the real standalone /msc-board/{slug}/
 * page this same background is *also* painted directly on <html>/<body>
 * (see class-msd-frame.php's inline <style> block), since the "screen"
 * there IS the actual browser viewport; the rule below is what makes the
 * Frame group visible everywhere else a preset is used too — the Style
 * Preset editor's own live preview, the Saved Board editor's preview, and
 * a board rendered inline via [menu_board]/[menu_board_saved] in a post
 * or page, none of which have a separate "viewport" to hang html/body
 * rules off. It's inert (fully transparent) for presets that don't set
 * any frame vars, and harmless to repeat on the standalone page too.
 *
 * Deliberately just its OWN background/filter/animation and nothing
 * about size or position: this element fills its container at its
 * normal block width, and paints strictly *underneath* the Wrapper card
 * below simply by being its ancestor in normal flow — no z-index or
 * pseudo-element layering trick needed, which is what previously let a
 * Frame color visually clobber the Wrapper color whenever both were set
 * on the same element. */
[class^="msc-style-"] {
	display: block;
	position: relative;
	background-color: var(--msc-frame-bg, transparent);
	background-image: var(--msc-frame-bg-gradient, none), var(--msc-frame-bg-effect, none);
	filter: var(--msc-frame-filter, none);
	animation: var(--msc-frame-animation, none);
}
/* Wrapper (card): the actual board box — background, sizing, border,
 * shadow, etc. A separate element from the Frame above, nested one level
 * in, so the two never compete for the same background paint. */
.msc-style-wrap {
	position: relative;
	z-index: 0; /* contains the bg-effect/animation "bg" scope's ::before layer below */
	background-color: var(--msc-wrap-bg, transparent) !important;
	width: var(--msc-wrap-width, auto) !important;
	max-width: var(--msc-wrap-max-width, none) !important;
	padding: var(--msc-wrap-padding, 0) !important;
	border-radius: var(--msc-wrap-radius, 0) !important;
	border: var(--msc-wrap-border, none) !important;
	outline: var(--msc-wrap-outline, none) !important;
	outline-offset: var(--msc-wrap-outline-offset, 0) !important;
	box-shadow: var(--msc-wrap-shadow, none) !important;
	filter: var(--msc-wrap-filter, none) !important;
}
.msc-style-content {
	position: relative;
	z-index: 1;
}
/* Scope routing for the wrapper's background effect + animation — default
   (no data-attr, or explicit "whole") matches pre-scope behavior exactly:
   both apply straight to the wrapper box. */
.msc-style-wrap:not([data-bgfx-scope]),
.msc-style-wrap[data-bgfx-scope="whole"] {
	background-image: var(--msc-wrap-bg-effect, none) !important;
}
.msc-style-wrap:not([data-anim-scope]),
.msc-style-wrap[data-anim-scope="whole"] {
	animation: var(--msc-wrap-animation, none) !important;
}
.msc-style-wrap[data-bgfx-scope="bg"]::before,
.msc-style-wrap[data-anim-scope="bg"]::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
}
.msc-style-wrap[data-bgfx-scope="bg"]::before {
	background-image: var(--msc-wrap-bg-effect, none) !important;
}
.msc-style-wrap[data-anim-scope="bg"]::before {
	animation: var(--msc-wrap-animation, none) !important;
}
.msc-style-wrap[data-anim-scope="text"] .msc-style-content {
	animation: var(--msc-wrap-animation, none) !important;
}

.msc-menu-table {
	width: 100% !important;
	border-collapse: collapse;
	font-size: 18px;
	color: inherit;
}
.msc-menu-table th,
.msc-menu-table td {
	padding: var(--msc-row-padding, 6px 10px) !important;
	text-align: right;
	color: inherit;
	background: var(--msc-row-bg, transparent) !important;
	border: var(--msc-row-border, none) !important;
	line-height: var(--msc-item-lh, var(--msc-board-lh, var(--msc-row-line-height, normal)));
}
.msc-menu-table tbody tr:nth-child(even) th,
.msc-menu-table tbody tr:nth-child(even) td {
	background: var(--msc-row-bg-alt, var(--msc-row-bg, transparent)) !important;
}
.msc-menu-table tbody tr:nth-child(odd) {
	filter: var(--msc-row-filter, none) !important;
}
.msc-menu-table tbody tr:nth-child(even) {
	filter: var(--msc-row-filter-alt, var(--msc-row-filter, none)) !important;
}
.msc-menu-table__name-col,
.msc-menu-table__name {
	text-align: var(--msc-name-align, left) !important;
	width: var(--msc-name-col-width, auto) !important;
}
.msc-menu-table td[data-col],
.msc-menu-table th[data-col] {
	min-width: var(--msc-price-col-min-width, 0) !important;
	max-width: var(--msc-price-col-max-width, none) !important;
}
.msc-menu-table__name {
	color: var(--msc-name-color, inherit) !important;
	font-size: var(--msc-name-size, inherit) !important;
	font-weight: var(--msc-name-weight, inherit) !important;
	text-shadow: var(--msc-name-text-shadow, none) !important;
}
.msc-menu-table thead th {
	background: var(--msc-header-bg, transparent) !important;
}
/* The "Size" attribute-label header cell — same concept (and same Style
   Presets section: "Attribute label") as the inline label shown before a
   stacked multi-variation price line, just rendered as a table header here
   instead. Falls back to the old uniform --msc-header-color when the
   Attribute label section hasn't been touched, so existing presets look
   unchanged. */
.msc-menu-table__name-col {
	color: var(--msc-attr-label-color, var(--msc-header-color, inherit)) !important;
	font-size: var(--msc-attr-label-size, inherit) !important;
	font-weight: var(--msc-attr-label-weight, inherit) !important;
	font-style: var(--msc-attr-label-style, normal) !important;
	text-transform: var(--msc-attr-label-transform, none) !important;
	-webkit-text-stroke: var(--msc-attr-label-stroke-width, 0) var(--msc-attr-label-stroke-color, transparent) !important;
}
/* The "Small" / "Large" value header cells — same concept (and same
   section: Price -> Value color/weight/size) as a variation's value text
   in stacked mode. Also falls back to --msc-header-color so an existing
   preset that only set the old Header section keeps looking the same. */
.msc-menu-table thead th[data-col] {
	color: var(--msc-price-value-color, var(--msc-header-color, inherit)) !important;
	font-size: var(--msc-price-value-size, inherit) !important;
	font-weight: var(--msc-price-value-weight, inherit) !important;
}
.msc-menu-table__desc {
	display: block;
	font-size: var(--msc-desc-size, 13px) !important;
	color: var(--msc-desc-color, inherit) !important;
	opacity: var(--msc-desc-opacity, 0.65) !important;
	font-weight: normal;
}
.msc-menu-table tbody tr td[data-col] {
	color: var(--msc-price-color, inherit) !important;
	font-size: var(--msc-price-size, inherit) !important;
	font-weight: var(--msc-price-weight, inherit) !important;
	background: var(--msc-price-bg, var(--msc-row-bg, transparent)) !important;
	text-shadow: var(--msc-price-text-shadow, none) !important;
	border-radius: var(--msc-price-radius, 0) !important;
	padding: var(--msc-price-padding, inherit) !important;
}

.msc-menu-stacked {
	width: 100% !important;
	/* Rows -> "Space between rows": one consistent knob for the vertical
	   breathing room between stacked items (tables get theirs from Row
	   padding, since table rows can't use flex gap). */
	display: flex;
	flex-direction: column;
	row-gap: var(--msc-row-gap, 0);
}
.msc-menu-stacked__row {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 4px 16px;
	padding: var(--msc-row-padding, 4px 0) !important;
	font-size: 18px;
	/* line height precedence: item :lh= > board Line height > Style
	   Preset Rows value. Separate vars because the preset defines its var
	   on the card wrapper INSIDE the item wrapper — same-var nearest-wins
	   resolution made the preset unbeatable (the "still not working" bug). */
	line-height: var(--msc-item-lh, var(--msc-board-lh, var(--msc-row-line-height, normal)));
	color: inherit;
	background: var(--msc-row-bg, transparent) !important;
	border: var(--msc-row-border, none) !important;
	filter: var(--msc-row-filter, none) !important;
}
.msc-menu-stacked__row:nth-child(even) {
	background: var(--msc-row-bg-alt, var(--msc-row-bg, transparent)) !important;
	filter: var(--msc-row-filter-alt, var(--msc-row-filter, none)) !important;
}
.msc-menu-stacked__name {
	color: var(--msc-name-color, inherit) !important;
	font-size: var(--msc-name-size, inherit) !important;
	font-weight: var(--msc-name-weight, inherit) !important;
	text-align: var(--msc-name-align, left) !important;
	text-shadow: var(--msc-name-text-shadow, none) !important;
	/* The name cell is the FLEXIBLE one: it shrinks and wraps internally
	   (long names / "Angel Hair / Fettuccine / ..." variant labels wrap
	   inside it) instead of pushing the price onto its own line — the
	   price belongs beside the name on the first line. min-width:0 is
	   what actually allows a flex child to shrink below its content. */
	flex: 1 1 0;
	min-width: 0;
}
.msc-menu-stacked__desc {
	display: block;
	font-size: var(--msc-desc-size, 13px) !important;
	color: var(--msc-desc-color, inherit) !important;
	opacity: var(--msc-desc-opacity, 0.65) !important;
}
.msc-menu-stacked__price {
	color: var(--msc-price-color, #c9760c) !important;
	font-weight: var(--msc-price-weight, bold) !important;
	font-size: var(--msc-price-size, inherit) !important;
	background: var(--msc-price-bg, transparent) !important;
	text-shadow: var(--msc-price-text-shadow, none) !important;
	border-radius: var(--msc-price-radius, 0) !important;
	padding: var(--msc-price-padding, 0) !important;
	margin-left: auto; /* stays right-aligned whether it's sharing the name's
	                       line or (rarely, e.g. a very long multi-variant
	                       price list in a narrow column) has wrapped onto
	                       its own line */
	text-align: right;
	/* Keep the price ON the name's first line: it never shrinks (prices
	   shouldn't squeeze), tops-align with the name, and is capped so a
	   long "Small $x · Medium $y · Large $z" list wraps between its own
	   parts rather than starving the name column entirely. */
	flex: 0 0 auto;
	align-self: flex-start;
	max-width: var(--msc-price-max-width, 65%);
}

.msc-menu-item {
	width: 100% !important;
}

/* --card: image centered on top, name, then PRICE, then description on
   its own line below (price before description — unlike --stacked). */
.msc-menu-item--card {
	display: flex; flex-direction: column; align-items: center; text-align: center;
}
.msc-menu-item--card .msc-menu-item__image { width: 100%; }
.msc-menu-item--card .msc-menu-item__desc { margin-top: 4px; }

/* --row: image on one side, name+description+price stacked together on
   the other, single horizontal line overall. */
.msc-menu-item--row {
	display: flex !important; flex-direction: row; align-items: center; gap: 14px;
}
.msc-menu-item--row .msc-menu-item__image { width: 40%; flex: 0 0 auto; margin: 0 !important; }
.msc-menu-item--row .msc-menu-item__row-content { flex: 1 1 auto; min-width: 0; }

.msc-menu-item__image {
	margin: var(--msc-item-image-margin, 0 0 8px) !important;
	background-image: var(--msc-item-image-bg-effect, none) !important;
	animation: var(--msc-item-image-animation, none) !important;
}
.msc-menu-item__image img {
	display: block;
	width: var(--msc-item-image-width, 100%) !important;
	height: var(--msc-item-image-height, 160px) !important;
	object-fit: var(--msc-item-image-fit, cover) !important;
	border-radius: var(--msc-item-image-radius, 0) !important;
	border: var(--msc-item-image-border, none) !important;
	box-shadow: var(--msc-item-image-shadow, none) !important;
	filter: var(--msc-item-image-filter, none) !important;
}
.msc-menu-item__custom {
	display: block;
	color: var(--msc-item-custom-color, inherit) !important;
	font-size: var(--msc-item-custom-size, 13px) !important;
	font-weight: var(--msc-item-custom-weight, normal) !important;
	text-align: var(--msc-item-custom-align, left) !important;
	text-shadow: var(--msc-item-custom-text-shadow, none) !important;
	margin-top: var(--msc-item-custom-margin-top, 6px) !important;
	animation: var(--msc-item-custom-animation, none) !important;
	font-style: var(--msc-custom-style, normal) !important;
	text-transform: var(--msc-custom-transform, none) !important;
	-webkit-text-stroke: var(--msc-custom-stroke-width, 0) var(--msc-custom-stroke-color, transparent) !important;
}
.msc-menu-item__name {
	font-size: var(--msc-name-size, 22px) !important;
	font-weight: var(--msc-name-weight, bold) !important;
	text-align: var(--msc-name-align, left) !important;
	color: var(--msc-name-color, inherit) !important;
	text-shadow: var(--msc-name-text-shadow, none) !important;
	font-style: var(--msc-name-style, normal) !important;
	text-transform: var(--msc-name-transform, none) !important;
	-webkit-text-stroke: var(--msc-name-stroke-width, 0) var(--msc-name-stroke-color, transparent) !important;
}
.msc-menu-item__desc {
	display: block;
	font-size: var(--msc-desc-size, 14px) !important;
	opacity: var(--msc-desc-opacity, 0.75) !important;
	color: var(--msc-desc-color, inherit) !important;
	font-weight: var(--msc-desc-weight, normal) !important;
	text-align: var(--msc-desc-align, left) !important;
	text-shadow: var(--msc-desc-text-shadow, none) !important;
	font-style: var(--msc-desc-style, normal) !important;
	text-transform: var(--msc-desc-transform, none) !important;
	-webkit-text-stroke: var(--msc-desc-stroke-width, 0) var(--msc-desc-stroke-color, transparent) !important;
}
.msc-menu-item__price {
	font-size: var(--msc-price-size, 20px) !important;
	color: var(--msc-price-color, #c9760c) !important;
	background: var(--msc-price-bg, transparent) !important;
	background-image: var(--msc-price-bg-effect, none) !important;
	margin-top: 4px;
	font-weight: var(--msc-price-weight, bold) !important;
	text-shadow: var(--msc-price-text-shadow, none) !important;
	border-radius: var(--msc-price-radius, 0) !important;
	padding: var(--msc-price-padding, 0) !important;
	animation: var(--msc-price-animation, none) !important;
	font-style: var(--msc-price-style, normal) !important;
	text-transform: var(--msc-price-transform, none) !important;
	-webkit-text-stroke: var(--msc-price-stroke-width, 0) var(--msc-price-stroke-color, transparent) !important;
}

/* Each size/variant in a price line (e.g. "Small $12.99") is wrapped in a
   span carrying data-col="small" / data-col="large" / etc, derived from
   its label. Target these to color sizes differently, e.g.:
     [data-col="large"] { color: #c0392b; font-weight: bold; }
   This works the same whether the shortcode rendered as a table or a
   stacked list — table cells get the same data-col attribute. */
.msc-price-part {
	white-space: nowrap;
}
/* The value ("Large") and the price ("$3.69") inside one variation part are
   now separate spans so they can be styled independently. Both default to
   inherit — a preset that never touches these renders identically to
   before this split existed (the price number keeps getting its color from
   --msc-price-color via the .msc-menu-stacked__price / __item__price rules
   above, since inherit just passes that down). */
.msc-price-part__value {
	color: var(--msc-price-value-color, inherit) !important;
	font-weight: var(--msc-price-value-weight, inherit) !important;
	font-size: var(--msc-price-value-size, inherit) !important;
	text-shadow: var(--msc-price-value-text-shadow, none) !important;
}
/* Optional decorations around every size/option label — Price → "Value
   text before/after" preset fields, e.g. "(" + ")" for "(Large)". */
.msc-price-part__value::before { content: var(--msc-price-value-before, ""); }
.msc-price-part__value::after  { content: var(--msc-price-value-after, ""); }
.msc-price-part__price {
	color: var(--msc-price-color, inherit) !important;
	font-weight: var(--msc-price-weight, inherit) !important;
}
/* Attribute label ("Size") shown before a multi-variation price line.
   Hidden by default (most menus don't need "Size" spelled out when the
   values themselves — Small/Medium/Large — are self-explanatory); turn on
   via the Attribute label section in Style Presets. */
.msc-menu-stacked__attr-label {
	display: var(--msc-attr-label-display, none);
	color: var(--msc-attr-label-color, inherit) !important;
	font-size: var(--msc-attr-label-size, .8em) !important;
	font-weight: var(--msc-attr-label-weight, 600) !important;
	margin-right: 6px;
	font-style: var(--msc-attr-label-style, normal) !important;
	text-transform: var(--msc-attr-label-transform, none) !important;
	-webkit-text-stroke: var(--msc-attr-label-stroke-width, 0) var(--msc-attr-label-stroke-color, transparent) !important;
}

/* [menu_rows] category heading — a separate block that sits above the
   table/stacked output it's grouped with, so it can be styled, hidden, or
   animated independently of the rows themselves. Only appears when a
   category name could be resolved and the "Show category heading" option
   (on by default) is left on. */
.msc-menu-category {
	/* No background here on purpose — this div also wraps the item rows
	   below the heading (see MSD_Render::render_category), so a background
	   set here used to paint the whole category section, not just the
	   heading, making --msc-cat-bg behave like a second wrapper background.
	   The heading's own background lives on .msc-menu-category__title below. */
}
.msc-menu-category__title {
	position: relative;
	margin: 0;
	color: var(--msc-cat-color, inherit) !important;
	font-size: var(--msc-cat-size, 24px) !important;
	font-weight: var(--msc-cat-weight, bold) !important;
	text-align: var(--msc-cat-align, left) !important;
	padding: var(--msc-cat-padding, 0 0 8px) !important;
	border: var(--msc-cat-border, none) !important;
	border-radius: var(--msc-cat-radius, 0) !important;
	outline: var(--msc-cat-outline, none) !important;
	outline-offset: var(--msc-cat-outline-offset, 0) !important;
	box-shadow: var(--msc-cat-shadow, none) !important;
	text-shadow: var(--msc-cat-text-shadow, none) !important;
	filter: var(--msc-cat-filter, none) !important;
	background-color: var(--msc-cat-bg, transparent) !important;
	width: var(--msc-cat-width, 100%) !important;
	font-style: var(--msc-cat-style, normal) !important;
	text-transform: var(--msc-cat-transform, none) !important;
	-webkit-text-stroke: var(--msc-cat-stroke-width, 0) var(--msc-cat-stroke-color, transparent) !important;
}
.msc-menu-category__title-text {
	position: relative;
	z-index: 1;
}
/* Scope routing — default/"whole" matches pre-scope behavior: both effect
   and animation apply straight to the title element. */
.msc-menu-category__title:not([data-bgfx-scope]),
.msc-menu-category__title[data-bgfx-scope="whole"] {
	background-image: var(--msc-cat-bg-effect, none), var(--msc-cat-bg-gradient, none) !important;
}
.msc-menu-category__title:not([data-anim-scope]),
.msc-menu-category__title[data-anim-scope="whole"] {
	animation: var(--msc-cat-animation, none) !important;
}
.msc-menu-category__title[data-bgfx-scope="bg"]::before,
.msc-menu-category__title[data-anim-scope="bg"]::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
}
.msc-menu-category__title[data-bgfx-scope="bg"]::before {
	background-image: var(--msc-cat-bg-effect, none), var(--msc-cat-bg-gradient, none) !important;
}
.msc-menu-category__title[data-anim-scope="bg"]::before {
	animation: var(--msc-cat-animation, none) !important;
}
.msc-menu-category__title[data-bgfx-scope="text"] .msc-menu-category__title-text {
	background-image: var(--msc-cat-bg-effect, none), var(--msc-cat-bg-gradient, none) !important;
}
.msc-menu-category__title[data-anim-scope="text"] .msc-menu-category__title-text {
	animation: var(--msc-cat-animation, none) !important;
}

/* Subcategory heading — one per subcategory group within a [menu_rows]
   category listing (e.g. "Fountain Drinks" / "Juice" inside "Drinks",
   "Sandwich Combo" inside "Combo"). Grouping happens in
   MSD_Render::group_by_subcategory(); products with no subcategory of
   their own render without one of these, exactly like before subcategory
   support existed. Deliberately a separate --msc-subcat-* set of vars
   rather than reusing --msc-cat-*, so the parent category heading and its
   subcategory headings can look different from each other. */
.msc-menu-subcategory__title {
	position: relative;
	margin: 0;
	color: var(--msc-subcat-color, inherit) !important;
	font-size: var(--msc-subcat-size, 18px) !important;
	font-weight: var(--msc-subcat-weight, bold) !important;
	text-align: var(--msc-subcat-align, left) !important;
	padding: var(--msc-subcat-padding, 0 0 6px) !important;
	border: var(--msc-subcat-border, none) !important;
	background-color: var(--msc-subcat-bg, transparent) !important;
	width: var(--msc-subcat-width, 100%) !important;
	animation: var(--msc-subcat-animation, none) !important;
	font-style: var(--msc-subcat-style, normal) !important;
	text-transform: var(--msc-subcat-transform, none) !important;
	-webkit-text-stroke: var(--msc-subcat-stroke-width, 0) var(--msc-subcat-stroke-color, transparent) !important;
}
.msc-menu-subcategory__title-text {
	position: relative;
	z-index: 1;
}
.msc-menu-subcategory__title:not([data-bgfx-scope]),
.msc-menu-subcategory__title[data-bgfx-scope="whole"] {
	background-image: var(--msc-subcat-bg-effect, none) !important;
}
.msc-menu-subcategory__title[data-bgfx-scope="bg"]::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background-image: var(--msc-subcat-bg-effect, none) !important;
}
.msc-menu-subcategory__title[data-bgfx-scope="text"] .msc-menu-subcategory__title-text {
	background-image: var(--msc-subcat-bg-effect, none) !important;
}
/* Subcategory-scoped price override — only takes effect once a value is
   set; otherwise falls through to the category/global --msc-price-color
   already applied on these same elements above, so a preset with no
   subcategory price color set renders identically to before. */
.msc-menu-subcategory .msc-menu-table td[data-col],
.msc-menu-subcategory .msc-menu-stacked__price,
.msc-menu-subcategory .msc-menu-item__price {
	color: var(--msc-subcat-price-color, var(--msc-price-color, inherit)) !important;
}

/* Category heading animation options — deliberately just three simple,
   dependency-free options. Anything scroll-triggered or per-row would need
   JS (IntersectionObserver etc.) and is out of scope here. */
@keyframes msc-fade-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}
@keyframes msc-slide-up {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: translateY(0); }
}
@keyframes msc-pulse {
	0%, 100% { opacity: 1; }
	50%      { opacity: .55; }
}
/* Glow pulse / shine sweep — the "button hover, but looping" style
   animations. They ride the same animation/box-shadow/filter properties as
   the shadow/filter fields above, so picking one of these alongside a
   manual Shadow or Filter value will have the animation take over while
   it's running (documented trade-off, not a bug). */
@keyframes msc-glow-pulse {
	0%, 100% { box-shadow: 0 0 0 rgba(255,255,255,0); }
	50%      { box-shadow: 0 0 18px rgba(255,255,255,.55); }
}
@keyframes msc-shine-sweep {
	0%, 100% { filter: brightness(1); }
	50%      { filter: brightness(1.3); }
}

/* ==========================================================================
   [menu_board] / [menu_board_col] / [msc_media] — the CSS Grid layer that
   replaces manually-positioned LayerSlider layers. One [menu_board] call is
   one grid; its --msc-board-* custom properties are written inline by
   MSC_Board (per-instance values like column count, not global theming, so
   they're set on the element itself rather than through a style preset).
   ========================================================================== */

/* Per-item schedule/loop visibility — item-visibility.js toggles this
   class off the visitor's browser clock; element stays in the DOM (so
   nothing pops in late) and is just hidden. */
.msc-vis--hidden {
	display: none !important;
}

/* .msc-board-col below also carries its own display:flex!important —
   equal specificity to .msc-vis--hidden above, and later in the
   cascade, so on a plain ".msc-vis--hidden" alone that flex rule would
   win the tie and the "hidden" column would just stay flexed and
   visible. This two-class selector outranks it regardless of source
   order, so a column-level schedule/loop swap (see
   MSD_Board::render_flat_columns()'s slot/variant handling) actually
   hides the whole column, not just whatever's inside it. */
.msc-board-col.msc-vis--hidden {
	display: none !important;
}

.msc-board {
	background-color: var( --msc-board-bg, transparent ) !important;
	display: grid !important;
	grid-template-columns: repeat( var( --msc-board-columns, 3 ), 1fr ) !important;
	column-gap: var( --msc-board-gap, 24px ) !important;
	row-gap: var( --msc-board-row-gap, 24px ) !important;
	align-items: var( --msc-board-align, stretch ) !important;
	height: var( --msc-board-height, 100% ) !important;
	width: 100%;
	box-sizing: border-box;
}

/* Each column is a flex column internally so a category heading, its rows,
   a media block, and another category (any mix, any order) stack in normal
   flow with no possibility of overlap — the failure mode this whole system
   replaces. */
.msc-board-col {
	display: flex !important;
	flex-direction: column !important;
	gap: var( --msc-board-col-gap, 12px );
	min-width: 0; /* lets long item names/tables shrink instead of forcing the grid wider than the slide */
	min-height: 0;
	overflow: hidden; /* a column's content should never spill past its cell on signage */
}

/* A [menu_board_col] with a table/stacked list inside should have that
   content fill the column's width; center is for a lone image/logo cell. */
.msc-board-col > * {
	width: 100%;
}

.msc-media {
	position: relative;
	width: 100%;
	overflow: hidden;
	border-radius: var( --msc-media-radius, 0 );
	box-shadow: var( --msc-media-shadow, none );
}
.msc-media__el {
	width: 100%;
	height: 100%;
}

/* [msc_embed] — post/page/layerslider tiles, sized the same way [msc_media]
   is (ratio/height/width on the wrapping box) so mixing them into a board's
   columns behaves predictably either way. */
.msc-embed {
	position: relative;
	width: 100%;
	box-sizing: border-box;
}

/* LayerSlider ships its own inline/JS-set pixel width & height on its
   slider root and internal containers, which otherwise beats a plain CSS
   rule (inline styles win over external CSS unless !important is used) —
   these !important rules are what let our box's ratio/height/width
   actually control the rendered size instead of LayerSlider's own idea of
   how big it should be. Covers the common LayerSlider container class
   names across recent versions; harmless no-ops on any it doesn't match. */
/* NOTE: the box (.msc-embed--layerslider) itself is deliberately NOT in
   this list — its own size comes from the shortcode's ratio/height/width
   (inline) and the var-driven preset rule further down; forcing it to
   100%x100% here was what made an explicit height/ratio on a LayerSlider
   item have no effect on the real render. Children are still forced to
   fill the box. */
.msc-embed--layerslider > *,
.msc-embed--layerslider .ls-container,
.msc-embed--layerslider .ls-wp-container,
.msc-embed--layerslider .ls-slide-image,
.msc-embed--layerslider .ls-bg,
.msc-embed--layerslider .ls-layer img,
.msc-embed--layerslider iframe {
	width: 100% !important;
	height: 100% !important;
	max-width: 100% !important;
	max-height: 100% !important;
}
.msc-embed__title {
	font-size: 18px;
	font-weight: bold;
	margin-top: 8px;
}
.msc-embed__excerpt {
	font-size: 14px;
	opacity: .75;
	margin-top: 4px;
}

/* "break after each category" — a thin divider line between stacked
   category blocks (and media) within one column, only when divider="1" is
   set on [menu_board]. The gap itself (category_gap attribute, default
   12px) always applies via .msc-board-col's flex gap, with or without the
   divider line. */
.msc-board--divider .msc-board-col > * + * {
	border-top: var( --msc-board-divider, 1px solid rgba(255,255,255,.15) );
	padding-top: var( --msc-board-col-gap, 12px );
	margin-top: 0; /* the flex gap already provides the space; this avoids doubling it */
}

/* "how can we fill the height of the items, not just the wrapper" — by
   default align-items:stretch (above) only stretches each .msc-board-col
   BOX to match the tallest column; nothing inside was ever told to grow,
   so a shorter column just gets one big blank gap at its own bottom. fill="1"
   on [menu_board] fixes that: each category block in the column shares the
   leftover height, and rows within a stacked category spread out through
   it (space-evenly) instead of clumping at the top. Only applies to
   stacked-layout categories — an HTML <table>'s rows don't reliably stretch
   with flex/grow, so table-layout categories (the Small/Large column
   tables) keep their natural height under fill mode too. */
.msc-board--fill .msc-board-col {
	height: 100%;
}
.msc-board--fill .msc-board-col > * {
	flex: 1 1 0;
	display: flex;
	flex-direction: column;
}
.msc-board--fill .msc-board-col > .msc-menu-category {
	justify-content: flex-start; /* heading stays put at the top */
}
.msc-board--fill .msc-menu-category > .msc-menu-stacked {
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: space-evenly;
}
.msc-board--fill .msc-menu-stacked__row {
	flex: 0 0 auto; /* rows keep their natural height; space-evenly does the spreading */
}
/* Media blocks opt out of the flex-grow reset above — a fixed-ratio photo
   shouldn't stretch. Table-layout categories now stretch their CARD
   (background/border reach the column bottom, so every column's bottom
   edge lands on the same line from a distance) while the table itself
   keeps its natural row height pinned to the top. */
.msc-board--fill .msc-media {
	flex: 0 0 auto;
}
.msc-board--fill .msc-board-col > *:has(.msc-menu-table) {
	flex: 1 1 auto;
	justify-content: flex-start;
}
.msc-board--fill .msc-board-col .msc-menu-table {
	flex: 0 0 auto; /* rows stay natural height; the card's background fills the rest */
}

/* Add-on groups: both the per-product inline list (addons_display_html,
   used when a menu_rows/menu_item "fields" list includes addons) and the
   standalone [menu_addons] block (addon_group_block) share the same
   .msc-addon-price treatment; the block itself gets its own wrapper. */
.msc-menu-item__addon-group {
	margin-top: 4px;
	font-size: 0.85em;
	opacity: 0.85;
}
.msc-addon-group__label {
	font-weight: 600;
}
.msc-addon-price {
	opacity: 0.75;
}

.msc-addon-block {
	padding: 8px 0;
}
.msc-addon-block--left {
	text-align: left;
}
.msc-addon-block--center {
	text-align: center;
}
.msc-addon-block--right {
	text-align: right;
}
.msc-addon-block__label {
	font-weight: 600;
	margin-bottom: 2px;
}
.msc-addon-block__desc {
	font-size: 0.85em;
	opacity: 0.75;
	margin-bottom: 4px;
}
.msc-addon-block__options {
	font-size: 0.9em;
}

/* ─── Style Preset CSS vars for addon groups ─────────────────────────── */
.msc-addon-block__label {
	color: var(--msc-addon-label-color, inherit) !important;
	font-size: var(--msc-addon-label-size, inherit) !important;
	font-weight: var(--msc-addon-label-weight, 600) !important;
	background-color: var(--msc-addon-label-bg, transparent) !important;
	background-image: var(--msc-addon-label-bg-effect, none) !important;
	animation: var(--msc-addon-label-animation, none) !important;
	font-style: var(--msc-addon-style, normal) !important;
	text-transform: var(--msc-addon-transform, none) !important;
	-webkit-text-stroke: var(--msc-addon-stroke-width, 0) var(--msc-addon-stroke-color, transparent) !important;
	/* display/padding/radius only take effect once a background or effect
	   is actually set (var() falls back to 0/none), so a plain label with
	   no background chosen renders exactly as before. */
	display: inline-block;
	padding: var(--msc-addon-label-bg-padding, 0);
	border-radius: var(--msc-addon-label-bg-radius, 0);
}
.msc-addon-block__options {
	color: var(--msc-addon-options-color, inherit) !important;
	font-size: var(--msc-addon-options-size, 0.9em) !important;
	text-align: inherit; /* inherits from the --center/--right modifier class above */
	font-style: var(--msc-addon-style, normal) !important;
	text-transform: var(--msc-addon-transform, none) !important;
}
.msc-addon-price {
	color: var(--msc-addon-price-color, inherit) !important;
}
.msc-addon-block {
	padding: var(--msc-addon-padding, 8px 0) !important;
	text-align: var(--msc-addon-align, left) !important;
}

/* ─── Style Preset CSS vars for image ───────────────────────────────────
   .msc-media is the shared wrapper for both [msc_media type="image"] and
   type="video" — the only thing that tells them apart is the tag of the
   .msc-media__el inside, so :has() is what lets image/video get separate
   Style Preset treatment without the shortcode needing separate wrapper
   classes. (Supported in all evergreen/Chromium-based signage players;
   these rules simply no-op on anything that doesn't support :has().) */
.msc-media:has(> img.msc-media__el) {
	background: var(--msc-image-backdrop-bg, var(--msc-image-bg, transparent)) !important;
	backdrop-filter: var(--msc-image-backdrop-filter, none);
	-webkit-backdrop-filter: var(--msc-image-backdrop-filter, none);
	width: var(--msc-image-width, 100%) !important;
	padding: var(--msc-image-padding, 0) !important;
	border: var(--msc-image-border, none) !important;
	border-radius: var(--msc-image-radius, 0) !important;
	outline: var(--msc-image-outline, none) !important;
	outline-offset: var(--msc-image-outline-offset, 0) !important;
	box-shadow: var(--msc-image-shadow, none) !important;
	animation: var(--msc-image-animation, none) !important;
	background-image: var(--msc-image-bg-effect, none) !important;
}
.msc-media img.msc-media__el {
	opacity: var(--msc-image-opacity, 1) !important;
	filter: var(--msc-image-filter, none) !important;
	object-fit: var(--msc-image-object-fit, cover) !important;
	text-shadow: var(--msc-image-text-shadow, none) !important;
}

/* ─── Style Preset CSS vars for video ───────────────────────────────── */
.msc-media:has(> video.msc-media__el) {
	background: var(--msc-video-backdrop-bg, var(--msc-video-bg, transparent)) !important;
	backdrop-filter: var(--msc-video-backdrop-filter, none);
	-webkit-backdrop-filter: var(--msc-video-backdrop-filter, none);
	width: var(--msc-video-width, 100%) !important;
	padding: var(--msc-video-padding, 0) !important;
	border: var(--msc-video-border, none) !important;
	border-radius: var(--msc-video-radius, 0) !important;
	outline: var(--msc-video-outline, none) !important;
	outline-offset: var(--msc-video-outline-offset, 0) !important;
	box-shadow: var(--msc-video-shadow, none) !important;
	animation: var(--msc-video-animation, none) !important;
	background-image: var(--msc-video-bg-effect, none) !important;
}
.msc-media video.msc-media__el {
	opacity: var(--msc-video-opacity, 1) !important;
	filter: var(--msc-video-filter, none) !important;
	object-fit: var(--msc-video-object-fit, cover) !important;
	text-shadow: var(--msc-video-text-shadow, none) !important;
}

/* ─── Style Preset CSS vars for LayerSlider embed ───────────────────── */
.msc-embed--layerslider {
	background: var(--msc-ls-bg, transparent) !important;
	width: var(--msc-ls-width, 100%) !important;
	padding: var(--msc-ls-padding, 0) !important;
	border: var(--msc-ls-border, none) !important;
	border-radius: var(--msc-ls-radius, 0) !important;
	outline: var(--msc-ls-outline, none) !important;
	outline-offset: var(--msc-ls-outline-offset, 0) !important;
	box-shadow: var(--msc-ls-shadow, none) !important;
	text-shadow: var(--msc-ls-text-shadow, none) !important;
	opacity: var(--msc-ls-opacity, 1) !important;
	filter: var(--msc-ls-filter, none) !important;
	animation: var(--msc-ls-animation, none) !important;
	background-image: var(--msc-ls-bg-effect, none) !important;
}

/* ─── Price parts: currency symbol & decimals, independently stylable ───
   format_price_html() wraps every rendered price as
   [symbol][int][dec] spans; these var()-driven rules are what the Style
   Preset "Price" group's symbol_*/dec_* fields feed. Defaults are all
   inherit/normal, so presets that never touch them change nothing. */
.msc-price-symbol {
	color: var(--msc-price-symbol-color, inherit);
	font-size: var(--msc-price-symbol-size, 1em);
	vertical-align: var(--msc-price-symbol-valign, baseline);
	display: var(--msc-price-symbol-display, inline);
}
.msc-price-dec {
	color: var(--msc-price-dec-color, inherit);
	font-size: var(--msc-price-dec-size, 1em);
	vertical-align: var(--msc-price-dec-valign, baseline);
}

/* "Sizes after item name" mode: the small Small / Medium / Large line the
   Board Builder's category "Size/variant display" option can move up next
   to the item name (shared-price case). Styled via the Style Preset Price
   group's vl_* fields. */
.msc-variant-labels {
	display: var(--msc-variant-labels-display, inline);
	color: var(--msc-variant-labels-color, inherit);
	font-size: var(--msc-variant-labels-size, 0.55em);
	font-weight: var(--msc-variant-labels-weight, normal);
	opacity: var(--msc-variant-labels-opacity, 0.85);
	text-shadow: var(--msc-variant-labels-text-shadow, none);
	margin-left: 0.5em;
	vertical-align: middle;
	white-space: nowrap;
}
.msc-variant-labels::before { content: var(--msc-variant-labels-before, ""); }
.msc-variant-labels::after  { content: var(--msc-variant-labels-after, ""); }
.msc-variant-labels[style], /* keep specificity low; block placement resets the indent */
.msc-menu-stacked__name .msc-variant-labels {
	line-height: 1.2;
}

/* Per-item line height (:lh= wrapper): applied to CONTENT pieces only —
   category/subcategory headings deliberately keep their own metrics
   (stacked rows and table cells already consume the var directly). */
.msc-lh .msc-text,
.msc-lh .msc-menu-item,
.msc-lh .msc-addon-block,
.msc-lh .msc-menu-item__addon-group,
.msc-lh .msc-embed__title,
.msc-lh .msc-embed__excerpt {
	line-height: var(--msc-item-lh, normal);
}
/* Split combined variations — the choices line under a row (see
   MSD_Render::split_combo_data). Reuses the add-on group look so the
   Add-on groups preset section styles it. */
.msc-menu-stacked__choices {
	flex-basis: 100%;
	font-size: 0.85em;
	opacity: 0.85;
	line-height: var(--msc-item-lh, var(--msc-board-lh, normal));
}
