/*
Theme Name: Unapp
Theme URI: https://colorlib.com/wp/themes/unapp/
Author: Colorlib
Author URI: https://colorlib.com
Description: Unapp is a lightweight, block-based WordPress theme with thirteen one-click starter sites — SaaS, portfolio, church, blog, fitness, restaurant, agency, shop, property, practice, courses, events and finance. Built for the Site Editor with 140+ section patterns, twelve colour palettes and five typography presets you can mix, seven section styles and eleven block styles. WooCommerce templates included. Self-hosted variable fonts, no page-builder framework, no jQuery, no icon fonts.
Version: 2.6.0
Update URI: https://updates.colorlib.com/theme/unapp.json
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 7.4
License: GNU General Public License v3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Text Domain: unapp
Tags: blog, one-column, rtl-language-support, wide-blocks, block-patterns, block-styles, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, style-variations, template-editing, threaded-comments, translation-ready

Unapp WordPress Theme, (C) 2018-2026 Colorlib
Unapp is distributed under the terms of the GNU GPL.
*/

/*
 * All visual styling lives in theme.json (global styles), styles/*.json (section
 * and color variations) and assets/css/*.css (per-block styles loaded on demand
 * via wp_enqueue_block_style). This file intentionally holds only the theme
 * header plus the few rules that have no theme.json equivalent.
 */

/* Post card thumbnails: clip and gently zoom on hover. */
.wp-block-post-featured-image {
	overflow: hidden;
}

.wp-block-post-featured-image img {
	transition: transform 0.4s ease;
}

@media (prefers-reduced-motion: no-preference) {
	.wp-block-post:hover .wp-block-post-featured-image img {
		transform: scale(1.03);
	}
}

/* Keep phone/app screenshots from stretching in narrow flex columns. */
.wp-block-image img {
	height: auto;
}

/* ==========================================================================
   Header navigation
   Core swaps the menu for the overlay toggle below 600px. With a real menu
   plus a call-to-action button that is far too late: between roughly 600 and
   1000 pixels the items wrap onto two or three lines. Move the swap up so the
   header always stays on one line.
   ========================================================================== */
@media (max-width: 999px) {
	.unapp-header-row .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	.unapp-header-row .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

/* Never let the header row wrap: the logo stays left, the menu and button stay
   right. Works wherever the header pattern is used — template part or page. */
.unapp-header-row {
	flex-wrap: nowrap;
}

.unapp-header-row > .wp-block-group {
	min-width: 0;
}

.unapp-header-row .wp-block-navigation:not(.is-vertical) > .wp-block-navigation__container {
	flex-wrap: nowrap;
}

.unapp-header-row .wp-block-navigation:not(.is-vertical) .wp-block-navigation-item__content {
	white-space: nowrap;
}

.unapp-header-row .wp-block-site-title {
	white-space: nowrap;
}

/* The mobile overlay is the one place the menu should stack. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	flex-wrap: wrap;
}

/* Core paints the open overlay white with black text whatever the palette — a
   white flash on a dark site — and keeps the header's 13px capitals, about
   22px tall to tap. The overlay takes its ground and text from the palette and
   sets the links at reading size with 44px targets. */
.wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	background-color: var(--wp--preset--color--base);
}

.wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	color: var(--wp--preset--color--contrast);
}

.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content .wp-block-navigation__container {
	gap: 0.25rem;
}

.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content .wp-block-navigation-item__content {
	display: flex;
	align-items: center;
	box-sizing: border-box;
	min-height: 44px;
	padding-block: 0.35rem;
	font-size: 1.25rem;
	letter-spacing: -0.01em;
	line-height: 1.3;
	text-transform: none;
}

.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-size: 1.0625rem;
	font-weight: 500;
}

/* The toggles draw a 24px icon; pad them to a 44px target without moving it.
   (The open button is a flex-layout child, whose margins core zeroes.) */
.wp-block-navigation .wp-block-navigation__responsive-container-open,
.wp-block-navigation .wp-block-navigation__responsive-container-close {
	padding: 10px;
	margin: -10px;
}

/* The small, uppercase, tracked style theme.json gives core/navigation is the
   header's. Every footer's link columns picked it up too and sat in capitals
   beside sentence-case columns, so menus outside the header read as the text
   around them. A menu that collapses into the mobile overlay is a site menu
   wherever it sits, and keeps the style — which is also how a header part
   edited on its own in the Site Editor, outside any <header>, keeps it. */
.wp-block-navigation:not(header *, .unapp-header-row *, :has(.wp-block-navigation__responsive-container-open)) {
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	letter-spacing: inherit;
	text-transform: none;
}

/* ==========================================================================
   Focus
   One consistent, high-contrast focus ring everywhere, instead of leaving it to
   each browser's default (which is blue and disappears on dark sections).
   ========================================================================== */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
	border-radius: 2px;
}

/* On coloured grounds — dark and gradient sections, covers, groups filled with
   a palette colour — a primary ring vanishes: a primary-to-accent band starts
   in the very colour of the ring. There the ring switches to the section's own
   text colour, which the section already has to keep readable. */
:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline-color: currentColor;
}

/* A filled button's label is coloured against its own fill (primary text on a
   white button), so its currentColor ring can match the section. There the
   ring takes the fill colour instead — the colour the pattern chose to stand
   out from that section. Default buttons are filled with secondary. */
:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button:not(.is-style-outline) > .wp-block-button__link:focus-visible {
	outline-color: var(--wp--preset--color--secondary);
}

:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button > .wp-block-button__link.has-base-background-color:focus-visible {
	outline-color: var(--wp--preset--color--base);
}

:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button > .wp-block-button__link.has-contrast-background-color:focus-visible {
	outline-color: var(--wp--preset--color--contrast);
}

:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button > .wp-block-button__link.has-primary-background-color:focus-visible {
	outline-color: var(--wp--preset--color--primary);
}

:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button > .wp-block-button__link.has-accent-background-color:focus-visible {
	outline-color: var(--wp--preset--color--accent);
}

:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button > .wp-block-button__link.has-surface-background-color:focus-visible {
	outline-color: var(--wp--preset--color--surface);
}

/* A dark-filled button sits on a dark section, so there its light label is the
   colour that shows. */
:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-button > .wp-block-button__link.has-dark-background-color:focus-visible {
	outline-color: currentColor;
}

/* Search with the button inside: core strips the field's outline and draws the
   box on the wrapper, so the ring goes on the wrapper. Inside that white box
   the button's ring is back on a light ground, so it returns to primary. */
.wp-block-search__button-inside .wp-block-search__inside-wrapper:has(> .wp-block-search__input:focus-visible) {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

:where(.is-style-section-dark, .is-style-section-gradient, .wp-block-cover, [class*="-gradient-background"],
	.has-primary-background-color, .has-secondary-background-color, .has-accent-background-color,
	.has-contrast-background-color, .has-dark-background-color)
	.wp-block-search__button-inside .wp-block-search__inside-wrapper:has(> .wp-block-search__input:focus-visible) {
	outline-color: currentColor;
}

.wp-block-search__button-inside .wp-block-search__inside-wrapper .wp-block-search__button:focus-visible {
	outline-color: var(--wp--preset--color--primary);
}

/* ==========================================================================
   Sticky header
   Users can switch it on per header from the block's Position control. These
   rules only make the result look right once they do.
   ========================================================================== */
.wp-block-template-part > .wp-block-group.is-position-sticky {
	backdrop-filter: saturate(140%) blur(12px);
	-webkit-backdrop-filter: saturate(140%) blur(12px);
	background-color: color-mix(in srgb, var(--wp--preset--color--base) 88%, transparent);
	z-index: 100;
}

/* ==========================================================================
   Accordion (WordPress 7.0)
   ========================================================================== */
.wp-block-accordion .wp-block-accordion-item {
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 14px;
	background: var(--wp--preset--color--base);
}

.wp-block-accordion .wp-block-accordion-item + .wp-block-accordion-item {
	margin-top: 0.75rem;
}

.wp-block-accordion-heading__toggle {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.15rem 1.5rem;
	background: none;
	border: 0;
	cursor: pointer;
	color: inherit;
	font: inherit;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 600;
	text-align: start;
}

.wp-block-accordion-heading__toggle-icon {
	flex: 0 0 auto;
	color: var(--wp--preset--color--primary);
	font-size: 1.35em;
	line-height: 1;
}

.wp-block-accordion-panel > * {
	margin-inline: 1.5rem;
}

.wp-block-accordion-panel > *:last-child {
	margin-bottom: 1.35rem;
}

/* ==========================================================================
   Pattern utilities
   Small helpers used by patterns that theme.json cannot express. Each is a
   plain class set on the block, so block markup stays valid.
   ========================================================================== */

/* Social links: core paints each service its brand colour in the logos-only
   style at the same specificity as the block's own colour class, so the winner
   depends on stylesheet order. Make the chosen palette colour win outright. */
.wp-block-social-links.is-style-logos-only .wp-social-link.has-base-color.has-base-color {
	color: var(--wp--preset--color--base);
}

.wp-block-social-links.is-style-logos-only .wp-social-link.has-muted-color.has-muted-color {
	color: var(--wp--preset--color--muted);
}

.wp-block-social-links.is-style-logos-only .wp-social-link.has-contrast-color.has-contrast-color {
	color: var(--wp--preset--color--contrast);
}

.wp-block-social-links.is-style-logos-only .wp-social-link.has-primary-color.has-primary-color {
	color: var(--wp--preset--color--primary);
}

/* Galleries: core drops to two across on small screens, which leaves a third
   image alone on the last row. Go to a single column instead. */
@media (max-width: 600px) {
	.wp-block-gallery.has-nested-images.columns-3 > figure.wp-block-image:not(#individual-image),
	.wp-block-gallery.has-nested-images.columns-default > figure.wp-block-image:not(#individual-image) {
		width: 100%;
	}
}

/* Even grids. WP's grid layout keeps a fixed column count at every width, which
   strands the last item on its own row on smaller screens. These classes step
   the columns down through counts that always divide the item count evenly. */
.wp-block-group.unapp-grid-4 {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.wp-block-group.unapp-grid-3 {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 1000px) {
	.wp-block-group.unapp-grid-4,
	.wp-block-group.unapp-grid-3 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* An odd number of items cannot pair up without stranding the last one, so
	   those grids stay three across until they can go straight to one. */
	.wp-block-group.unapp-grid-3:has(> :last-child:nth-child(odd)) {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 739px) {
	.wp-block-group.unapp-grid-3:has(> :last-child:nth-child(odd)) {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 560px) {
	.wp-block-group.unapp-grid-4,
	.wp-block-group.unapp-grid-3 {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Logo cloud: an even grid so no logo is left stranded on its own row —
   six across, then three, then two. */
.wp-block-group.unapp-logo-cloud {
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	align-items: center;
	justify-items: center;
}

@media (max-width: 900px) {
	.wp-block-group.unapp-logo-cloud {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 480px) {
	.wp-block-group.unapp-logo-cloud {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.unapp-logo-cloud img {
	max-width: 100%;
}

/* Logo cloud: quiet, monochrome marks that pick up the palette on hover. */
.unapp-logo-cloud img {
	opacity: 0.55;
	filter: grayscale(1);
	transition: opacity 0.2s ease, filter 0.2s ease;
}

.unapp-logo-cloud:hover img {
	opacity: 0.75;
}

/* ==========================================================================
   Post grids (Query Loop)
   Cards in a row share one height, so meta, titles and "Read more" line up
   whether or not a post has a featured image.
   ========================================================================== */
.wp-block-post-template.is-layout-grid > li {
	display: flex;
}

.wp-block-post-template.is-layout-grid > li > .wp-block-group {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
}

.wp-block-post-template.is-layout-grid .wp-block-post-excerpt {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
}

.wp-block-post-template.is-layout-grid .wp-block-post-excerpt__more-text {
	margin-top: auto;
	padding-top: 0.75em;
}

/* Cards in a row share one height too. Core stretches each column to the row
   (and grid items stretch on their own), but a card inside a column kept its
   content height, so a row of testimonials measured 336/302/302px and a row of
   pricing cards 389/424/389px. A card that is its column's only child now
   fills the column. Columns aligned top, centre or bottom are not stretched by
   core, and stay as they are. */
.wp-block-columns:not([class*="are-vertically-aligned-"]) > .wp-block-column:not([class*="is-vertically-aligned-"]) > .wp-block-group:only-child:is(.is-style-card, .is-style-elevated, .is-style-frosted, .is-style-outline, .is-style-section-gradient, .is-style-section-dark) {
	box-sizing: border-box;
	height: 100%;
}

/* A card that ends in buttons — in Columns or a grid — pins them to its
   bottom edge, so the calls to action in a row line up. The spare height goes
   below the block before the buttons, which keeps the buttons' own top margin
   (set inline by the patterns). */
:is(
	.wp-block-columns:not([class*="are-vertically-aligned-"]) > .wp-block-column:not([class*="is-vertically-aligned-"]) > .wp-block-group:only-child,
	.is-layout-grid > .wp-block-group
):is(.is-style-card, .is-style-elevated, .is-style-frosted, .is-style-outline, .is-style-section-gradient, .is-style-section-dark):has(> .wp-block-buttons:last-child) {
	display: flex;
	flex-direction: column;
}

:is(
	.wp-block-columns:not([class*="are-vertically-aligned-"]) > .wp-block-column:not([class*="is-vertically-aligned-"]) > .wp-block-group:only-child,
	.is-layout-grid > .wp-block-group
):is(.is-style-card, .is-style-elevated, .is-style-frosted, .is-style-outline, .is-style-section-gradient, .is-style-section-dark) > :nth-last-child(2):has(+ .wp-block-buttons:last-child) {
	margin-bottom: auto;
}

/* Query pagination reads as one control group. */
.wp-block-query-pagination {
	gap: 0.4rem;
}

.wp-block-query-pagination-numbers {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.4rem;
}

.wp-block-query-pagination :is(.page-numbers, .wp-block-query-pagination-previous, .wp-block-query-pagination-next) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.5em;
	padding: 0.45em 0.85em;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 999px;
	text-decoration: none;
	line-height: 1;
}

.wp-block-query-pagination .page-numbers.dots {
	min-width: 0;
	padding-inline: 0.35em;
	border-color: transparent;
}

.wp-block-query-pagination .page-numbers.current {
	background-color: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

.wp-block-query-pagination :is(a.page-numbers, a.wp-block-query-pagination-previous, a.wp-block-query-pagination-next):hover {
	background-color: var(--wp--preset--color--surface);
	border-color: var(--wp--preset--color--muted);
}

/* ==========================================================================
   Content alignment
   Post content is a full-width constrained container so wide/full blocks can
   bleed. Core floats legacy left/right aligned direct children to the edge of
   that container (= the viewport); pull them back to the content column so
   left, right, center, wide and full stay predictable.
   ========================================================================== */
.wp-block-post-content.wp-block-post-content.is-layout-constrained > .alignleft {
	margin-inline-start: max(0px, calc((100% - var(--wp--style--global--content-size)) / 2));
}

.wp-block-post-content.wp-block-post-content.is-layout-constrained > .alignright {
	margin-inline-end: max(0px, calc((100% - var(--wp--style--global--content-size)) / 2));
}

/* Full-width text containers without their own padding must not touch the viewport edge. */
.wp-block-post-content > .alignfull.wp-block-columns:not([style*="padding"]),
.wp-block-post-content > .alignfull.wp-block-group:not(.has-global-padding):not([style*="padding"]),
.wp-block-post-content > .alignfull.wp-block-gallery > figcaption,
.wp-block-post-content > .alignfull.wp-block-image > figcaption {
	padding-inline: var(--wp--style--root--padding-left, 1.5rem) var(--wp--style--root--padding-right, 1.5rem);
}

/* Legacy paginated posts (<!--nextpage-->). */
.post-nav-links {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-top: var(--wp--preset--spacing--50);
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.post-nav-links .post-page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.25em;
	padding: 0.35em 0.6em;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 999px;
	text-decoration: none;
}

.post-nav-links .post-page-numbers.current {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

/* Classic (freeform) markup has no block gap, so give it the same vertical
   rhythm as block content. Elements rendered by blocks carry a wp-block-*
   class and keep using blockGap. */
:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) :is(h1, h2, h3, h4, h5, h6):not([class*="wp-block-"]) {
	margin-top: 1.8em;
	margin-bottom: 0.6em;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) :is(p, ul, ol, dl, table, pre, blockquote, address, figure, form):not([class*="wp-block-"]) {
	margin-top: 0;
	margin-bottom: 1.5em;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) li > :is(ul, ol) {
	margin-top: 0.35em;
	margin-bottom: 0.35em;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) li {
	margin-bottom: 0.35em;
}

/* Consecutive headings stay tight together. */
:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) :is(h1, h2, h3, h4, h5, h6):not([class*="wp-block-"]) + :is(h1, h2, h3, h4, h5, h6):not([class*="wp-block-"]) {
	margin-top: 0.8em;
}

:is(.wp-block-post-content, .wp-block-comment-content) > :first-child {
	margin-top: 0;
}

:is(.wp-block-post-content, .wp-block-comment-content) > :last-child {
	margin-bottom: 0;
}

/* ==========================================================================
   Classic (non-block) content: shortcodes, captions, HTML tags
   Scoped to post/comment content and the editor canvas.
   ========================================================================== */
:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) img {
	max-width: 100%;
	height: auto;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) :where(figure) {
	margin-inline: 0;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) .aligncenter {
	display: block;
	margin-inline: auto;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) img.alignleft,
:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) .wp-caption.alignleft {
	float: inline-start;
	margin: 0.5em 1.5em 1em 0;
	margin-inline: 0 1.5em;
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) img.alignright,
:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) .wp-caption.alignright {
	float: inline-end;
	margin: 0.5em 0 1em 1.5em;
	margin-inline: 1.5em 0;
}

/* Classic captions ([caption]) match block captions. */
.wp-caption {
	max-width: 100%;
	margin-bottom: 1.5em;
}

.wp-caption img {
	display: block;
}

.wp-caption-text,
.gallery-caption {
	margin-top: 0.5em;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
}

/* Classic [gallery] shortcode → responsive grid. */
.gallery {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1rem;
	margin: 1.5em 0;
}

.gallery-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.gallery-columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.gallery-columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.gallery-columns-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.gallery-columns-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.gallery-columns-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
.gallery-columns-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
.gallery-columns-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }

.gallery-item {
	margin: 0;
	text-align: center;
}

.gallery-icon img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1;
	object-fit: cover;
	border-radius: 8px;
}

/* A single-column classic gallery keeps the image's own proportions. */
.gallery-columns-1 .gallery-icon img {
	aspect-ratio: auto;
}

@media (max-width: 600px) {
	.gallery-columns-4,
	.gallery-columns-5,
	.gallery-columns-6,
	.gallery-columns-7,
	.gallery-columns-8,
	.gallery-columns-9 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Classic blockquote (block quotes are styled by theme.json). */
:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) blockquote:not([class*="wp-block-"]):not(.wp-block-pullquote *) {
	margin: 1.5em 0;
	padding-inline-start: var(--wp--preset--spacing--40);
	border-inline-start: 4px solid var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--large);
}

:is(.wp-block-post-content, .wp-block-comment-content, .editor-styles-wrapper) blockquote:not([class*="wp-block-"]) cite {
	display: block;
	margin-top: 0.5em;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	font-style: normal;
}

/* Tables — classic and block share the same rhythm. */
:is(.wp-block-post-content, .wp-block-comment-content) table {
	width: 100%;
	margin: 1.5em 0;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--small);
}

:is(.wp-block-post-content, .wp-block-comment-content) :is(td, th) {
	padding: 0.75rem;
	border: 1px solid var(--wp--preset--color--border);
	text-align: start;
	vertical-align: top;
}

:is(.wp-block-post-content, .wp-block-comment-content) th {
	font-weight: 600;
}

/* Preformatted / code — classic tags match the Code block. */
:is(.wp-block-post-content, .wp-block-comment-content) pre:not([class*="wp-block-"]) {
	margin: 1.5em 0;
	padding: var(--wp--preset--spacing--40);
	overflow-x: auto;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 8px;
	background: var(--wp--preset--color--surface);
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
}

:is(.wp-block-post-content, .wp-block-comment-content) :is(:not(pre) > code, kbd, samp) {
	padding: 0.15em 0.4em;
	border-radius: 4px;
	background: var(--wp--preset--color--surface);
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 0.9em;
}

/* Definition lists, rules, addresses. */
:is(.wp-block-post-content, .wp-block-comment-content) dt {
	font-weight: 600;
}

:is(.wp-block-post-content, .wp-block-comment-content) dd {
	margin: 0 0 1em;
	margin-inline-start: var(--wp--preset--spacing--40);
}

:is(.wp-block-post-content, .wp-block-comment-content) hr:not([class*="wp-block-"]) {
	margin: 2em 0;
	border: 0;
	border-top: 1px solid var(--wp--preset--color--border);
}

:is(.wp-block-post-content, .wp-block-comment-content) address {
	margin-bottom: 1.5em;
	font-style: normal;
}

/* Media embeds never overflow the column. */
:is(.wp-block-post-content, .wp-block-comment-content) :is(iframe, embed, object, video) {
	max-width: 100%;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

/* Core's "Square" style targets the wrapper, but the radius is set on the link
   by global styles, so it needs re-applying here. */
.wp-block-button.is-style-squared > .wp-block-button__link,
.wp-block-button.is-style-squared .wp-element-button {
	border-radius: 0;
}

/* Aligned single buttons should still line up with the text column. */
.wp-block-button.aligncenter {
	text-align: center;
}

/* Buttons placed in a flex row (e.g. the header) must not get squeezed by long menus. */
.is-layout-flex > .wp-block-buttons {
	flex-shrink: 0;
}

/* ==========================================================================
   Form fields
   Without a colour of their own, text fields fall back to the browser's white
   box with black text — which is what the comment form and search fields
   showed on a dark palette. Take both from the palette instead. Zero
   specificity, so a form plugin's or WooCommerce's own field styles still win.
   ========================================================================== */
:where(input:not([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="image"], [type="hidden"]), textarea, select) {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
}

:where(input, textarea)::placeholder {
	color: var(--wp--preset--color--muted);
	opacity: 1;
}

/* Search with the button inside draws the box on its wrapper, which core
   paints white. */
.wp-block-search__button-inside .wp-block-search__inside-wrapper {
	background-color: var(--wp--preset--color--base);
}

/* Full-width sections sit flush
   ------------------------------------------------------------------------
   The root block gap (1.25rem) lands as a top margin on every block in a
   constrained layout and on every top-level template area. Between two
   full-bleed sections, and between the header or footer and a page that starts
   or ends with one, that margin showed as a 20px strip of page ground above
   tinted sections, gradient bands, cover heroes and the dark footer. Sections
   carry their own padding, so the gap adds nothing there. Ordinary content — a
   paragraph after a full-width image, a heading after a cover — keeps it. */
:is(.wp-block-post-content, .is-root-container) > :is(.wp-block-group, .wp-block-cover).alignfull
	+ :is(.wp-block-group, .wp-block-cover).alignfull {
	margin-block-start: 0;
}

.wp-site-blocks > main:has(> .wp-block-post-content:first-child > :is(.wp-block-group, .wp-block-cover).alignfull:first-child) {
	margin-block-start: 0;
}

.wp-site-blocks > main:has(> .wp-block-post-content:last-child > :is(.wp-block-group, .wp-block-cover).alignfull:last-child) + footer {
	margin-block-start: 0;
}

/* Section seams
   ------------------------------------------------------------------------
   Sections are separated by their ground: explanation on the page ground,
   proof and prices on the tinted one. Where two sections share a ground they
   would otherwise read as one long column, so the second takes a hairline. */
:is(.wp-block-post-content, .editor-styles-wrapper) > .wp-block-group.alignfull:not(.is-style-section-soft):not(.has-background):not(.wp-block-cover)
	+ .wp-block-group.alignfull:not(.is-style-section-soft):not(.has-background):not(.wp-block-cover),
:is(.wp-block-post-content, .editor-styles-wrapper) > .wp-block-group.alignfull.is-style-section-soft
	+ .wp-block-group.alignfull.is-style-section-soft {
	border-top: 1px solid var(--wp--preset--color--border);
}

/* Header on small screens
   ------------------------------------------------------------------------
   The header row is nowrap by contract, so its children have to be allowed to
   shrink or they push past the viewport. With a long call-to-action label — or
   with WooCommerce adding account and cart icons to the row — the button was
   overflowing by about 36px at 390px.

   The button used to keep its full width, so a long label ("Book an
   appointment") still pushed the page to 409px at 390 and 392px at 360. Now the
   brand takes whatever the menu toggle and button leave, down to a floor, and
   wraps onto a second line before it is cut; only below that floor does the
   button label wrap. */
@media (max-width: 599px) {
	.unapp-header-row > .wp-block-group {
		min-width: 0;
	}

	.unapp-header-row > .wp-block-group:first-child {
		flex: 1 1 0;
		min-width: min(8.5rem, 44%);
	}

	.unapp-header-row > .wp-block-group:last-child {
		flex: 0 1 auto;
	}

	.unapp-header-row > .wp-block-group > :is(.wp-block-site-logo, .wp-block-navigation) {
		flex-shrink: 0;
	}

	/* The row's gaps come from block spacing presets; at this width they are
	   most of the overflow. */
	.unapp-header-row,
	.unapp-header-row > .wp-block-group {
		gap: 0.6rem !important;
	}

	.unapp-header-row .wp-block-site-title {
		min-width: 0;
		display: -webkit-box;
		overflow: hidden;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 2;
		line-clamp: 2;
		white-space: normal;
		overflow-wrap: anywhere;
		line-height: 1.15;
	}

	.unapp-header-row.unapp-header-row .wp-block-buttons,
	.unapp-header-row .wp-block-buttons > .wp-block-button {
		flex-shrink: 1;
		min-width: 0;
	}

	/* The header pattern sets this padding and a font-size class inline, so only
	   !important reaches them. */
	.unapp-header-row .wp-block-buttons > .wp-block-button > .wp-block-button__link {
		padding: 0.55rem 0.75rem !important;
		font-size: 0.8125rem !important;
		line-height: 1.15;
		text-wrap: balance;
	}
}

/* Composition patterns
   ------------------------------------------------------------------------
   Behaviour the block editor cannot express: a sticky explanation column, a
   logo marquee, and the monthly/yearly price switch. All three degrade to a
   sensible static layout with no JavaScript and no motion. */

.unapp-sticky {
	position: sticky;
	top: var(--wp--preset--spacing--50);
}

@media (max-width: 781px) {
	.unapp-sticky {
		position: static;
	}
}

.unapp-marquee {
	overflow: hidden;
	mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.unapp-marquee__track {
	width: max-content;
	animation: unapp-marquee 46s linear infinite;
}

.unapp-marquee__track figure {
	margin: 0;
	flex: 0 0 auto;
	opacity: 0.55;
	filter: grayscale(1);
}

/* Pause for a pointer and for the keyboard alike: a logo that is a link must
   hold still while it has focus. */
.unapp-marquee:hover .unapp-marquee__track,
.unapp-marquee:focus-within .unapp-marquee__track {
	animation-play-state: paused;
}

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

@media (prefers-reduced-motion: reduce) {
	.unapp-marquee__track {
		animation: none;
		flex-wrap: wrap;
		justify-content: center;
		width: auto;
	}
}

/* Price switch: monthly is what renders without JavaScript. */
.unapp-price__yearly {
	display: none;
}

.unapp-period__to-monthly {
	display: none;
}

[data-unapp-period="yearly"] .unapp-price__yearly {
	display: inline;
}

[data-unapp-period="yearly"] .unapp-price__monthly {
	display: none;
}

[data-unapp-period="yearly"] .unapp-period__to-yearly {
	display: none;
}

[data-unapp-period="yearly"] .unapp-period__to-monthly {
	display: inline;
}

/* --------------------------------------------------------------------------
   Site Tagline in a footer brand column

   The footers show the site's own tagline when one is set, and fall back to
   the pattern's written blurb when it is not. Site Tagline is a dynamic block,
   and the style engine drops rgba() from a dynamic block's colour attribute,
   so the muted tone the blurb carries inline is applied here instead — the two
   branches then look the same.
   -------------------------------------------------------------------------- */

.wp-block-site-tagline.unapp-footer-note {
	color: rgba(255, 255, 255, 0.75);
}

/* --------------------------------------------------------------------------
   Footer bottom row on phones

   The niche footers end in an unstacked 60/40 row: copyright on the left,
   credit right-aligned. On a phone that squeezed both into two-line wraps
   (196px and 130px wide at 390, three lines at 360), so there the two stack
   and share the start edge.
   -------------------------------------------------------------------------- */

@media (max-width: 599px) {
	footer .wp-block-columns.is-not-stacked-on-mobile:has(> .wp-block-column > .has-text-align-right) {
		flex-wrap: wrap !important;
	}

	footer .wp-block-columns.is-not-stacked-on-mobile:has(> .wp-block-column > .has-text-align-right) > .wp-block-column {
		flex-basis: 100% !important;
	}

	footer .wp-block-columns.is-not-stacked-on-mobile > .wp-block-column > .has-text-align-right {
		text-align: start;
	}
}

/* Contact slot fallback: a long address such as reception@forestreetdental.example
   is one unbreakable word, which pushed the button past a phone-width card. */
.unapp-form-slot .wp-block-button__link {
	overflow-wrap: anywhere;
}

/* Logo rows: a narrow column caps the width while the height is fixed, so the
   wider marks (Northwind, Meridian) were squeezed to 147px instead of scaling. */
img[src*="/assets/images/logos/"] {
	object-fit: contain;
}

.unapp-business-profile {
	box-sizing: border-box;
	max-width: var(--wp--style--global--content-size);
	margin: var(--wp--preset--spacing--60) auto;
	padding: var(--wp--preset--spacing--50);
	border-radius: 20px;
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--contrast);
}

.unapp-business-profile p:empty {
	display: none;
}

.unapp-business-profile p:first-child {
	font-weight: 700;
}

.unapp-business-profile a {
	color: var(--wp--preset--color--primary);
	overflow-wrap: anywhere;
}

.unapp-business-profile--footer {
	margin: var(--wp--preset--spacing--30) 0 0;
	padding: 0;
	background: transparent;
}

.unapp-business-profile--footer p:first-child {
	font-weight: inherit;
}

/* Starter introductions keep copy readable beside the artwork, then give each
   action its own touch target when columns stack. Applies in the editor too. */
.unapp-starter-hero h1 {
	text-wrap: balance;
}

.unapp-starter-actions > .wp-block-button {
	min-width: 0;
}

.unapp-starter-actions .wp-block-button__link {
	min-height: 48px;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	text-wrap: balance;
}

@media (max-width: 781px) {
	.unapp-starter-hero {
		padding-block: var(--wp--preset--spacing--60) !important;
	}

	.unapp-starter-hero h1 {
		font-size: clamp(2.25rem, 8vw, 3.5rem) !important;
	}

	.unapp-client-row .has-text-align-right,
	.unapp-hours-row .has-text-align-right {
		text-align: start;
	}
}

@media (max-width: 599px) {
	.unapp-starter-actions > .wp-block-button {
		flex-basis: 100%;
		width: 100%;
	}

	.unapp-starter-actions .wp-block-button__link {
		width: 100%;
	}
}

/* Section swaps remain ordinary Columns and Group blocks in the editor. */
.wp-block-columns.is-style-unapp-section-stack {
	flex-direction: column;
	align-items: stretch;
}

.wp-block-columns.is-style-unapp-section-stack > .wp-block-column {
	flex-basis: auto !important;
	width: 100%;
}

/* Native Grid controls own the desktop count; the theme only stacks on phones. */
@media (max-width: 739px) {
	.wp-block-group.unapp-section-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}
