/*
Theme Name: smeweb.site
Theme URI: https://www.smeweb.site
Author: smeweb.site
Author URI: https://www.smeweb.site
Description: Block themes for smeweb.site
Version: 1.9.5
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 7.4
License: GNU General Public License
License URI: license.txt
Text Domain: smeweb
Tags: full-site-editing, block-patterns, block-styles, custom-colors, custom-logo, custom-menu, editor-style, translation-ready, blog, portfolio, business
*/

/*
 * Global design tokens (color, typography, spacing, layout) live in theme.json.
 * This file carries only what theme.json cannot express: interaction states,
 * a few composite components, and the Fluent Forms bridge.
 *
 * Contents
 * 1.  Base
 * 2.  Header / navigation
 * 3.  Buttons
 * 4.  Cards
 * 5.  Feature checklists
 * 6.  Marquee
 * 7.  Pricing page — hero and packages
 * 7b. Pricing hero — floating elements
 * 7c. Website templates page
 * 8.  FAQ accordion (details/summary)
 * 9.  Posts
 * 10. Footer
 * 11. Fluent Forms
 * 12. Utilities & decorations
 * 13. Accessibility & motion
 */

/* ------------------------------------------------------------------ *
 * 0. Type: Jost for Latin and figures, LINE Seed Sans TH for Thai
 * ------------------------------------------------------------------ */

/*
 * One stack, two scripts. A browser resolves font-family per character, not per
 * element: Jost carries no Thai glyphs, so Thai falls through to LINE Seed Sans TH,
 * while Latin and digits are served by Jost because it comes first. Nothing has to know
 * which language a string is in.
 *
 * Jost is self-hosted here. It was named in theme.json all along but never arrived —
 * the Google Fonts request is off (see smeweb_load_google_fonts), so every stack that
 * started with Jost was silently falling through to Anuphan, then Noto Sans Thai, then
 * the platform UI font. What looked like Jost on a Windows machine was Segoe UI.
 *
 * Two subsets of the variable font, 300-700 on one axis: latin at 26 KB and latin-ext
 * at 17 KB. unicode-range means a page only fetches the file it needs, and latin covers
 * U+0000-00FF, so the figures come from it. Cyrillic is not shipped — nothing on this
 * site is written in it.
 *
 * Self-hosted rather than switching the Google request back on: one origin, no third
 * party in the render path, and the same arrangement LINE Seed already has through the
 * font library.
 */
@font-face {
	font-family: "Jost";
	font-style: normal;
	font-weight: 300 700;
	font-display: swap;
	src: url("assets/fonts/jost-latin-ext.woff2") format("woff2");
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
	font-family: "Jost";
	font-style: normal;
	font-weight: 300 700;
	font-display: swap;
	src: url("assets/fonts/jost-latin.woff2") format("woff2");
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
 * Applied by redefining the presets rather than by restating font-family on each
 * selector that sets it.
 *
 * Global Styles — which lives in the database and outranks theme.json — declares a
 * family on body, on a, on h1 through h6, on buttons and on post titles, and every one
 * of those resolves through one of these three variables. Redefining the variables
 * reaches all of them at once, and reaches whatever the next Global Styles rule turns
 * out to be, where a list of selectors would have to be found and extended.
 *
 * html:root rather than :root, so this wins on specificity rather than on being later
 * in the cascade. It is later today; that is a fact about enqueue order, not something
 * to build on.
 *
 * The line-seed variable now leads with Jost, which reads oddly against its name. It is
 * the trade for reaching every rule from one place, and there is no case on this site
 * for Latin set in LINE Seed while Thai is not.
 */
html:root {
	--smeweb-type: "Jost", "LINE Seed Sans TH", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

	--wp--preset--font-family--body: var(--smeweb-type);
	--wp--preset--font-family--display: var(--smeweb-type);
	--wp--preset--font-family--line-seed-sans-th: var(--smeweb-type);
}
/* ------------------------------------------------------------------ *
 * 1. Base
 * ------------------------------------------------------------------ */

html {
	scroll-behavior: smooth;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: hidden;
}

/*
 * Top level sections butt against one another.
 *
 * WordPress gives every child of .wp-site-blocks a block gap:
 *
 *   :where(.wp-site-blocks) > * { margin-block-start: 1.5rem; }
 *
 * Header, main and footer are all full-bleed bands carrying their own padding,
 * so those 24px never separated anything — they only exposed a strip of page
 * background: white under the navbar, and again above the footer. Zeroed for
 * every gap rather than just the one that was noticed, because it is the same
 * seam each time.
 *
 * This is the outer half of the problem fixed inside the footer in 1.1.4; that
 * one was the same core rule applied to .smeweb-footer's own two children.
 *
 * The core selector is `:where(…) > *` — specificity (0,0,0) — so one class
 * clears it.
 */
.wp-site-blocks > * {
	margin-block-start: 0;
}

/*
 * And the same again one level in, between the sections themselves.
 *
 * `<main>` is a constrained container, so core gives each of its children
 *
 *   :root :where(.is-layout-constrained) > * { margin-block-start: 1.5rem; }
 *
 * Every top-level child of main in this theme is a full-bleed band carrying its
 * own vertical padding, so those 24px separated nothing and only showed the page
 * behind. Invisible between the bands that have no background, obvious between
 * the lavender features band and the blue clients band.
 *
 * Scoped to `main`, not to `.is-layout-constrained` at large: the same rule is
 * what spaces content *inside* a card or a section, and that spacing is wanted.
 * Element plus class is (0,1,1), against core's `:root :where(…)` at (0,1,0).
 */
main.wp-block-group > * {
	margin-block-start: 0;
}

img,
video,
svg {
	max-width: 100%;
	height: auto;
}

/*
 * Form controls take the page font.
 *
 * Browsers do not let inputs inherit font-family — they use the operating system UI
 * font instead — so a field renders in whatever the OS reaches for. In Latin that
 * passes for a while; in Thai it does not, because the fallback is a looped face and
 * the site is set in a loopless one, so the placeholder in a search box was visibly
 * a different alphabet from the label above it.
 *
 * Written for every control rather than for the field that showed it. This is a
 * default browsers get wrong, not a property of one input, and the next field added
 * anywhere would have arrived with the same fault.
 *
 * Only the family is inherited. Size stays with each control, because a plugin that
 * sizes its own fields has usually done so for a reason.
 */
input,
textarea,
select,
button {
	font-family: inherit;
}

/*
 * Running text gets room between its lines.
 *
 * Global Styles sets body to 1.3 and everything inherits it, so a paragraph at
 * 17.6px was getting 22.9px of leading. theme.json asks for 1.7 and has been
 * overruled by the database since before this stylesheet existed — this restores
 * the number the theme already wanted rather than inventing one.
 *
 * 1.3 is tight for any language and tighter for this one: Thai stacks vowels above
 * and tone marks above those, so the ascender zone is two storeys deep and the
 * descenders of the line above meet it. Latin at 1.3 looks dense; Thai at 1.3 has
 * marks nearly touching the line above.
 *
 * Applied to paragraphs and content lists, not to body. Raising body would take the
 * navigation row, the marquee band and every single-line label with it, growing the
 * header and the bands by the difference — none of which is running text and none of
 * which was asked about.
 *
 * Left alone deliberately, because each already carries its own and each is right:
 * buttons at 1.2, the step chips at 1.5, post excerpts at 1.7 from theme.json.
 * Headings stay at 1.3 as well — at 44px that is 57px of leading, which is generous
 * in absolute terms, and loosening display type would change the shape of every
 * hero on the site.
 */
p,
.smeweb-checklist li,
.smeweb-entry-content li {
	line-height: 1.7;
}

/*
 * The exceptions are the paragraphs that are not prose: a single-line label inside a
 * component sized around it. Left at the inherited value so the component keeps its
 * height.
 */
p.smeweb-tpl-count,
p.wp-block-site-title,
.smeweb-marquee p {
	line-height: 1.3;
}

/*
 * Centred standalone paragraphs get a measure.
 *
 * A section's own width is set by its widest element — a three-card grid, a
 * table — and a lone sentence centred in that space inherits it. Measured on the
 * home page, the intro under "Our Clients" ran 1200px at 17.6px type: 68em,
 * against the 30-40em a line wants. The features sub-head and closing line came
 * in at 62em, the hero's supporting sentence at 55em.
 *
 * 42em is chosen over a pixel value so the measure tracks the type: fluid sizes
 * mean the same paragraph is 14px on a phone and 19px on a desktop, and a fixed
 * max-width would be two different measures.
 *
 * Card and column copy is unaffected — those parents are already narrower than
 * 42em, so the cap never binds. Eyebrows are caught but are a few words long.
 */
.wp-block-group > p.has-text-align-center,
.wp-block-cover__inner-container > p.has-text-align-center {
	max-width: 42em;
	margin-inline: auto;
}

/*
 * Even lines, so a paragraph does not end in two words on a line of its own.
 *
 * Measured across the site before touching it, taking line widths from
 * Range.getClientRects() so these are the boxes the browser actually made. The pricing lead
 * ran 711px then 82px; the sentence under the template grid 739px then 22px; a service card
 * 292/270/52; the footer blurb 364/362/62. Thirty-four paragraphs on five pages ended on a line
 * under 55% of their longest, and a dozen under 20%.
 *
 * balance, not pretty. Both were measured on the same paragraphs and pretty moved almost
 * nothing here — 711/82 stayed 711/82, and its best result was 292/250/73 against balance's
 * 215/200/205. Chromium implements pretty as a light touch on the last lines; balance rewrites
 * the whole block, which is what a two-line lead needs.
 *
 * Safe in the way that matters: balance redistributes lines without changing how many there
 * are, so every height measured before and after was identical — no card resized, nothing
 * reflowed. Where it cannot help it does nothing: a six-line excerpt came back untouched,
 * because browsers cap balancing at a handful of lines.
 *
 * Unsupported in an older browser means the paragraph wraps exactly as it does today, so there
 * is nothing to fall back to.
 */
h1,
h2,
h3,
h4,
.wp-block-heading,
p,
.wp-block-post-excerpt__excerpt {
	text-wrap: balance;
}

/*
 * Except the body of an article, where it would be wrong rather than merely useless.
 *
 * Balancing is for a heading or a lead — a block short enough to read as one shape. Long-form
 * copy wants an even left edge and a normal rag; balancing paragraph after paragraph gives a
 * column of narrow blocks that drift away from the measure. Headings inside the article are
 * deliberately left balanced.
 *
 * wrap, not normal. text-wrap takes wrap | nowrap | balance | pretty | stable, so normal is not
 * a value it has: the first attempt was dropped as invalid and the article body stayed balanced,
 * which a computed-style check caught rather than an eye.
 */
.smeweb-entry-content p,
.smeweb-entry-content li {
	text-wrap: wrap;
}

/*
 * And except every card that clamps its text, which is the other half of the same idea.
 *
 * Balancing evens out all the lines a block has, including the ones a clamp then hides. On a
 * card that is exactly wrong: the hidden line still gets a share of the words, so the visible
 * ones come up short and the right side of the card empties out. Measured across the four-wide
 * grid, the first line of a title filled 64% of its column under balance and 96% without —
 * 211px and 251px of a 357px card against 350px and 343px.
 *
 * The cost is a last line that can land at about a third, and in a clamped card that reads as
 * normal: a title whose first line runs the full width reads as filling the card, where two
 * lines that both stop short read as the card being half empty. It is the opposite call to the
 * one above for the same reason — what the reader sees is not the whole block.
 *
 * pretty was measured here too and came out identical to wrap on every card, so there is no
 * third option to reach for.
 */
.smeweb-post-scroll .wp-block-post-excerpt__excerpt,
.smeweb-trending .wp-block-post-excerpt__excerpt,
:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-excerpt__excerpt,
:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-title a,
.smeweb-picks .wp-block-post-excerpt__excerpt,
.smeweb-picks .wp-block-post-title a {
	text-wrap: wrap;
}

/* Anchor targets clear the sticky header. */
:target {
	scroll-margin-top: 6rem;
}

:where(a):focus-visible,
:where(button):focus-visible,
:where(input, textarea, select):focus-visible,
:where(summary):focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
	border-radius: 4px;
}

/* ------------------------------------------------------------------ *
 * 2. Header / navigation
 * ------------------------------------------------------------------ */

/*
 * Sticky belongs on the template part wrapper, not on the group inside it.
 *
 * A sticky box only travels inside its own parent's box, and
 * <header class="wp-block-template-part"> is exactly as tall as the header it
 * contains — so `position: sticky` on .smeweb-header had nowhere to travel and
 * never engaged, at any scroll position. The wrapper's parent is
 * .wp-site-blocks, the whole page, which is the room the header actually needs.
 *
 * All eleven templates render this part with `tagName: header`, so one selector
 * covers every page. The footer part is a <footer>, so it is not caught.
 */
.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 100;
}

.smeweb-header {
	background-color: rgba(255, 255, 255, 0.92);
	backdrop-filter: saturate(180%) blur(12px);
	-webkit-backdrop-filter: saturate(180%) blur(12px);
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

/*
 * The header and footer bars run the width of the window rather than stopping at
 * the 1200px content measure: at this scale they read as part of the browser
 * chrome, and a logo floating 350px in from the edge of a wide window does not.
 *
 * `--smeweb-shell-inset` is the single number all of them use, so "the footer
 * lines up with the navbar" is a fact rather than a coincidence that survives
 * until someone edits one of them. It resolves to 36px at 390, 59px at 1180 and
 * 67px at 1440.
 *
 * All of this is done in the stylesheet rather than in the template part markup,
 * because both parts are overridden in the database — see 1.1.16 and 1.1.11 in
 * logs.md — so edits to parts/header.html and parts/footer.html do not reach the
 * site. A stylesheet rule does.
 */
:root {
	--smeweb-shell-inset: clamp(1.5rem, calc(1.5rem + 3vw), 5.5rem);
}

/*
 * Core gives the header 24px of root padding through `.has-global-padding`, one
 * class; zeroed here at two so the inset below is the only horizontal spacing and
 * the two do not stack.
 */
.smeweb-header.has-global-padding {
	padding-inline: 0;
}

/*
 * Core caps the row with
 *   .wp-container-core-group-is-layout-… > :where(:not(.alignleft)…)
 * which is one class, (0,1,0), against two here.
 */
.smeweb-header > .wp-block-group {
	max-width: none;
	padding-inline: var(--smeweb-shell-inset);
}

.smeweb-header .wp-block-site-logo img {
	max-height: 44px;
	width: auto;
}

/*
 * The menu sits on the centre line of the bar, not in the middle of what is left over.
 *
 * The row is three children under space-between: the logo, the menu, the two buttons.
 * space-between centres the middle child only when the outer two match, and they do not — the
 * logo is 75px and the buttons are 248px, so the menu sat exactly half of that 173px difference
 * to the left, 87px, at every width measured.
 *
 * Taking the menu out of flow is what fixes it. Balancing the sides with flex: 1 1 0 was tried
 * first and made things worse: at 1440 the two outer boxes want 234px each and the buttons
 * cannot shrink under 248, so the row overflowed and the menu wrapped — a 149px header where it
 * had been 77. Absolute positioning asks the row for no space at all, so nothing has to give.
 *
 * Percentages on an absolutely positioned child resolve against the containing block's padding
 * box, which here is the full width of the bar, so left: 50% is the real centre and not the
 * centre of the padded area.
 *
 * Only from 1480 up, and that number is a measurement, not a round one.
 *
 * The two sides are not symmetric — 75px of logo against 248px of buttons — so a menu on the true
 * centre line reaches further right than one pushed left by space-between. Below 1480 it reaches
 * into the buttons: measured 28px of overlap at 1360 and 54px at 1300, and only 10px of clearance
 * at 1440, which is touching. 1480 is the first width with a full 24px gap, the same gap the row
 * uses between its own children.
 *
 * Between 1300 and 1479 the bar keeps space-between and the menu keeps its 87px lean. That is the
 * honest trade: there is no room to centre it there without shrinking the menu or the buttons,
 * and a menu touching the login button is worse than one sitting off centre.
 *
 * Below 1300 the button takes over and the menu is in an overlay, where centring against the bar
 * would mean nothing.
 */
@media (min-width: 1480px) {
	.smeweb-header .is-content-justification-space-between {
		position: relative;
	}

	/*
	 * width: max-content is the part that actually centres it.
	 *
	 * An absolutely positioned box with left and no right shrinks to fit the space between left
	 * and the containing block's right edge — 650px at 1300, where the menu needs 787. The row is
	 * nowrap so the words overflowed the box instead of wrapping, and translateX(-50%) then shifted
	 * by half the box rather than half the words: measured still 39px off at 1300, 53 at 1360, 10 at
	 * 1440, and 0 only from 1600 up where the box happened to be wide enough.
	 *
	 * max-content sizes the box to the words whatever room is on that side, so the two halves of the
	 * shift are the same number again.
	 */
	.smeweb-header .is-content-justification-space-between > :nth-child(2) {
		position: absolute;
		left: 50%;
		width: max-content;
		transform: translateX(-50%);
	}
}
.smeweb-header .wp-block-navigation {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
}

.smeweb-header .wp-block-navigation .wp-block-navigation-item__content {
	padding-block: 0.35rem;
	border-bottom: 2px solid transparent;
	transition: color 0.18s ease, border-color 0.18s ease;
}

.smeweb-header .wp-block-navigation .wp-block-navigation-item__content:hover,
.smeweb-header .wp-block-navigation .current-menu-item > .wp-block-navigation-item__content {
	color: var(--wp--preset--color--primary);
	border-bottom-color: var(--wp--preset--color--accent);
}

/* Submenus */
.smeweb-header .wp-block-navigation .wp-block-navigation-submenu__toggle + .wp-block-navigation__submenu-container,
.smeweb-header .wp-block-navigation .wp-block-navigation__submenu-container {
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 14px;
	box-shadow: 0 18px 40px rgba(20, 20, 43, 0.12);
	padding: 0.5rem;
	background-color: var(--wp--preset--color--base);
}

.smeweb-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	border-radius: 8px;
	padding: 0.5rem 0.75rem;
	border-bottom: 0;
}

.smeweb-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
	background-color: var(--wp--preset--color--surface);
}

/* ---------------------------------------------------------------- *
 * Mobile menu — full page overlay
 * ---------------------------------------------------------------- */

/*
 * The header uses backdrop-filter, and per CSS spec an element with
 * backdrop-filter (like filter/transform) becomes the containing block for
 * its position:fixed descendants. WordPress's overlay is `position:fixed;
 * inset:0`, so it would be trapped inside the header bar rather than
 * covering the viewport. Core adds .has-modal-open to <html> while the menu
 * is open, so the filter is dropped for exactly that duration.
 */
html.has-modal-open .smeweb-header,
body.has-modal-open .smeweb-header {
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	background-color: transparent;
	border-bottom-color: transparent;
}

/* Stop the page behind the overlay from scrolling. */
html.has-modal-open,
body.has-modal-open {
	overflow: hidden;
	touch-action: none;
}

.wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--base);
	padding: 1rem var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	overflow-y: auto;
	overscroll-behavior: contain;
	animation: smeweb-menu-in 0.22s ease-out;
}

@keyframes smeweb-menu-in {
	from {
		opacity: 0;
		transform: translateY(-8px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

/* Close button sits on the same line the logo occupies in the header. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
	top: 1.15rem;
	right: var(--wp--preset--spacing--30);
	width: 2.5rem;
	height: 2.5rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--surface);
	transition: background-color 0.18s ease, color 0.18s ease;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close:hover {
	background-color: var(--wp--preset--color--accent);
	color: #fff;
}


/*
 * The navigation keeps its desktop flex layout (a right-aligned row) via
 * these custom properties, which core's own rules read. Overriding the
 * properties — rather than fighting the rules with !important — turns the
 * whole tree into a stacked column for the overlay only.
 */
.wp-block-navigation__responsive-container.is-menu-open {
	--navigation-layout-direction: column;
	--navigation-layout-justify: flex-start;
	--navigation-layout-align: stretch;
	--navigation-layout-wrap: nowrap;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-page-list {
	flex-direction: column;
	align-items: stretch;
	justify-content: flex-start;
	width: 100%;
	gap: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	padding-top: 0;
}

/* Each destination becomes a full-width row with a hairline divider. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
	width: 100%;
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	display: block;
	width: 100%;
	padding: 1.05rem 0;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	border-bottom: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover,
.wp-block-navigation__responsive-container.is-menu-open .current-menu-item > .wp-block-navigation-item__content {
	color: var(--wp--preset--color--accent-dark);
}

/* Submenus expand inline instead of floating as a dropdown card. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	border: 0;
	border-radius: 0;
	box-shadow: none;
	padding: 0 0 0 var(--wp--preset--spacing--30);
	background-color: transparent;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item {
	border-bottom: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	padding: 0.65rem 0;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
	color: var(--wp--preset--color--muted);
}

/*
 * The brand mark and CTA are inner blocks of the navigation so they appear
 * inside the overlay. The navigation renders one DOM tree for both layouts,
 * so they are hidden everywhere except in the open overlay — the header bar
 * keeps its own always-visible copy of each.
 */
/*
 * Core wraps the site-logo in an <li class="wp-block-navigation-item">, so the
 * list item itself must be hidden — hiding only the inner div would leave an
 * empty item still consuming the flex gap in the desktop bar. The buttons
 * block is NOT wrapped in an <li>; it renders as a sibling of the list, so it
 * is targeted directly.
 */
.wp-block-navigation .wp-block-navigation-item:has(.smeweb-menu-logo),
.wp-block-navigation .smeweb-menu-cta {
	display: none;
}

/*
 * Shown again inside the overlay, without the link-row divider the sibling
 * items carry. The logo stays in normal flow as the first row so it can
 * never overlap the links; the close button floats opposite it.
 */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:has(.smeweb-menu-logo) {
	display: block;
	width: 100%;
	border-bottom: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .smeweb-menu-logo {
	display: block;
	width: 100%;
	/* The desktop nav is right-justified; reset that for the overlay. */
	text-align: left;
	margin: 0 0 var(--wp--preset--spacing--40);
	padding-right: 3.5rem;
}

.wp-block-navigation__responsive-container.is-menu-open .smeweb-menu-logo .custom-logo-link {
	display: inline-block;
}

.wp-block-navigation__responsive-container.is-menu-open .smeweb-menu-logo img {
	display: block;
	max-height: 36px;
	width: auto;
	margin: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .smeweb-menu-cta {
	display: flex;
	width: 100%;
	margin-top: var(--wp--preset--spacing--40);
}

.wp-block-navigation__responsive-container.is-menu-open .smeweb-menu-cta .wp-block-button__link {
	padding-top: 1rem;
	padding-bottom: 1rem;
	font-size: var(--wp--preset--font-size--medium);
}

/* Hamburger trigger */
.wp-block-navigation__responsive-container-open {
	width: 2.5rem;
	height: 2.5rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	color: var(--wp--preset--color--primary);
	transition: background-color 0.18s ease;
}

.wp-block-navigation__responsive-container-open:hover {
	background-color: var(--wp--preset--color--surface);
}

.wp-block-navigation__responsive-container-open svg,
.wp-block-navigation__responsive-container-close svg {
	width: 1.6rem;
	height: 1.6rem;
	fill: currentColor;
}

/* Keep the header CTA from crowding the logo on narrow screens. */
@media (max-width: 599px) {
	.smeweb-header .wp-block-button__link {
		padding: 0.55rem 1.05rem;
		font-size: 0.8rem;
	}

	.smeweb-header .wp-block-site-logo img {
		max-height: 36px;
	}
}

/* ------------------------------------------------------------------ *
 * 3. Buttons
 * ------------------------------------------------------------------ */

/*
 * 18px, the same as the excerpt, and a decision with a cost — leave it alone unless the cost
 * is being revisited. On "ทั้งหมด" the tone mark sits above the vowel mark, and at 18px the
 * two rasterise into one another at DPR 1, a large monitor at 100%. 19.2px is the smallest
 * size where they separate and 18.4 still merges; magnifying the DPR-1 render 7x shows it,
 * and no weight buys them back at 18 — 500 and 400 both merge.
 *
 * line-height 1.45 rather than 1.2: a line of Thai carries more ink than a 1.2 box, and a
 * label that wraps would stack one line’s marks into the descenders above it.
 *
 * The size lives here, with the rest of the button, rather than in a rule of its own. An
 * earlier attempt to set it near the header did nothing at all — a later rule was handing
 * every button font-size: medium, which came to 19.2px on a desktop and so looked exactly
 * like the value being asked for.
 *
 * In rem since, at the same 18px for a default root. A button is a thing people have to read
 * before they can press it, so it was the worst of the five to have left in px.
 */
.wp-block-button__link {
	font-size: 1.125rem;
	font-weight: 500;
	letter-spacing: 0.01em;
	line-height: 1.45;
	transition: transform 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}

.wp-block-button__link:hover,
.wp-block-button__link:focus-visible {
	transform: translateY(-2px);
	box-shadow: 0 12px 26px rgba(20, 20, 43, 0.18);
}

.wp-block-button__link:active {
	transform: translateY(0);
	box-shadow: none;
}

/*
 * Pill button with a trailing arrow badge — the primary CTA in the design.
 *
 * Geometry is the Figma spec: inline-flex, 10px gap, and asymmetric padding
 * (6px 8px 6px 16px) that sits tight against the badge on the right, so the
 * badge — not the padding — sets the button's height.
 *
 * The spec also carried `backdrop-filter: blur(39.25px)`. Not reproduced: the
 * fill is opaque, so there is no backdrop left to blur and the declaration
 * would only cost a compositing layer. Its `border-radius: 74px` is likewise
 * left to the theme's 999px pill — past half the button's height the two
 * render identically.
 */
.wp-block-button.is-style-smeweb-arrow .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 6px 8px 6px 16px;
}

/*
 * The badge is a solid white disc with the arrow knocked out in the button's
 * own colour. The arrow has to be baked into the SVG, so there is one rule per
 * button colour rather than a single `currentColor` trick — the text is white,
 * the arrow is not. Accent (red) is the default; the blue variant on the
 * portfolio CTA overrides it below.
 */
.wp-block-button.is-style-smeweb-arrow .wp-block-button__link::after {
	content: "";
	flex: 0 0 auto;
	width: 1.9em;
	height: 1.9em;
	border-radius: 50%;
	background-color: #fff;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FF0000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M12 5l7 7-7 7'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 1em 1em;
	transition: transform 0.18s ease;
}

.wp-block-button.is-style-smeweb-arrow .wp-block-button__link.has-primary-background-color::after {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f2acd' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M12 5l7 7-7 7'/%3E%3C/svg%3E");
}

.wp-block-button.is-style-smeweb-arrow .wp-block-button__link:hover::after {
	transform: translateX(3px);
}

/*
 * Pill button with a leading document glyph — the "ดูแพ็กเกจราคา" CTA.
 * Drawn in CSS so the icon stays decorative: it never reaches the
 * accessibility tree, and the button label stays a single translatable string.
 * The stroke is hard-coded white, like is-style-smeweb-arrow above, so pair
 * this style with a filled (primary/accent) background.
 */
.wp-block-button.is-style-smeweb-doc .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
}

.wp-block-button.is-style-smeweb-doc .wp-block-button__link::before {
	content: "";
	flex: 0 0 auto;
	width: 1.2em;
	height: 1.2em;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z'/%3E%3Cpath d='M14 3v5h5'/%3E%3Cpath d='M9 13h6M9 17h4'/%3E%3C/svg%3E");
}

/* Outline button that keeps its shape on hover. */
.wp-block-button.is-style-outline .wp-block-button__link {
	border-width: 2px;
}

.wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

/* ------------------------------------------------------------------ *
 * 4. Cards
 * ------------------------------------------------------------------ */

.smeweb-card {
	height: 100%;
	transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}

.smeweb-card.is-hoverable:hover {
	transform: translateY(-6px);
	box-shadow: 0 22px 46px rgba(20, 20, 43, 0.14);
	border-color: var(--wp--preset--color--primary);
}

/*
 * Editor-selectable card style. Patterns set these values explicitly so
 * they survive in exported markup; this variant lets an editor apply the
 * same look to any group from the block sidebar.
 */
.wp-block-group.is-style-smeweb-card {
	height: 100%;
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: var(--smeweb-radius-card, 18px);
	padding: var(--wp--preset--spacing--40);
	box-shadow: var(--wp--preset--shadow--soft);
	transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}

.wp-block-group.is-style-smeweb-card:hover {
	transform: translateY(-6px);
	box-shadow: var(--wp--preset--shadow--lifted);
	border-color: var(--wp--preset--color--primary);
}

/* Make columns in a row equal height so cards line up. */
.smeweb-card-grid .wp-block-column {
	display: flex;
	flex-direction: column;
}

.smeweb-card-grid .wp-block-column > .wp-block-group {
	flex: 1 1 auto;
}

/*
 * The three feature cards share their rows, so the checklists start on the same line.
 *
 * They did not, and a min-height on the description would only have held at one width. The
 * descriptions wrap to different depths and the depth moves: measured 3/3/2 lines at 1440,
 * 3/3/3 at 1024 and 4/4/3 at 900, which put the third list 30px high at 1440 and 10px low
 * at 900. Each card lays its own children out, so nothing tied them together.
 *
 * Subgrid ties them together. The row of columns owns the four tracks — shot, title,
 * description, list — and each card borrows them, so the description track is as deep as
 * the deepest description and all three lists begin at its foot, at every width.
 *
 * Two levels of it because the card is a grandchild: core wraps every column in
 * .wp-block-column, and both levels have to pass the tracks through.
 *
 * Four tracks is the card’s child count now that Learn More is gone — figure, heading,
 * paragraph, list. Adding a fifth child to these cards means adding a track here.
 *
 * :has(.smeweb-feature-shot) because .smeweb-card-grid is shared with the services and
 * pricing rows, which have their own shapes. Above 782px only: below it core stacks the
 * columns and there is nothing left to align.
 *
 * Where subgrid is missing the declaration is dropped and each card lays itself out as it
 * does today — the section still reads, it just loses the alignment.
 */
@media (min-width: 782px) {
	.wp-block-columns.smeweb-card-grid:has(.smeweb-feature-shot) {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		grid-template-rows: auto auto auto auto;

		/*
		 * row-gap: 0 or the spacing lands twice. The columns block carries blockGap 40, which
		 * core writes as `gap` — harmless while the row was flex and it only had one line, but
		 * as a grid it falls between all four tracks as well, on top of the margins the card’s
		 * own constrained layout already puts between its children. It measured: the cards went
		 * from 964 to 1078 tall, and only 37px of that was the dividers.
		 */
		row-gap: 0;
	}

	.smeweb-card-grid:has(.smeweb-feature-shot) > .wp-block-column,
	.smeweb-card-grid:has(.smeweb-feature-shot) > .wp-block-column > .smeweb-card {
		display: grid;
		grid-row: span 4;
		grid-template-rows: subgrid;
	}
}

/*
 * Feature card artwork sits in a portrait window, as in the design, rather than
 * at the source image's own proportions. The three uploads are square, so a
 * fixed window is what keeps the three cards sharing one silhouette — otherwise
 * a replacement image of another shape would knock the row out of alignment.
 *
 * 4:5 rather than the design's tighter crop: the squares are screenshots, and
 * anchoring to the top while trimming a fifth keeps the part that carries the
 * meaning. Scoped to its own class because .smeweb-card-grid is shared with the
 * pricing and services grids, whose images are not meant to be cropped.
 */
.smeweb-feature-shot img {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: top center;
	width: 100%;
}

/*
 * The glyph at the top of a service card — no tile behind it, per the comp.
 *
 * It was a 48px red tile with the glyph knocked out in white. The comp shows the
 * glyph on its own in the brand red, so the box, its radius and its background all
 * go, and the mask below paints in `currentColor` instead of white.
 *
 * With the tile gone the hover lift and red glow went too — they were the tile
 * responding, and the card now answers a hover with its own gradient ring.
 *
 * The glyph is a graphic rather than text, so the 3.0 of WCAG AA applies to it and
 * not the 4.5: #FF0000 on white measures 4.00, which clears that. Ironically this
 * reads better than the white-on-red tile it replaces, which measured the same 4.00
 * against a threshold of 4.5.
 */
.smeweb-service-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--wp--preset--color--accent);
}

/*
 * The six pricing service icons, delivered through the stylesheet.
 *
 * patterns/services.php holds the right icons and reaches the server, but the
 * pricing page on the live site renders a copy of that file as it stood at 1.1.27,
 * flattened into the database. Proven, not assumed: the theme there reports 1.1.30
 * and the page requests style.css?ver=1.1.30 — which also clears the pattern
 * transient, since WP_Theme::get_block_patterns() keys it on the version — while
 * the markup still carries viewBox="0 0 24 24", and the HTML is not cached
 * (cf-cache-status: DYNAMIC, no age). Rendered output older than every file that
 * could produce it has one remaining source.
 *
 * Clearing that override is the obvious repair and is the wrong move here. The
 * database copy carries eight edited lines of package specification — storage from
 * 2/4/20 GB against the pattern's 5/30/50, one page against ten — which are terms
 * of sale someone set deliberately. Resetting the template would overwrite them to
 * win back an icon. Images and prices were compared too and are identical, so this
 * is the whole of what is at stake, and it is enough.
 *
 * So the glyphs arrive as masks over the markup that is actually there. Two costs:
 *
 *   - Markup and rendering disagree. View source shows the old glyph; the screen
 *     shows the new one.
 *   - The icons are positional. Each is bound to the column a card sits in rather
 *     than to the card, so reordering the cards reorders the icons.
 *
 * Delete this whole block if the override is ever cleared — after the eight package
 * lines are back. The pattern's own icons take over and nothing else changes: the
 * same six shapes at the same size, from the same source. On staging, where the
 * pattern does render, this block hides the correct inline glyph and paints an
 * identical one over it, which is harmless and still redundant.
 *
 * :has() keeps the third grid on the page out of this — the package table, same
 * class, no service icons. Both icon grids are siblings, so the second is reached
 * as "a grid preceded by a grid", and that extra compound is what gives rows four
 * to six the specificity to override rows one to three.
 */
.smeweb-card-grid:has(.smeweb-service-icon) .smeweb-service-icon > svg {
	display: none;
}

.smeweb-card-grid:has(.smeweb-service-icon) .smeweb-service-icon::after {
	content: "";
	width: 34px;
	height: 34px;
	background-color: currentColor;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

/* Web Design, WordPress Development, SEO Search. */
.smeweb-card-grid:has(.smeweb-service-icon) > .wp-block-column:nth-child(1) .smeweb-service-icon::after {
	-webkit-mask-image: url("assets/images/service-icon-01.svg");
	mask-image: url("assets/images/service-icon-01.svg");
}
.smeweb-card-grid:has(.smeweb-service-icon) > .wp-block-column:nth-child(2) .smeweb-service-icon::after {
	-webkit-mask-image: url("assets/images/service-icon-02.svg");
	mask-image: url("assets/images/service-icon-02.svg");
}
.smeweb-card-grid:has(.smeweb-service-icon) > .wp-block-column:nth-child(3) .smeweb-service-icon::after {
	-webkit-mask-image: url("assets/images/service-icon-03.svg");
	mask-image: url("assets/images/service-icon-03.svg");
}
/* Faster Performance, Real-Time Dashboards, Drag & Drop. */

.smeweb-card-grid:has(.smeweb-service-icon) ~ .smeweb-card-grid:has(.smeweb-service-icon) > .wp-block-column:nth-child(1) .smeweb-service-icon::after {
	-webkit-mask-image: url("assets/images/service-icon-04.svg");
	mask-image: url("assets/images/service-icon-04.svg");
}
.smeweb-card-grid:has(.smeweb-service-icon) ~ .smeweb-card-grid:has(.smeweb-service-icon) > .wp-block-column:nth-child(2) .smeweb-service-icon::after {
	-webkit-mask-image: url("assets/images/service-icon-05.svg");
	mask-image: url("assets/images/service-icon-05.svg");
}
.smeweb-card-grid:has(.smeweb-service-icon) ~ .smeweb-card-grid:has(.smeweb-service-icon) > .wp-block-column:nth-child(3) .smeweb-service-icon::after {
	-webkit-mask-image: url("assets/images/service-icon-06.svg");
	mask-image: url("assets/images/service-icon-06.svg");
}

/*
 * Service cards, from the supplied comp.
 *
 * Scoped by the same :has() as the masks above, so the two service grids are
 * reached while the package table below and the home page feature cards — which
 * share .smeweb-card — keep what they have.
 *
 * border-radius is the one !important here. The flattened markup carries
 * `border-radius:18px` as an inline style and nothing short of !important outranks
 * an inline declaration. The shadow needs no such help: the copy in the database
 * predates the block's shadow attribute, so these cards render with
 * `box-shadow: none` today — measured in the browser, not assumed — and an ordinary
 * rule is enough.
 */
.smeweb-card-grid:has(.smeweb-service-icon) .smeweb-card {
	position: relative;
	border-radius: 10px !important;
	background-color: var(--wp--preset--color--base);
	box-shadow: 0 4px 20px 9px rgba(84, 90, 255, 0.08);
}

/*
 * Hover is a gradient ring, #1725CC into #FF0000.
 *
 * Both ends are written as literals because that is how the pair was specified.
 * The red end equals `accent`, but #1725CC is near the theme's `primary` (#1f2acd)
 * without being it, so naming one as a token and the other as a hex would suggest a
 * relationship that is not there.
 *
 * Drawn with the mask-composite ring the theme already uses for
 * .smeweb-gradient-border. `inset: -1px` lays it over the 1px outline the markup
 * carries, so that grey edge is covered rather than showing as a second ring just
 * outside this one.
 */
.smeweb-card-grid:has(.smeweb-service-icon) .smeweb-card.is-hoverable::before {
	content: "";
	position: absolute;
	inset: -1px;
	border-radius: 11px;
	padding: 2px;
	background: linear-gradient(135deg, #1725CC 0%, #FF0000 100%);
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask-composite: exclude;
	opacity: 0;
	transition: opacity 0.22s ease;
	pointer-events: none;
}

.smeweb-card-grid:has(.smeweb-service-icon) .smeweb-card.is-hoverable:hover::before {
	opacity: 1;
}

/*
 * The shared hover shadow is ink-tinted and would read as a different family
 * beside the blue one above, so these cards deepen their own instead. The lift is
 * left as it was.
 */
.smeweb-card-grid:has(.smeweb-service-icon) .smeweb-card.is-hoverable:hover {
	box-shadow: 0 10px 28px 9px rgba(84, 90, 255, 0.14);
}

/*
 * Gradient hairline border (red → blue) used on the trending post card — and on the site card in
 * the account area, which was asked to carry the same stroke.
 *
 * That card drew its own before: a 1px ring at 180deg from blue to red, built from two
 * backgrounds with background-origin doing the work. Sharing this rule is what makes the two
 * equal rather than similar — 2px, 115deg, accent into primary, on a 22px corner — and it retires
 * the last gradient ring in the stylesheet built from two stacked backgrounds. background-origin
 * is still used once, on a button further up this file, where it is doing a different job.
 */
.smeweb-gradient-border,
.smeweb-mysite__card--site,
.smeweb-account-body .fct-customer-dashboard-subscriptions-inner,
.wp-block-group.is-style-smeweb-gradient-border {
	position: relative;
	border-radius: 22px;
	background-color: var(--wp--preset--color--base);
}

.smeweb-gradient-border::before,
.smeweb-mysite__card--site::before,
.smeweb-account-body .fct-customer-dashboard-subscriptions-inner::before,
.wp-block-group.is-style-smeweb-gradient-border::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	padding: 2px;
	background: linear-gradient(115deg, var(--wp--preset--color--accent) 0%, var(--wp--preset--color--primary) 100%);
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask-composite: exclude;
	pointer-events: none;

	/*
	 * Above the content, not behind it.
	 *
	 * Both this and the card’s children are positioned at z-index auto, so they paint in tree
	 * order and anything positioned later covers the ring. It went unnoticed while every card
	 * kept a padding that held its content clear of the edge; the moment the trending picture
	 * was allowed to reach the frame it painted straight over the hairline down the left side.
	 * Sampled at the card’s left edge: photo greys where the gradient should have been.
	 */
	z-index: 1;
}

/* ------------------------------------------------------------------ *
 * 5. Feature checklists
 * ------------------------------------------------------------------ */

.smeweb-checklist,
ul.is-style-smeweb-check,
ul.is-style-smeweb-check-blue,
ul.is-style-smeweb-check-light,
ul.is-style-smeweb-check-badge {
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * Put the gap back above a checklist inside a feature card, and then some.
 *
 * The reset above sets `margin: 0` through `ul.is-style-smeweb-check`, a class
 * plus a type selector, which outranks the card's own block-gap rule
 * (`.wp-container-… > * + *`, one class). The result was a description running
 * straight into the first bullet with no separation at all. spacing-40 rather
 * than restoring the card's spacing-30 rhythm: the list is dense — four x-small
 * items with tight leading — so it reads better as a distinct block than as one
 * more line of the paragraph.
 *
 * Scoped to .smeweb-card, which the pricing table's cards do not use: they are
 * .smeweb-package and keep their own tighter spacing.
 */
.smeweb-card .smeweb-checklist {
	margin-block-start: var(--wp--preset--spacing--40);
}

.smeweb-checklist li {
	position: relative;

	/*
	 * 2.15rem, up from 1.85. The mark grew by 4.3px and this grew by 4.8, which holds the gap
	 * between mark and text at the 14.5px it already was — grow one without the other and the
	 * tick crowds the sentence instead of labelling it.
	 */
	padding-left: 2.15rem;
	margin-bottom: 0.7rem;
	line-height: 1.65;
}

/*
 * A rule between the items of a feature checklist.
 *
 * outline (#e4e0f0) rather than a grey of its own: it is the line already drawn around
 * these cards, so the divider reads as part of the card and not as a new colour.
 *
 * On the foot of each item but the last, not the head of each but the first — and that is
 * the whole reason the marks were sitting high. It was written as padding-top on li + li,
 * which pushed the text down 11.2px while the mark stayed pinned to the top of the item,
 * so the first item looked right and the other three did not. A padding-bottom leaves the
 * top of every item alone.
 *
 * padding-bottom matches the 0.7rem margin already below, so the line sits midway between
 * two items rather than against either.
 *
 * Scoped to the feature cards. The pricing tables draw their own rows and the checklists on
 * dark bands would show the line as a scratch.
 */
.smeweb-card:has(.smeweb-feature-shot) .smeweb-checklist li:not(:last-child) {
	border-bottom: 1px solid var(--wp--preset--color--outline);
	padding-bottom: 0.7rem;
}

/*
 * The mark is the uploaded check-mark, worn as a mask rather than painted as an image.
 *
 * As a background-image the colour comes from the file, and this mark has three colours to
 * be — red on white, blue on the pale surfaces, white on the dark bands — so it would have
 * meant three uploads to keep in step. Masked, the file supplies the shape and
 * background-color supplies the colour, so the three variants below are one line each.
 *
 * top: 0.14em, measured rather than guessed. The mark and the first line of text were
 * sampled out of the render and their ink compared: at 0.14em both centre on 9.25px, and
 * each 0.06em above that pushes the mark 1px low. Ink rather than boxes, because Thai tone
 * marks and descenders stretch the font box past what the eye reads as the line.
 *
 * The file is 24px square with its ink filling 20 of that. The old drawing filled 11 of 24,
 * so at the same box this renders close to twice the weight — which is the mark that was
 * asked for, not a scaling mistake.
 *
 * The 24px source is now the limit rather than a footnote. At 1.35em the box is 19.4px, so
 * a 2x screen wants 39px of ink out of a 24px file and softens it. Re-export the tick at
 * 64px square and nothing here has to change — the mask scales to the box either way.
 */
.smeweb-checklist li::before {
	content: "";
	position: absolute;
	left: 0;

	/*
	 * top follows the size, and it has to. mask-size: contain centres the ink in the box, so
	 * growing the box from 1.05em to 1.35em drops the ink half the difference — 2.15px at this
	 * text size. The 0.14em that centred the old mark would now sit it that much low, which is
	 * why this is 0 rather than left alone.
	 */
	top: 0;
	width: 1.35em;
	height: 1.35em;
	background-color: var(--wp--preset--color--accent);

	/*
	 * These two are still here for the badge variant below, which is the one mark that stays
	 * a painted image. Dropping them tiled its tick into the corner of the disc.
	 */
	background-repeat: no-repeat;
	background-position: center;

	-webkit-mask-image: url("../../uploads/2026/08/check-mark-1.png");
	mask-image: url("../../uploads/2026/08/check-mark-1.png");
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

/* Blue check on light-blue surfaces, white check on dark surfaces. */
.smeweb-checklist.is-style-smeweb-check-blue li::before {
	background-color: var(--wp--preset--color--primary);
}

.smeweb-checklist.is-style-smeweb-check-light li::before {
	background-color: #fff;
}

/*
 * Round check badge used inside pricing cards.
 *
 * Left on its own drawing on purpose. This mark is a filled disc with the tick knocked out
 * of it, so the mask above would cut the disc away and leave the tick alone — the disc is
 * background, and a mask does not know one from the other. mask-image: none puts it back.
 */
.smeweb-checklist.is-style-smeweb-check-badge li::before {
	-webkit-mask-image: none;
	mask-image: none;
	top: 0.2em;
	width: 1.3em;
	height: 1.3em;
	border-radius: 50%;
	background-color: var(--wp--preset--color--primary);
	background-size: 0.8em 0.8em;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.6 9 17.6 20 6.6'/%3E%3C/svg%3E");
}

.smeweb-checklist.is-style-smeweb-check-badge li {
	padding-left: 2.1rem;
}

/* ------------------------------------------------------------------ *
 * 5b. Signup form (FluentAuth)
 * ------------------------------------------------------------------ */

/*
 * The registration form arrives unstyled — browser defaults, which on this site means 13.3px
 * text, a 2px grey system border and square corners against a page set in 17.6px.
 *
 * The numbers here are not invented: they are read off the contact form, which is the site’s
 * other form and already carries the design. 55px tall, 10px corners, a 1px outline border on
 * the surface tint, 17.6px text, and a pill for the submit in brand blue. Two forms that look
 * like the same site.
 *
 * Scoped on the plugin’s own fls_ classes rather than on the page, so the login and password
 * reset forms get it too wherever they are used.
 *
 * Every selector carries the wrapper class as well, and it has to. The plugin styles its
 * inputs as `.fls_registration_wrapper .fls_registration_form input` — two classes and an
 * element, the same weight as the obvious selector here — and its stylesheet is enqueued
 * after the theme’s, so it won on source order alone: the border and the tint took, and
 * the padding and the whole submit button did not. Measured, not assumed: computed padding
 * read the plugin’s 10px and the button stayed 5px of its own blue.
 */
.fls_registration_wrapper,
.fls_login_form_wrapper {
	max-width: none;
}

.fls_registration_fields,
.fls_login_form_wrapper .fls_login_fields {
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.fls_registration_wrapper .fls_field_label {
	margin-bottom: 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
}

/*
 * Every input, by type rather than by class: the plugin puts no class of its own on them, and
 * naming the types is what keeps the hidden nonce fields out of it.
 */
.fls_registration_wrapper .fls_registration_form input[type="text"],
.fls_registration_wrapper .fls_registration_form input[type="email"],
.fls_registration_wrapper .fls_registration_form input[type="password"],
.fls_login_form_wrapper .fls_login_form input[type="text"],
.fls_login_form_wrapper .fls_login_form input[type="email"],
.fls_login_form_wrapper .fls_login_form input[type="password"] {
	width: 100%;
	padding: 0.85rem 1.1rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--surface);

	/*
	 * #8d86a8, and the number is the point of it.
	 *
	 * The comp draws these fields without a border, and measured that way the boundary came to
	 * 1.09:1 against the card — the tint alone. WCAG asks 3:1 for the edge of a control, and
	 * 1.09 is close enough to nothing that on a bright screen the card reads as five labels
	 * with no boxes under them. This is the lightest lavender-grey that clears it: 3.44:1.
	 * #9a93b5, one step lighter and closer to the comp, measures 2.91 and does not.
	 *
	 * It is heavier than the comp. That is the trade, and it is the accessible side of it.
	 */
	border: 1px solid #8d86a8;
	border-radius: 10px;
	box-shadow: none;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.fls_registration_wrapper .fls_registration_form input:focus,
.fls_login_form_wrapper .fls_login_form input:focus {
	outline: none;
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.12);
}

.fls_registration_wrapper .fls_registration_form input::placeholder,
.fls_login_form_wrapper .fls_login_form input::placeholder {
	color: var(--wp--preset--color--muted);
}

/*
 * The submit is the site’s pill, not the plugin’s 5px rounded rectangle in its own #0275ff.
 *
 * !important on the four properties the plugin also sets, and only those. Its rule is
 * .fls_registration_wrapper .fls_registration_form #fls_submit — an id and two classes, one
 * class heavier than the selector here — so specificity alone loses. An important declaration
 * outranks a non-important one whatever the weight, which is the cheapest way through and
 * leaves the selector readable instead of stacking classes to out-count a plugin.
 */
.fls_registration_wrapper #fls_submit,
.fls_login_form_wrapper .fls_login_form button[type="submit"] {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	width: 100%;
	margin-top: var(--wp--preset--spacing--20);
	padding: 0.85rem 2rem !important;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small) !important;
	font-weight: 500;
	color: var(--wp--preset--color--base) !important;
	background-color: var(--wp--preset--color--primary) !important;
	border: 0;
	border-radius: 999px !important;
	cursor: pointer;
	transition: background-color 0.18s ease;
}

.fls_registration_wrapper #fls_submit:hover,
.fls_login_form_wrapper .fls_login_form button[type="submit"]:hover {
	background-color: var(--wp--preset--color--primary-dark) !important;
}

/*
 * The Google button sits under a rule of its own rather than against the submit. The plugin
 * draws no separator, and without one the two read as a pair of equal choices.
 */
.fls_registration_wrapper + .fm_login_with,
.fm_login_with {
	margin-top: var(--wp--preset--spacing--40);
	padding-top: var(--wp--preset--spacing--40);
	border-top: 1px solid var(--wp--preset--color--outline);
}

.fm_login_with .fm_buttons_wrap {
	display: flex;
	justify-content: center;
}

/*
 * The signup screen, to the second comp.
 *
 * The sides swap from the first one: the wash and the mark are on the left now, the form on
 * white on the right. No card either — the fields sit straight on the white, which is why the
 * boundary on them carries the whole job of showing where to type.
 *
 * No header and no footer, which is why templates/page-register.html exists. The mark links
 * home, and that is the way back.
 */
.smeweb-auth-page {
	display: grid;
	grid-template-columns: 1fr 1fr;
	min-height: 100vh;
	min-height: 100dvh;
}

/*
 * The left half: the supplied wash, the mark centred on it, the ribbon across the lower half
 * and the line at the foot.
 *
 * The wash is the uploaded artwork rather than the gradient token it stood in for. Shipped as
 * WebP: the upload is a 954x1177 PNG at 567KB, and the same picture at q85 is 38KB — a 93%
 * saving with a maximum channel difference of 5 and 0.01% of channels off by more than 3,
 * measured against the PNG.
 *
 * cover, and centred: the artwork is 0.81:1 and this panel is nearer 0.72:1 on a desktop, so
 * something has to be cropped and the middle is where the colour is.
 */
.smeweb-auth-brand {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	/*
	 * The extra room underneath is what lifts the mark off the ribbon.
	 *
	 * Centring put it at the middle of a 1000px panel, 415–585, and the ribbon’s stroke crossed
	 * straight through that — measured on the render, not guessed. A deeper bottom padding moves
	 * the centre of what is being centred up: the mark lands near 39% down, which is where the
	 * comp has it, and the ribbon has the band below to itself.
	 *
	 * A percentage on padding-bottom resolves against the width, not the height. 30% of a 720px
	 * column is 216px, so it scales with the column rather than the viewport — which is the
	 * behaviour wanted here, since the ribbon is sized off the width too.
	 */
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--50) 30%;
	background-image: url("assets/img/auth-bg.webp");
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	overflow: hidden;
}

/*
 * The ribbon.
 *
 * Left as a PNG, which is the one place in this theme where that is the right answer: it is a
 * single flat red on transparency, which is what PNG compresses best. 11KB as it stands
 * against 15KB re-encoded as WebP at q92 — measured, and the conversion was dropped when the
 * numbers came back the wrong way round.
 *
 * Wider than the panel and pulled left, because the comp has it running off that edge. The
 * aspect ratio is the file's own 1037:534, so the curve keeps its shape at any width, and
 * overflow on the panel above is what cuts it off cleanly.
 */
.smeweb-auth-brand::after {
	content: "";
	position: absolute;
	/*
	 * Pushed right and left to run off the right edge, which is what the comp does with it.
	 *
	 * The band starts at the panel’s left edge — it is already cut off in the file itself, so
	 * left: 0 puts that cut on the border — and at 110% the box reaches 792px of a 720px column,
	 * so the curl at the far end lands past the edge and is clipped. An earlier pass narrowed it
	 * to 100% to show the tail whole; this comp shows it cut instead, so it is wider again.
	 *
	 * bottom follows the width. Widening makes it taller (aspect-ratio does the sizing), and at
	 * 12% the top of the box climbed back to 435 against a mark ending at 509. 6% puts the ink
	 * back at 579, which is 70px clear.
	 */
	left: 0;
	width: 110%;
	bottom: 8%;
	aspect-ratio: 1037 / 534;
	background-image: url("assets/img/auth-wave.png");
	background-size: 100% 100%;
	background-repeat: no-repeat;
	pointer-events: none;
}

/* The mark and the line sit over the ribbon, not under it. */
.smeweb-auth-brand .wp-block-site-logo,
.smeweb-auth-tagline {
	position: relative;
	z-index: 1;
}

.smeweb-auth-brand .wp-block-site-logo {
	width: min(290px, 80%);
}

/*
 * The link in between has to become a block. Core wraps the mark in an inline
 * <a class="custom-logo-link">, which shrinks to its content, so the picture’s width: 100%
 * resolved against the file’s own 143px rather than the figure.
 */
.smeweb-auth-brand .wp-block-site-logo a {
	display: block;
}

.smeweb-auth-brand .wp-block-site-logo img {
	width: 100%;
	height: auto;
}

/*
 * At the foot of the panel, out of flow.
 *
 * An auto top margin would have done it, but an auto margin on the last flex item eats the
 * free space the centring needs — measured, the mark ended up at y=149 of a 1000px panel
 * instead of the middle. Taking the line out of flow lets the mark have the whole column to
 * centre in.
 */
.smeweb-auth-tagline {
	position: absolute;
	left: var(--wp--preset--spacing--50);
	right: var(--wp--preset--spacing--50);
	bottom: var(--wp--preset--spacing--50);
	margin: 0;
	font-weight: 500;
	line-height: 1.5;
	color: var(--wp--preset--color--contrast);
}

/* The right half is plain white in this comp, not the wash. */
.smeweb-auth-panel {
	display: flex;
	flex-direction: column;
	justify-content: center;

	/*
	 * No horizontal padding, because the measure below is a percentage of this panel and it has
	 * to mean the panel rather than whatever is left after padding.
	 */
	padding: clamp(2rem, 5vw, 5rem) 0;
	background-color: var(--wp--preset--color--base);
}

/*
 * One column, one left edge.
 *
 * Everything here was centred at a different width: the headline shrank to its text at 334px,
 * the line under it to 525, and the form sat at 500 because the plugin caps its wrapper there.
 * Three centred boxes of three widths means three left edges, and the comp has them all on one.
 *
 * The centring was not asked for either. Core gives every child of a constrained layout
 * margin-inline: auto, and an auto margin on the cross axis of a flex column does not just
 * centre the item — it stops it stretching, which is what shrank the headline to its text.
 *
 * 64% is read off the comp: its form column is 320 of a 504px panel. Being a percentage it
 * holds that proportion as the window changes rather than stranding the form in the middle of
 * a wide panel, and 620px caps it before the lines get too long to read.
 */
.smeweb-auth-panel > * {
	width: 64%;
	max-width: 620px;
	margin-inline: auto;
}

.smeweb-auth-title,
.smeweb-auth-lede {
	margin: 0;
	line-height: 1.35;
	color: var(--wp--preset--color--primary);
}

/*
 * One step down from the headline.
 *
 * Both were x-large, which read as two competing headlines — and once the column narrowed to
 * 64% the second one wrapped to three lines. At large it fits on one and the pair reads as a
 * title with a line under it, which is what it is.
 */
.smeweb-auth-lede {
	margin-bottom: 0;
	font-weight: 600;
}

/*
 * The consent line sits close under the headline pair.
 *
 * It was 72px clear, which is more than the gap between the headline and its own second line,
 * and read as a separate block rather than a note belonging to the form.
 *
 * Two boxes stack between the two: post-content prints an .entry-content around the shortcode,
 * and the plugin's wrapper is inside that. Core gives .entry-content margin-block-start: 1.5rem
 * as a child of a constrained layout, and the 24 the wrapper had of its own landed under it —
 * flex margins do not collapse, so 24 and 24 measured 48. The number lives on .entry-content
 * now, which is the box that actually follows the headline, and the wrapper adds nothing.
 */
.smeweb-auth-panel > .entry-content {
	margin-top: var(--wp--preset--spacing--30);
}

/* Both wrappers, for the same reason: the gap belongs to .entry-content above them, once. */
.smeweb-auth-panel .fls_registration_wrapper,
.smeweb-auth-panel .fls_login_wrapper,
.smeweb-auth-panel .fls_reset_pass_wrapper {
	margin-top: 0;
}

/* The plugin caps all three at 500px, narrower than the column they sit in. */
.smeweb-auth-panel .fls_reset_pass_wrapper {
	max-width: none;
}

/* The name in the brand red, as the comp has it. */
.smeweb-auth-title__brand {
	color: var(--wp--preset--color--accent);
}

/*
 * The order the reader gets, which is not the order the markup arrives in.
 *
 * The plugin builds the wrapper as form-then-whatever-the-filters-appended, so the consent
 * line, the rule and the Google button are all siblings after the form. The comp wants consent,
 * Google, rule, fields. order: on a flex column is what puts them there without moving a line
 * of anyone else’s markup.
 */
.smeweb-auth-panel .fls_registration_wrapper {
	display: flex;
	flex-direction: column;

	/* The plugin caps this at 500px, which is narrower than the column it now sits in. */
	max-width: none;
}


/*
 * The container is nothing now — the button inside it carries the whole look.
 *
 * It used to be a pill with a border of its own, because what sat inside was Google's iframe
 * button with its own border, and the two read as a button inside a button. With One Tap off on
 * this page (see smeweb_auth_no_one_tap) what is inside is the plugin's own anchor, and that is
 * what gets dressed.
 */
.smeweb-auth-panel .fm_login_with {
	box-sizing: border-box;
	order: 2;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
}

/*
 * The button itself, to the numbers off the Figma inspector: 16px of padding, 80px corners, a
 * 1px #DEDEDE edge on white, and stretched to the column.
 *
 * The gap is not the sheet's. Figma has 33px between the mark and the words, which centred as a
 * pair reads as two things rather than one label with its logo. 0.75rem is what the marquee
 * icons were brought to for the same reason.
 */
.smeweb-auth-panel .fs_auth_btn {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.75rem;
	box-sizing: border-box;
	width: 100%;
	padding: 16px;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	background: #fff;
	border: 1px solid #dedede;
	border-radius: 80px;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.smeweb-auth-panel .fs_auth_btn:hover {
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.08);
}

/* The mark is a 24px SVG in the markup; it keeps that size whatever the text does. */
.smeweb-auth-panel .fs_auth_btn svg {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
}

/*
 * The same edge and ground as the rule above, at one class more weight.
 *
 * The plugin sets a near-black border on .fs_auth_btn from a stylesheet printed after the
 * theme's, so at equal weight it won and the button came out with a #23292f edge instead of
 * the #DEDEDE on the sheet. Three classes settles it without !important.
 */
/*
 * margin-bottom zeroed with the rest: the plugin leaves 10px under the button, which is added
 * to the 24 below the wrapper and made one gap 34 where the other was 24.
 */
.smeweb-auth-panel .fm_login_with .fs_auth_btn {
	margin-bottom: 0;
	color: var(--wp--preset--color--contrast);
	background: #fff;
	border: 1px solid #dedede;
}

.smeweb-auth-panel .fm_login_with .fs_auth_btn:hover {
	border-color: var(--wp--preset--color--primary);
}

/*
 * Not flex here. The plugin centres the button in this wrapper, and a centred flex item does
 * not stretch — the button came out 318px inside a 461px column, so its left edge missed the
 * one every field above it shares. As a block the width: 100% below is the column.
 */
.smeweb-auth-panel .fm_login_with .fm_buttons_wrap {
	display: block;
}

/* A rule with the label sitting in the gap, drawn from the line either side of the words. */
.smeweb-auth-panel .smeweb-auth-or {
	order: 3;
	display: flex;
	align-items: center;
	gap: 1rem;
	margin: var(--wp--preset--spacing--30) 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
}

.smeweb-auth-panel .smeweb-auth-or::before,
.smeweb-auth-panel .smeweb-auth-or::after {
	content: "";
	flex: 1 1 auto;
	height: 1px;
	background-color: var(--wp--preset--color--outline);
}

.smeweb-auth-panel .fls_registration_form {
	order: 4;
}

/*
 * 2rem between fields, and the group's own margin zeroed so the gap is one number.
 *
 * It measured 49px: 24 of grid gap, 15 of margin the plugin puts under each group, and the
 * rest from the wrap inside. Against a 59px field that is a ratio of 0.83, where the comp sits
 * near 0.59 — the fields read as separate things rather than one block. 32px brings it to 0.54.
 */
.smeweb-auth-panel .fls_registration_fields {
	display: grid;
	gap: 2rem;
}

/*
 * !important, because the plugin sets this at the same weight and prints after the theme. The
 * 15px it puts under every group is added to the grid gap rather than replacing it, so the two
 * together came to 47px between boxes where the gap said 32.
 */
.smeweb-auth-panel .fls_registration_wrapper .fls_field_group {
	margin-bottom: 0 !important;
}

/*
 * The field, to the numbers off the Figma inspector: 60px tall, 0 20px of padding, 10px
 * corners, #F9F9FF, laid out as flex with space-between so the placeholder and the reveal
 * button sit at opposite ends.
 *
 * The box moved from the input to the wrap around it, and that is what makes the spec
 * reachable. space-between needs two children in one flex container, and the plugin gives
 * exactly that — the input and the button injected beside it — so the wrap becomes the field
 * and the input becomes its text. It also ends the reveal button being positioned on top of a
 * padding reserved for it, which is what the old rule did.
 *
 * One number worth saying out loud: #F9F9FF against white is about 1.04:1. WCAG asks 3:1 for
 * the edge of a control, and 1.2.119 had put a #8d86a8 border here at 3.44 for exactly that
 * reason. The Figma sheet shows no border, so the border is gone and the spec is what is
 * built. Putting it back is one line — see the focus rule below for where it would go.
 *
 * On the login page the box is the <p> wp_login_form() wraps each field in. It holds a label
 * and an input, the label is hidden, and what is left is the same two-child flex container the
 * signup wrap is — so the same numbers apply without a second copy of them.
 */
.fls_registration_wrapper .fs_input_wrap,
.fls_reset_pass_wrapper .fs_input_wrap,
.fls_login_wrapper .login-username,
.fls_login_wrapper .login-password {
	display: flex;
	justify-content: space-between;
	align-items: center;
	box-sizing: border-box;
	height: 60px;
	padding: 0 20px;
	background-color: #f9f9ff;

	/* Transparent, so the focus ring below has a border to colour rather than adding one. */
	border: 1px solid transparent;
	border-radius: 10px;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

/*
 * focus-within, not focus: what the eye reads as the field is the wrap now, and the thing
 * being focused is the input inside it.
 */
.fls_registration_wrapper .fs_input_wrap:focus-within,
.fls_reset_pass_wrapper .fs_input_wrap:focus-within,
.fls_login_wrapper .login-username:focus-within,
.fls_login_wrapper .login-password:focus-within {
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.12);
}

/*
 * The input is the text inside the field, with none of the field's own decoration left on it.
 *
 * flex: 1 0 0 is the Figma value. margin: 0 is not cosmetic — the plugin puts a 10px top
 * margin on every input, which used to land on top of the grid gap and made 32px measure 42.
 */
.fls_registration_wrapper .fls_registration_form input[type="text"],
.fls_registration_wrapper .fls_registration_form input[type="email"],
.fls_registration_wrapper .fls_registration_form input[type="password"],
.fls_reset_pass_wrapper .fls_reset_pass_form input[type="text"],
.fls_login_wrapper form#loginform input.input {
	flex: 1 0 0;
	width: auto;
	min-width: 0;
	height: 100%;
	margin: 0;
	padding: 0;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	color: var(--wp--preset--color--contrast);
	background-color: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
}

.fls_registration_wrapper .fls_registration_form input:focus,
.fls_reset_pass_wrapper .fls_reset_pass_form input:focus,
.fls_login_wrapper form#loginform input.input:focus {
	outline: none;
	box-shadow: none;
}

.fls_registration_wrapper .fls_registration_form input::placeholder,
.fls_reset_pass_wrapper .fls_reset_pass_form input::placeholder,
.fls_login_wrapper form#loginform input.input::placeholder {
	color: var(--wp--preset--color--muted);
}

/*
 * The reveal button sits in flow at the far end, which is what space-between is for. It was
 * absolutely positioned over a 3.2rem padding reserved on the input; neither is needed now.
 */
.smeweb-auth-reveal {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.5rem;
	height: 1.5rem;
	margin-left: 0.75rem;
	padding: 0;
	color: var(--wp--preset--color--muted);
	background: none;
	border: 0;
	cursor: pointer;
}

.smeweb-auth-reveal:hover {
	color: var(--wp--preset--color--primary);
}

.smeweb-auth-reveal svg {
	width: 1.25rem;
	height: 1.25rem;
}

.smeweb-auth-mismatch {
	margin: 0.4rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--accent);
}

/*
 * The submit is the site’s pill. !important on the four properties the plugin also sets: its
 * rule is an id and two classes, one class heavier than this one, and an important declaration
 * outranks a heavier selector without stacking classes to out-count a plugin.
 */
.fls_registration_wrapper #fls_submit,
.fls_registration_wrapper #fls_verification_submit,
.fls_reset_pass_wrapper .fls_reset_pass_form #fls_reset_pass,
.fls_login_wrapper #wp-submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	width: 100%;
	margin-top: var(--wp--preset--spacing--20);
	padding: 0.95rem 2rem !important;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small) !important;
	font-weight: 500;
	color: var(--wp--preset--color--base) !important;
	background-color: var(--wp--preset--color--primary) !important;
	border: 0;
	border-radius: 999px !important;
	cursor: pointer;
	transition: background-color 0.18s ease;
}

.fls_registration_wrapper #fls_submit:hover,
.fls_registration_wrapper #fls_verification_submit:hover,
.fls_reset_pass_wrapper .fls_reset_pass_form #fls_reset_pass:hover,
.fls_login_wrapper #wp-submit:hover {
	background-color: var(--wp--preset--color--primary-dark) !important;
}

/*
 * The way out of the auth screen, above everything else on it.
 *
 * This template prints no header and no footer — that is what makes the two halves work — so
 * without this a visitor who lands here and changes their mind has the browser's back button
 * and nothing else. It is a child of the panel, so it takes the panel's column and its left
 * edge like everything below it.
 */
.smeweb-auth-back {

	/* Stated, because the heading below it is not a first child any more but still has no top. */
	margin-bottom: 2rem;
	font-size: var(--wp--preset--font-size--small);
}

.smeweb-auth-back a {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* Before the words rather than after them, and pointing the other way: it goes back. */
.smeweb-auth-back a::before {
	content: "←";
	color: var(--wp--preset--color--accent);
	transition: transform 0.18s ease;
}

.smeweb-auth-back a:hover {
	color: var(--wp--preset--color--primary);
}

.smeweb-auth-back a:hover::before {
	transform: translateX(-3px);
}

/*
 * The line to the other half, centred in the column with no mark on it.
 *
 * It had an arrow after the words and sat on the left edge like everything else. The comp puts
 * it in the middle and drops the arrow, which is the right call for a line that is a footnote to
 * the form rather than a step in it.
 */
.smeweb-auth-alt {
	margin-top: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	color: #6e6e85;
	text-align: center;
}

/*
 * The question is grey and the answer is the brand blue, so the link is the only thing on the
 * line that looks like one. #6e6e85 on white is 4.96:1, over the 4.5 this size of text asks for.
 */
.smeweb-auth-alt a {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

.smeweb-auth-alt a:hover {
	text-decoration: underline;
}

/*
 * The panel a signed-in visitor gets in place of the form.
 *
 * Spans, made blocks here: the plugin wraps its message in a <p>, and a <div> inside a
 * paragraph is closed by the parser before any of this could reach it. See
 * smeweb_auth_signed_in_panel().
 */
.smeweb-auth-panel .smeweb-auth-signedin {
	display: block;
	padding: clamp(1.5rem, 3vw, 2.5rem);
	background-color: var(--wp--preset--color--surface);
	border-radius: 24px;
	text-align: center;
}

.smeweb-auth-signedin__title {
	display: block;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	line-height: 1.4;
	color: var(--wp--preset--color--contrast);
}

.smeweb-auth-signedin__hint {
	display: block;
	margin-top: 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.smeweb-auth-signedin__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.75rem;
	margin-top: var(--wp--preset--spacing--30);
}

.smeweb-auth-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.7rem 1.6rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--primary);
	text-decoration: none;
	background-color: transparent;
	border: 1px solid var(--wp--preset--color--primary);
	border-radius: 999px;
	transition: background-color 0.18s ease, color 0.18s ease;
}

.smeweb-auth-btn--solid {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
}

.smeweb-auth-btn:hover {
	background-color: var(--wp--preset--color--primary-dark);
	border-color: var(--wp--preset--color--primary-dark);
	color: var(--wp--preset--color--base);
}

/* The star beside a label, hidden — this comp has no labels at all, and the marker is in the
   placeholder. !important because the plugin prints after the theme. */
.fls_registration_wrapper .fls_field_label.is-required label::after {
	content: none !important;
}

/*
 * Stacked below 880px, where two halves would leave the form about 340px wide. The mark
 * becomes a band across the top and the panel takes the rest.
 */
/* ---- the code step, between filling the form in and having an account ---- */

/*
 * The plugin swaps the fields for this once the form is sent, inside the same wrapper, so it
 * inherits the column and the field box already. What it does not inherit is any of the
 * spacing: it arrives as a bare div with a paragraph, a label and a button in it.
 */
.smeweb-auth-panel .fls_signup_verification {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
}

/* The line that says where the code went. It is the only instruction on the screen. */
.smeweb-auth-panel .fls_2fa_instruction {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	color: var(--wp--preset--color--contrast);
}

/*
 * The label goes, as it does on every other field here — the placeholder carries the name and
 * the paragraph above has already said what to type. Hidden rather than removed, so a screen
 * reader still reads the field its label.
 */
.smeweb-auth-panel .fls_field_verification .fls_field_label {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* A code is a short string of characters, and reads better spaced out and not in a text face. */
.smeweb-auth-panel #fls_field_verification {
	letter-spacing: 0.18em;
}

.smeweb-auth-panel #fls_field_verification::placeholder {
	letter-spacing: normal;
}

/* The plugin wraps its button in p.submit, which brings a margin the column already provides. */
.smeweb-auth-panel .fls_signup_verification p.submit {
	margin: 0;
}

/*
 * What the template costs, under its description on the card.
 *
 * Only on the cards that have a package: no placeholder, no "ติดต่อสอบถาม", nothing at all,
 * because an empty row on fifteen of sixteen cards would be worse than a shorter card.
 */
.smeweb-tpl-card-pkg {
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 0.5rem;
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--x-small);
}

.smeweb-tpl-card-pkg__name {
	color: var(--wp--preset--color--muted);
}

.smeweb-tpl-card-pkg__price {
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

/*
 * The live demo, in a full-screen overlay opened by a link.
 *
 * display: none until :target matches, which does two jobs at once: it hides the overlay, and
 * it stops the iframe loading, because a browser does not fetch the contents of a box it is not
 * rendering. That is what keeps an 82.8 MB demo off the page until somebody asks for it.
 */
.smeweb-tpl-demo__launch {
	margin: var(--wp--preset--spacing--30) 0 0;
	text-align: center;
}

.smeweb-tpl-demo__open {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.8rem 1.8rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
	border-radius: 999px;
	text-decoration: none;
	transition: background-color 0.18s ease;
}

.smeweb-tpl-demo__open::after {
	content: "↗";
}

.smeweb-tpl-demo__open:hover {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary-dark);
}

.smeweb-tpl-demo {
	display: none;
}

/*
 * The markup for this is printed on wp_footer, and that is load-bearing. Inside a constrained
 * layout core caps every child at content-size with margin: auto !important, which it applies to
 * a fixed box as readily as to a paragraph: inset: 0 was honoured, then the width was cut to
 * 1200 and the box centred, so the "full screen" overlay was a 1248px strip with the page
 * showing either side. See smeweb_tpl_demo_queue().
 *
 * overflow + overscroll-behavior are the scroll lock. A wheel over the backdrop used to scroll
 * the page underneath — measured 900px — and you closed the overlay somewhere else than you
 * opened it. overscroll-behavior: contain stops the chain at a scroll container even when that
 * container cannot scroll, which html:has(...) { overflow: hidden } would also do, but that one
 * removes the document scrollbar and shifts the whole page sideways as it opens.
 */
.smeweb-tpl-demo:target {
	position: fixed;
	z-index: 200;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	overscroll-behavior: contain;
	padding: clamp(0.5rem, 2vw, 1.5rem);
}

/* A link, not a div, so clicking away closes it without a script. */
.smeweb-tpl-demo__backdrop {
	position: absolute;
	inset: 0;
	background-color: rgba(20, 20, 43, 0.62);
	backdrop-filter: blur(3px);
}

.smeweb-tpl-demo__panel {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	width: 100%;
	height: 100%;
	max-width: 1600px;
	overflow: hidden;
	background-color: var(--wp--preset--color--base);
	border-radius: 16px;
	box-shadow: 0 30px 80px rgba(20, 20, 43, 0.4);
}

.smeweb-tpl-demo__radio,
.smeweb-tpl-demo__wide {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

/* Name on the left, devices in the middle, the way out on the right. */
.smeweb-tpl-demo__bar {
	position: relative;
	z-index: 2;
	background-color: var(--wp--preset--color--base);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	flex: 0 0 auto;
	padding: 0.6rem 0.9rem;
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

/*
 * The name, and what the template costs if a package has been set.
 *
 * min-width: 0 is what lets the name truncate instead of pushing the price out of the bar: a
 * flex item will not shrink below its content without it, whatever overflow says.
 */
.smeweb-tpl-demo__title {
	display: flex;
	align-items: baseline;
	gap: 0.6rem;
	flex: 1 1 0;
	min-width: 0;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

.smeweb-tpl-demo__name {
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.smeweb-tpl-demo__pkg {
	flex: 0 0 auto;
	font-weight: 400;
	white-space: nowrap;
	color: var(--wp--preset--color--muted);
}

.smeweb-tpl-demo__pkg b {
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

.smeweb-tpl-demo__devices {
	display: flex;
	flex: 0 0 auto;
	gap: 0.2rem;
	padding: 0.2rem;
	background-color: var(--wp--preset--color--surface);
	border-radius: 999px;
}

.smeweb-tpl-demo__device {
	padding: 0.3rem 0.8rem;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
	border-radius: 999px;
	cursor: pointer;
	transition: color 0.18s ease, background-color 0.18s ease;
}

.smeweb-tpl-demo__device:hover {
	color: var(--wp--preset--color--primary);
}

.smeweb-tpl-demo__actions {
	display: flex;
	align-items: center;
	flex: 1 1 0;
	gap: 0.9rem;
	justify-content: flex-end;
	font-size: var(--wp--preset--font-size--x-small);
}

/*
 * Fill the window, and say which way it is going to go.
 *
 * One label holding both words with one hidden, so the button reads ขยายเต็มจอ when it will
 * expand and ย่อลง when it will not — a control that keeps the same text in both states makes
 * you press it to find out.
 */
.smeweb-tpl-demo__grow {
	box-sizing: border-box;
	padding: 0.3rem 0.95rem;
	color: var(--wp--preset--color--contrast);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	white-space: nowrap;
	cursor: pointer;
	transition: color 0.18s ease, background-color 0.18s ease;
}

.smeweb-tpl-demo__grow::before {
	content: "⤢";
	margin-inline-end: 0.35rem;
}

.smeweb-tpl-demo__grow:hover {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--contrast);
}

.smeweb-tpl-demo__grow-out {
	display: none;
}

.smeweb-tpl-demo__wide:checked ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__grow::before {
	content: "⤡";
}

.smeweb-tpl-demo__wide:checked ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__grow-in {
	display: none;
}

.smeweb-tpl-demo__wide:checked ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__grow-out {
	display: inline;
}

.smeweb-tpl-demo__wide:focus-visible ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__grow {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

/*
 * :has() because the checkbox lives inside the panel and these two are its ancestors, which a
 * sibling combinator cannot reach. Everything else about this toggle uses ~ and works without
 * it, so a browser too old for :has() gets a button that changes its own label and nothing
 * more — wrong, but not broken.
 */
.smeweb-tpl-demo:has(.smeweb-tpl-demo__wide:checked) {
	padding: 0;
}

.smeweb-tpl-demo:has(.smeweb-tpl-demo__wide:checked) .smeweb-tpl-demo__panel {
	max-width: none;
	border-radius: 0;
}

/* The one thing in the bar that is being sold, so it is the one thing that is filled in. */
/*
 * ซื้อเทมเพลตนี้ — the buy button, on the blue-red gradient.
 *
 * It sits beside ขยายเต็มจอ and ปิด, which are both outlined and neutral, so this is the only
 * filled control in the bar and the gradient is what separates "spend money" from "look around".
 *
 * The blue-red preset, which is the same one the active All pill in the category sidebar uses —
 * the one place in this theme where the two brand colours meet. Not a gradient written here, so
 * the two cannot drift apart.
 *
 * border-color: transparent rather than no border, so the button keeps the exact box it had
 * with a 1px solid one and nothing beside it in the bar shifts.
 *
 * background-origin: border-box is what that border then requires, and it is not optional.
 * background-clip defaults to border-box but background-origin defaults to padding-box, so the
 * gradient was being sized to the padding box and clipped to the larger border box — leaving
 * the 1px ring filled with the gradient's edge extension. On a 115-degree gradient that
 * extension is the far end, so the ring came out the opposite colour to the button underneath
 * it: read off the pixels at 6x, six device px of #F2030C down the blue left edge and six of
 * #2B28C2 up the red right edge, which is exactly one CSS pixel of border on each side.
 *
 * With the origin on the border box the gradient spans everything it paints and the ring takes
 * the local colour. The solid background-color is not involved — removing it was the first fix
 * tried and the ring survived it.
 *
 * Worth knowing before reusing this: white measures 9.25:1 over the blue end and 4.00:1 over
 * the red, and the bar's text is 14.4px, which needs 4.5. Bold does not change that — WCAG
 * only counts bold as large text from 18.66px. Ending the gradient at #E60000 instead of
 * #FF0000 gives 4.81:1 there and is indistinguishable at this size.
 */
.smeweb-tpl-demo__cta {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0.4rem 1.1rem;
	font-weight: 700;
	color: var(--wp--preset--color--base);
	/*
	 * #E60000 rather than the accent's own #FF0000 at the red end.
	 *
	 * White on #FF0000 measures 3.9:1, under the 4.5 this label needs at 500 weight, and the
	 * red end is where the label sits. #E60000 clears it and is the value the hover below
	 * already darkens to, so the two states are built from one pair of stops.
	 *
	 * Written out rather than by editing the blue-red preset: that preset is the front page's
	 * as well, and there the gradient carries no text over its red end.
	 */
	background-color: #E60000;
	background-image: linear-gradient(115deg, #1f2acd 0%, #E60000 100%);
	background-origin: border-box;
	border: 1px solid transparent;
	border-radius: 999px;
	text-decoration: none;
	white-space: nowrap;
	transition: background-image 0.18s ease, filter 0.18s ease;
}

/*
 * The bag, as a mask over currentColor rather than an inline SVG in the markup.
 *
 * Same idiom as the breadcrumb house: the glyph then takes the button's own colour and cannot
 * fall out of step with it, and the label stays the only thing in the PHP. Sized in em so it
 * tracks the label — 1.05em against a 500-weight line reads as the same optical weight as the
 * text beside it.
 */
.smeweb-tpl-demo__cta::before {
	content: "";
	flex: 0 0 auto;
	width: 1.05em;
	height: 1.05em;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='m23.8 30h-15.6c-3.3 0-6-2.7-6-6v-.2l.6-16c.1-3.3 2.8-5.8 6-5.8h14.4c3.2 0 5.9 2.5 6 5.8l.6 16c.1 1.6-.5 3.1-1.6 4.3s-2.6 1.9-4.2 1.9c0 0-.1 0-.2 0zm-15-26c-2.2 0-3.9 1.7-4 3.8l-.6 16.2c0 2.2 1.8 4 4 4h15.8c1.1 0 2.1-.5 2.8-1.3s1.1-1.8 1.1-2.9l-.6-16c-.1-2.2-1.8-3.8-4-3.8z'/%3E%3Cpath d='m16 14c-3.9 0-7-3.1-7-7 0-.6.4-1 1-1s1 .4 1 1c0 2.8 2.2 5 5 5s5-2.2 5-5c0-.6.4-1 1-1s1 .4 1 1c0 3.9-3.1 7-7 7z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='m23.8 30h-15.6c-3.3 0-6-2.7-6-6v-.2l.6-16c.1-3.3 2.8-5.8 6-5.8h14.4c3.2 0 5.9 2.5 6 5.8l.6 16c.1 1.6-.5 3.1-1.6 4.3s-2.6 1.9-4.2 1.9c0 0-.1 0-.2 0zm-15-26c-2.2 0-3.9 1.7-4 3.8l-.6 16.2c0 2.2 1.8 4 4 4h15.8c1.1 0 2.1-.5 2.8-1.3s1.1-1.8 1.1-2.9l-.6-16c-.1-2.2-1.8-3.8-4-3.8z'/%3E%3Cpath d='m16 14c-3.9 0-7-3.1-7-7 0-.6.4-1 1-1s1 .4 1 1c0 2.8 2.2 5 5 5s5-2.2 5-5c0-.6.4-1 1-1s1 .4 1 1c0 3.9-3.1 7-7 7z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/*
 * The hover darkens both ends by hand.
 *
 * A background-color hover would do nothing now — the gradient is a background-image and paints
 * over it. #161fa0 is the primary-dark preset and #E60000 the red the label's contrast note
 * above names, so the darker gradient is built from values the theme already has rather than a
 * filter, which would also dim the white label.
 */
.smeweb-tpl-demo__cta:hover,
.smeweb-tpl-demo__cta:focus-visible {
	color: var(--wp--preset--color--base);
	background-image: linear-gradient(115deg, #161fa0 0%, #E60000 100%);
	border-color: transparent;
}

.smeweb-tpl-demo__close {
	padding: 0.3rem 0.95rem;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	white-space: nowrap;
}

.smeweb-tpl-demo__close::before {
	content: "✕ ";
}

.smeweb-tpl-demo__close:hover {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--contrast);
}

/*
 * The frame takes the rest of the panel, and only its width changes with the device.
 *
 * Height stays put on purpose: a real 390x844 would resize the panel on every switch. The
 * framed page answers its own media queries either way, because what it reads is the iframe
 * width — and 834 and 390 are an iPad Air and an iPhone 14, not round numbers.
 */
/*
 * Two jobs in one box, both of them what the frame is sitting on.
 *
 * While the demo loads it is the only thing there, so it says so. Once the demo paints it is the
 * stage the frame sits on, which is what a tablet or phone width is centred against — grey reads
 * as a screen the device is placed on, where the panel's white read as a hole in the panel.
 */
.smeweb-tpl-demo__wait {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
	background-color: var(--wp--preset--color--surface);
}

/*
 * The stage, the device and the screen.
 *
 * The tablet and phone tabs used to narrow the iframe and leave it as a rectangle on grey. They
 * now stand the demo in a device: __stage centres, __device carries the shell, the iframe is the
 * screen. On the desktop tab both wrappers are transparent and full size, so that tab is exactly
 * what it was.
 *
 * The screen width is the number that matters and it stays literal — 834 for the tablet, 390 for
 * the phone, with the bezel added on top of it rather than taken out of it, so the demo is still
 * being asked to render at a real device width. Nothing is scaled: a transform would let the
 * body keep a photogenic aspect ratio but would lie about the viewport the page is laying out
 * for, which is the only reason to have these tabs.
 *
 * The height is therefore whatever the panel can give, capped so a tall monitor does not stretch
 * the phone into a ribbon. Measured on this panel: about 900px of stage at 1080p, which lands
 * the phone screen near 390x876 and the tablet near 834x920.
 */
.smeweb-tpl-demo__stage {
	position: relative;
	z-index: 1;
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: center;
	min-height: 0;
}

/*
 * box-sizing is not inherited here, and it was measurable: with the default content-box the
 * bezel was added outside the width, so min(874px) gave an 834 tablet screen a 914 body and
 * measured the screen itself at 874 — the whole point of the number, wrong by exactly the two
 * bezels. Same on the phone, 414 instead of 390. border-box puts the bezel inside the width.
 */
.smeweb-tpl-demo__body {
	position: relative;
	display: flex;
	box-sizing: border-box;
	width: 100%;
	height: 100%;
	margin-inline: auto;
	transition: width 0.24s ease, padding 0.24s ease, border-radius 0.24s ease;
}

.smeweb-tpl-demo__frame {
	display: block;
	flex: 1 1 auto;
	width: 100%;
	height: 100%;
	border: 0;

	/*
	 * Transparent, not white: the grey behind it is the loading message, and an opaque frame
	 * would cover it for the second and a half before the demo paints.
	 */
	background-color: transparent;
}

/* No island and no side buttons on the desktop tab — they only exist in the rules below. */
.smeweb-tpl-demo__island {
	display: none;
}

/*
 * The shell both devices share: a dark body with a hairline of light around it where a real one
 * catches the room, over the panel's own shadow softened a little.
 */
.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body,
.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body {
	background-image: linear-gradient(157deg, #3c3c4c 0%, #191927 46%, #23232f 100%);
	box-shadow:
		inset 0 0 0 1px rgba(255, 255, 255, 0.16),
		0 22px 55px rgba(20, 20, 43, 0.42);
}

/* And a margin off the panel edges, so the body reads as an object standing on the grey. */
.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage,
.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage {
	padding: clamp(0.75rem, 2.2vh, 1.75rem) 1rem;
}

/*
 * Tablet: iPad Pro 12.9", 1024 x 1366, asked for by name. The bezel is 20px and is added on top
 * of the screen rather than taken out of it, so the width below is 1024 + two bezels.
 */
.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body {
	width: min(1064px, 100%);
	max-height: 1406px;
	padding: 20px;
	border-radius: 34px;
}

.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__frame {
	border-radius: 16px;
}

/* On a tablet the one thing above the screen is the camera. */
.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__island {
	position: absolute;
	top: 8px;
	left: 50%;
	display: block;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background-color: #4b4b5c;
	transform: translateX(-50%);
}

/* Phone: iPhone 14/15, 390 x 844, in a 12px bezel. */
.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body {
	width: min(414px, 100%);
	max-height: 868px;
	padding: 12px;
	border-radius: 52px;
}

.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__frame {
	border-radius: 40px;
}

/* The island sits over the screen, which is where the real one is. */
.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__island {
	position: absolute;
	top: 22px;
	left: 50%;
	z-index: 2;
	display: block;
	width: 82px;
	height: 22px;
	border-radius: 999px;
	background-color: #08080d;
	transform: translateX(-50%);
}

/*
 * Side buttons, drawn beside the body with pseudo-elements rather than three more spans in the
 * markup. The left one is a single 3px sliver whose gradient leaves the gaps — silent switch,
 * volume up, volume down — and the right one is the power button on its own.
 *
 * They sit at -3px, outside the body but inside the stage's 1rem of side padding, so the panel's
 * overflow: hidden never reaches them.
 */
.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body::before {
	content: "";
	position: absolute;
	top: 15%;
	left: -3px;
	width: 3px;
	height: 27%;
	border-radius: 2px 0 0 2px;
	background-image: linear-gradient(
		to bottom,
		#2e2e3c 0 20%,
		transparent 20% 33%,
		#2e2e3c 33% 63%,
		transparent 63% 71%,
		#2e2e3c 71% 100%
	);
}

.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body::after {
	content: "";
	position: absolute;
	top: 25%;
	right: -3px;
	width: 3px;
	height: 13%;
	border-radius: 0 2px 2px 0;
	background-color: #2e2e3c;
}

/*
 * On a small screen the mock-up thins out rather than disappears.
 *
 * A 12px bezel and a 52px radius are read against a 390px screen; on a 390px window the device
 * is the whole width and both are a big bite out of it. The buttons go because at that size they
 * are two dark specks against the panel edge.
 */
@media (max-width: 700px) {
	.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage,
	.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage {
		padding: 0.5rem;
	}

	.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body {
		padding: 10px;
		border-radius: 20px;
	}

	.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__frame {
		border-radius: 12px;
	}

	.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body {
		padding: 7px;
		border-radius: 30px;
	}

	.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__frame {
		border-radius: 24px;
	}

	.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__island {
		top: 14px;
		width: 62px;
		height: 17px;
	}

	.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body::before,
	.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__stage .smeweb-tpl-demo__body::after {
		display: none;
	}
}

/* Which device is showing. */
.smeweb-tpl-demo__radio:nth-of-type(1):checked ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__device:nth-child(1),
.smeweb-tpl-demo__radio:nth-of-type(2):checked ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__device:nth-child(2),
.smeweb-tpl-demo__radio:nth-of-type(3):checked ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__device:nth-child(3) {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
}

.smeweb-tpl-demo__radio:nth-of-type(1):focus-visible ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__device:nth-child(1),
.smeweb-tpl-demo__radio:nth-of-type(2):focus-visible ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__device:nth-child(2),
.smeweb-tpl-demo__radio:nth-of-type(3):focus-visible ~ .smeweb-tpl-demo__bar .smeweb-tpl-demo__device:nth-child(3) {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

/*
 * On a phone the bar is two rows, arranged rather than left to wrap where it lands.
 *
 * It claimed two rows and measured three. The name took a row of its own, and then the device
 * switch and the actions wanted 382px of the 345 available, so the actions wrapped again: 145px
 * of an 844px screen spent on our own chrome before the demo got any. Ordering them puts the
 * name and the way out on row one and the device switch on row two — measured 145px down to
 * about 112px, with every control grown to a 40px target on the way.
 */
@media (max-width: 600px) {
	.smeweb-tpl-demo__bar {
		flex-wrap: wrap;
		row-gap: 0.4rem;
	}

	/* Row one is shared with the actions, so the name and the price stack instead of competing. */
	.smeweb-tpl-demo__title {
		order: 1;
		flex: 1 1 0;
		flex-direction: column;
		align-items: flex-start;
		gap: 0;
	}

	/*
	 * The actions get a row of their own once one of them is a button worth pressing.
	 *
	 * They shared row one with the name before, which worked while they were two small links.
	 * Adding เลือกเทมเพลตนี้ wanted 297px of the 148 that row had left, so the row splits: name,
	 * then the device switch, then the three actions spread across the full width. It costs about
	 * 39px of demo height, which is the trade for the primary action being a real target.
	 */
	.smeweb-tpl-demo__actions {
		order: 4;
		flex: 1 1 100%;
		justify-content: space-between;
	}

	.smeweb-tpl-demo__devices {
		order: 3;
		flex: 1 1 100%;
		justify-content: center;
	}

	/*
	 * 40px, because these are being tapped now rather than pointed at.
	 *
	 * border-box matters here: min-height on a label with padding is the content box, so the first
	 * attempt made a 50px control out of a 40px minimum and the bar only came down from 145 to 134.
	 */
	.smeweb-tpl-demo__grow,
	.smeweb-tpl-demo__cta,
	.smeweb-tpl-demo__close,
	.smeweb-tpl-demo__device {
		box-sizing: border-box;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		/* inline-flex makes the close mark its own flex item, and the space after it vanished. */
		gap: 0.3rem;
		min-height: 40px;
	}

	.smeweb-tpl-demo__panel {
		border-radius: 12px;
	}

	.smeweb-tpl-demo:has(.smeweb-tpl-demo__wide:checked) .smeweb-tpl-demo__panel {
		border-radius: 0;
	}
}


/* ---- the reset half of the same screen ---- */

/*
 * One field and a button, so the only spacing that matters is between them.
 *
 * !important on the group for the same reason the signup one needs it: the plugin puts 15px
 * under every group from a rule of three classes printed after this stylesheet.
 */
.smeweb-auth-panel .fls_reset_pass_wrapper .fls_field_group {
	margin-bottom: var(--wp--preset--spacing--30) !important;
}

/* wpautop leaves an empty paragraph after the shortcode; it is invisible and 24px tall. */
.smeweb-auth-panel .entry-content > p:empty {
	display: none;
}

/* ---- the login half of the same screen ---- */

/*
 * Every login rule here is prefixed .fls_login_wrapper form#loginform, and that is not
 * decoration.
 *
 * The plugin prints a <style> block in the body — after this stylesheet — that sets
 * .fls_login_wrapper form#loginform { display: block }, its > p children to block with 15px
 * under each, and .input to 10px of padding and a 100% width. All three are an id, a class and
 * a type, so a two-class selector loses the tie on order and the first build of this page came
 * out in source order with the Google button at the bottom. The prefix adds one class, which
 * settles it without !important.
 */

/* Same 500px cap as the signup wrapper, and it has to go for the same reason. */
.smeweb-auth-panel .fls_login_wrapper {
	max-width: none;
}

/*
 * The form is the column, and the column is not in source order.
 *
 * wp_login_form() writes username, password, middle, submit. The plugin appends the Google
 * button to login_form_bottom, which is after all of that, and the design puts it first. The
 * form is a flex column so order can say what the reader gets — the same trick the signup
 * wrapper uses, one level lower down because that is where the button lands here.
 */
.smeweb-auth-panel .fls_login_wrapper form#loginform {
	display: flex;
	flex-direction: column;
	margin: 0;
}

.smeweb-auth-panel .fls_login_wrapper form#loginform .fm_login_with {
	order: 1;
}

/*
 * display restated for the same reason as the fields below: the plugin blocks every > p in this
 * form, and the lines either side of the words are pseudo-elements that grow to fill a flex row.
 * As a block they had nothing to grow into and the rule showed up as bare left-aligned text.
 */
.smeweb-auth-panel .fls_login_wrapper form#loginform > p.smeweb-auth-or {
	order: 2;
	display: flex;
	margin: var(--wp--preset--spacing--30) 0;
}

/*
 * display restated, because the box these two are is the flex container the field spec is
 * written against — see the .fs_input_wrap rule for the numbers. The gaps are the signup
 * column's: nothing above the first field, 32 between the two.
 */
.smeweb-auth-panel .fls_login_wrapper form#loginform > p.login-username {
	order: 3;
	display: flex;
	margin: 0;
}

.smeweb-auth-panel .fls_login_wrapper form#loginform > p.login-password {
	order: 4;
	display: flex;
	margin: 2rem 0 0;
}

.smeweb-auth-panel .fls_login_wrapper form#loginform > .smeweb-auth-row {
	order: 5;
	margin: 1.25rem 0 0.75rem;
}

/* No margin of its own: the gap above the pill is the one on the submit itself. */
.smeweb-auth-panel .fls_login_wrapper form#loginform > p.login-submit {
	order: 6;
	margin: 0;
}

/*
 * The labels are still in the markup, only hidden — a placeholder is gone the moment anything
 * is typed, and this is the name a screen reader keeps.
 *
 * Gated on the class smeweb_auth_login_placeholders() only adds when both placeholders landed.
 * If that ever stops matching the plugin's markup the labels come back rather than leaving two
 * empty boxes with nothing to say what they are.
 */
.smeweb-auth-fields-ready form#loginform > p.login-username label,
.smeweb-auth-fields-ready form#loginform > p.login-password label {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Stay signed in on the left, the way out of a forgotten password on the right. */
.smeweb-auth-panel .smeweb-auth-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	font-size: var(--wp--preset--font-size--x-small);
}

/* The plugin makes every label in this form a block; this one is a row of two things. */
.smeweb-auth-panel .fls_login_wrapper form#loginform label.smeweb-auth-remember {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-weight: 400;
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
}

.smeweb-auth-remember input[type="checkbox"] {
	width: 1rem;
	height: 1rem;
	margin: 0;
	accent-color: var(--wp--preset--color--primary);
}

.smeweb-auth-forgot {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

.smeweb-auth-forgot:hover {
	text-decoration: underline;
}


@media (max-width: 880px) {
	.smeweb-auth-page {
		grid-template-columns: 1fr;
		min-height: 0;
	}

	.smeweb-auth-brand {
		padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--40);
	}

	/*
	 * The ribbon goes. Stacked, the left half is a band a couple of hundred pixels tall and a
	 * curve that reads as a sweep across a full column reads as a smear across a strip.
	 */
	.smeweb-auth-brand::after {
		display: none;
	}

	.smeweb-auth-brand .wp-block-site-logo {
		width: min(180px, 46%);
	}

	.smeweb-auth-tagline {
		position: static;
		margin-top: var(--wp--preset--spacing--30);
		font-size: var(--wp--preset--font-size--small);
	}

	.smeweb-auth-panel {
		padding: var(--wp--preset--spacing--50) 1.5rem;
	}

	/* A 64% column on a phone is a letterbox; here it is the panel less its gutter. */
	.smeweb-auth-panel > * {
		width: 100%;
	}
}

/*
 * The account control that replaces the two calls to action once someone is signed in.
 *
 * A details element, so the menu opens with no script — the same thing the FAQ rows are built
 * on. summary carries the name and the mark; the panel under it is absolutely positioned so
 * opening it does not push the header taller.
 */
.smeweb-account {
	position: relative;
}

.smeweb-account__who {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	padding: 0.35rem 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
	border-radius: 999px;
	cursor: pointer;
	list-style: none;
	transition: background-color 0.18s ease;
}

/* Safari draws its own triangle on a summary and only this turns it off. */
.smeweb-account__who::-webkit-details-marker {
	display: none;
}

.smeweb-account__who:hover {
	background-color: var(--wp--preset--color--surface);
}

/* The first letter of the name in a disc, which costs nothing and asks no third party. */
.smeweb-account__mark {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	line-height: 1;
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
	border-radius: 50%;
	text-transform: uppercase;
}

/* A long address would push the nav off the row; the mark and the arrow stay whatever happens. */
.smeweb-account__name {
	max-width: 10rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.smeweb-account > .smeweb-account__who::after {
	content: "";
	flex: 0 0 auto;
	width: 0.5rem;
	height: 0.5rem;
	margin-left: 0.1rem;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateY(-2px) rotate(45deg);
	transition: transform 0.18s ease;
}

.smeweb-account[open] > .smeweb-account__who::after {
	transform: translateY(1px) rotate(-135deg);
}

.smeweb-account__menu {
	position: absolute;
	z-index: 20;
	top: calc(100% + 0.5rem);
	right: 0;
	display: flex;
	flex-direction: column;
	min-width: 12rem;
	padding: 0.4rem;
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 14px;
	box-shadow: 0 18px 40px rgba(20, 20, 43, 0.14);
}

.smeweb-account__link {
	padding: 0.55rem 0.75rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	border-radius: 10px;
}

.smeweb-account__link:hover {
	color: var(--wp--preset--color--primary);
	background-color: var(--wp--preset--color--surface);
}

/*
 * In the overlay it is not a dropdown. There is a column of room there, so the name sits at the
 * top and the links go under it as rows — nothing to open, nothing to close.
 */
.smeweb-account--stacked {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	margin-top: var(--wp--preset--spacing--30);
	padding-top: var(--wp--preset--spacing--30);
	border-top: 1px solid var(--wp--preset--color--outline);
}

.smeweb-account--stacked .smeweb-account__who {
	margin-bottom: 0.3rem;
	cursor: default;
}

.smeweb-account--stacked .smeweb-account__name {
	max-width: none;
	font-weight: 600;
}

/*
 * The login is a word in the brand blue, not a second button.
 *
 * It arrived as a core outline button, which is what put a ring on it, and two rings side by
 * side read as a choice between two equal things. One pill and one word says which is which.
 *
 * The style class is still on the block in the database. Neutralising it here rather than
 * rewriting the markup keeps the change in one place and reversible.
 */
.smeweb-header-login .wp-block-button__link {
	padding-inline: 0.4rem !important;
	color: var(--wp--preset--color--primary);
	background-color: transparent;
	border: 0;
	box-shadow: none;
}

/*
 * Four classes on the hover, and every one of them is load-bearing.
 *
 * The block still carries is-style-outline in the database, and that style paints a filled hover
 * from .wp-block-button.is-style-outline .wp-block-button__link:hover — three classes, one more
 * than a two-class rule here. So the fill won while the colour did not, and hovering the word
 * turned it into brand blue on brand blue: invisible. The lift came from a third rule again, and
 * put the word 2px up as it went.
 */
.smeweb-header .wp-block-button.smeweb-header-login .wp-block-button__link:hover,
.smeweb-header .wp-block-button.smeweb-header-login .wp-block-button__link:focus-visible {
	color: var(--wp--preset--color--primary);
	background-color: transparent;
	box-shadow: none;
	transform: none;
	text-decoration: underline;
}

/*
 * In the overlay it goes back to being a button.
 *
 * There it is a full-width row stacked over the signup one, and a bare word in that position
 * reads as a stray line of text rather than something to tap. Same reasoning, opposite answer,
 * because the shape around it is different.
 */
.smeweb-menu-cta .smeweb-header-login .wp-block-button__link {
	padding-inline: 1.6rem !important;
	box-shadow: inset 0 0 0 2px currentColor;
}

/* The overlay one does want the fill, and says so at the same weight rather than by accident. */
.smeweb-header .smeweb-menu-cta .smeweb-header-login .wp-block-button__link:hover,
.smeweb-header .smeweb-menu-cta .smeweb-header-login .wp-block-button__link:focus-visible {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
	box-shadow: inset 0 0 0 2px var(--wp--preset--color--primary);
	transform: none;
	text-decoration: none;
}

/* Stacked in the phone menu it is a block, and the fill button below it sets the rhythm. */
@media (max-width: 781px) {
	.smeweb-menu-cta {
		gap: 0.6rem;
	}
}

/*
 * Once the menu is behind its button, the bar carries the signup pill alone.
 *
 * Measured at 414: the bar was 134px tall with the two of them beside a logo and a hamburger,
 * and 69 with one. The overlay has both, so nothing is lost.
 */
@media (max-width: 599px) {
	.smeweb-header > .wp-block-group .wp-block-buttons:not(.smeweb-menu-cta) .smeweb-header-login {
		display: none;
	}
}

/*
 * The menu goes behind its button below 1300, not below 600.
 *
 * 1024 was right for five inline items and is wrong for seven. ตัวอย่างเว็บไซต์ and
 * คู่มือการใช้งาน pushed the bar past what one row holds, and because the old breakpoint was
 * 1023 the wrap happened in a band the overlay never covered: measured 77px at 1290 and 149px
 * — two rows — at every step from 1280 down to 1024, where the button finally took over. A
 * 256px stretch of broken header, and none of it visible at the width the design is drawn at.
 *
 * 1299 rather than 1279, so the switch happens twenty pixels before the wrap does. Thai and
 * Latin fall back to different faces at different widths and the bar is only as wide as the
 * words in it; a threshold sitting exactly on the measurement is a threshold that fails the
 * first time a menu label is renamed.
 *
 * 600 is core's number for a menu of three or four short words, which this is not.
 *
 * The rules below are core's own two, inverted. It shows the open button under 600 and the
 * inline list over it; below 1300 both of those now flip, and .is-menu-open is left alone so
 * the overlay still opens.
 */
@media (max-width: 1299px) {
	.smeweb-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

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

/* ------------------------------------------------------------------ *
 * 6. Marquee
 * ------------------------------------------------------------------ */

.smeweb-marquee {
	overflow: hidden;
	display: flex;
	user-select: none;
}

.smeweb-marquee__track {
	display: flex;
	flex: 0 0 auto;
	align-items: center;

	/*
	 * 0.75rem, down from 2.5.
	 *
	 * Two gaps set the rhythm of this strip and they were the same 40px: the one inside an
	 * item, between a service and the mark after it, and this one, between that mark and the
	 * next service. Equal spacing left the mark belonging to nothing — it read as ending the
	 * name behind it as often as introducing the one ahead. 12px here against the 40 inside
	 * the item pairs every mark with the service it announces.
	 *
	 * padding-right matches, because it is the same gap: it is what stands between the last
	 * mark of one track and the first service of the copy that follows it, and the seam has to
	 * read like every other join or the loop shows.
	 */
	gap: 0.75rem;
	padding-right: 0.75rem;
	white-space: nowrap;
	/*
	 * 41s covers one untouched track at the 32 px/s that assets/js/marquee.js applies —
	 * roughly 1310px of content, which is what five services come to. The script
	 * overwrites this with a duration worked out from the real width, so this value only
	 * governs the case where it never ran.
	 */
	animation: smeweb-marquee-scroll 41s linear infinite;
}

.smeweb-marquee:hover .smeweb-marquee__track {
	animation-play-state: paused;
}

.smeweb-marquee__item {
	display: inline-flex;
	align-items: center;

	/*
	 * 4rem, up from 2.5.
	 *
	 * Pulling the mark up against the service ahead of it took 28px out of the space between
	 * one service and the next — 74px where there had been 102 — because that space is this gap
	 * plus the mark plus the 0.75rem after it. Raising this one restores the distance between
	 * entries without giving back the pairing: 64 + 22 + 12 comes to 98px, and the mark stays
	 * where it belongs.
	 */
	gap: 4rem;
	font-weight: 500;
}

/*
 * The separator between services, and the red band it sits on.
 *
 * The mark is the supplied Icon-Slide-02.png, from the media library — 74x74 for a
 * 22.4px box, so it stays crisp on a 2x display where the 37px first cut had to be
 * stretched 1.21x past its own resolution. 1,538 bytes. Same shape, checked against
 * the earlier file at matched size: 2.3% of pixels differ, all of it resampling along
 * the edges.
 *
 * Before that came an SVG that wrapped a 228x228 PNG whose base64 had arrived
 * truncated — valid header and IEND either side of the gap, so it decoded without
 * complaint and rendered as nothing. Standing in for it was a drawn asterisk of
 * rounded petals; the real mark has eight straight arms with flat ends, which is not
 * something worth guessing at once the file exists.
 *
 * Applied as a mask rather than a background image. The file is white on transparent,
 * which is right for the red band and wrong everywhere else; as a mask its alpha is
 * the shape and the colour stays in CSS, so one file serves both the band and the
 * fallback below.
 */
.smeweb-marquee__item::after {
	content: "";
	width: 1.4rem;
	height: 1.4rem;
	flex: 0 0 auto;
}

/*
 * Longhands, not the mask shorthand: older WebKit accepts -webkit-mask-image but not
 * a size inside the shorthand, and would drop the whole declaration.
 *
 * The colour lives in here rather than on the rule above so that a browser with no
 * mask support gets no separator at all instead of a solid red square.
 */
@supports (mask-image: url("i.png")) or (-webkit-mask-image: url("i.png")) {
	.smeweb-marquee__item::after {
		background-color: var(--wp--preset--color--accent);
		-webkit-mask-image: url("../../uploads/2026/08/Icon-Slide-02.png");
		-webkit-mask-repeat: no-repeat;
		-webkit-mask-position: center;
		-webkit-mask-size: contain;
		mask-image: url("../../uploads/2026/08/Icon-Slide-02.png");
		mask-repeat: no-repeat;
		mask-position: center;
		mask-size: contain;
	}

	.wp-block-group:has( > .smeweb-marquee ) .smeweb-marquee__item::after {
		background-color: var(--wp--preset--color--base);
	}
}

/*
 * One gradient across a run of sections — on the pricing page, from the counters down
 * through the packages. White at the top of the run, #EBF1FF at the bottom.
 *
 * The run is two sibling sections with no wrapper between them, and the page renders
 * from the database so none can be added. Each section therefore carries the same
 * gradient sized to the height of the whole run and offset upward by how far into it
 * the section sits, so the second paints the continuation of the first rather than a
 * second copy. A copy each would put the pale bottom edge of one against the white top
 * edge of the next and draw a line across the page.
 *
 * The two numbers come from assets/js/section-tint.js, which also adds this class. CSS
 * cannot read a height. Without the script nothing is marked and the sections keep the
 * backgrounds they had.
 *
 * Every longhand is !important, and background-color is set as well as the image. The
 * ends of the run carry has-surface-background-color and
 * has-lavender-wash-gradient-background; the second is a `background` shorthand written
 * with !important, and a shorthand marked important hands that priority to every
 * longhand it implies — so size, position, repeat and attachment all have to be claimed
 * back explicitly or the preset gradient wins them.
 *
 * main > for specificity: the preset classes score the same as a single class, and
 * leaning on source order to break the tie is not worth the saving.
 */
main > .smeweb-tint {
	background-color: transparent !important;
	background-image: linear-gradient(to bottom, #FFFFFF 0%, #EBF1FF 100%) !important;
	background-repeat: no-repeat !important;
	background-size: 100% var(--smeweb-tint-span, 100%) !important;
	background-position: 0 var(--smeweb-tint-offset, 0) !important;
	background-attachment: scroll !important;
}

/*
 * The red ribbon behind the packages — the supplied Vector-BG.png, 1920x865 of red on
 * transparency, 28 KB.
 *
 * Carried as a second background layer rather than a pseudo-element. A pseudo-element
 * would need z-index: -1 to sit under the cards, and a negative child paints before its
 * own stacking context block backgrounds — so the section gradient would cover it
 * unless the section were also made a stacking context. A background layer is behind
 * the content by definition and needs none of that.
 *
 * The cost of that choice is this rule having to restate the gradient layer from
 * .smeweb-tint above, including its two custom properties, because background-image is
 * one list and cannot be added to. Two classes here outscore the one there, so the
 * order these appear in the file does not matter.
 *
 * Full width, because the design runs it off both edges, and a height from
 * assets/js/section-tint.js: whatever the gap between the copy above the cards and the
 * note below will take. Both are given explicitly, so past about 1500px the image is
 * squashed rather than kept at its own 2.22:1 — 17% at 1920, 38% at 2560, nothing at
 * 1440 where a full-width ribbon already fits.
 *
 * Deliberate, and the least bad of three. Keeping the ratio and capping the height left
 * a floating band with two blunt cut ends inside the section; keeping the ratio and
 * letting it overrun put red ink across 39% of the intro paragraph at 1920 and 70% of
 * the eyebrow at 2560. On an abstract swoosh a flatter curve costs nothing.
 *
 * The class is added by the same script, so without it there is no ribbon rather than a
 * ribbon at some guessed size.
 */
main > .smeweb-tint.smeweb-vector {
	background-color: transparent !important;
	background-image:
		url("../../uploads/2026/08/Vector-BG.png"),
		linear-gradient(to bottom, #FFFFFF 0%, #EBF1FF 100%) !important;
	background-repeat: no-repeat, no-repeat !important;
	background-size:
		100% var(--smeweb-vector-height),
		100% var(--smeweb-tint-span, 100%) !important;
	background-position:
		center var(--smeweb-vector-top),
		0 var(--smeweb-tint-offset, 0) !important;
	background-attachment: scroll, scroll !important;
}

/*
 * The dotted square at the foot of the packages, and the note beside it.
 *
 * Same pattern as the corners of the templates hero — a repeating radial gradient in
 * brand blue at 21px, a third opaque — reused rather than redrawn so the two pages
 * carry the same mark. Eleven rows of dots is a pattern, not artwork.
 *
 * On the section rather than inside it, so it sits against the window edge instead of
 * the 1200px content measure. A pseudo-element is safe here where the ribbon needed a
 * background layer: that had to stay behind the cards, this sits in empty space beside
 * the note, so painting above the flow costs nothing. pointer-events: none all the
 * same, since it covers part of the section.
 *
 * The constrained-layout rule that caps every direct child of a group at the content
 * measure does not reach it — that selector matches elements, and a generated box is
 * not one.
 */
main > .smeweb-tint.smeweb-vector {
	position: relative;
}

/*
 * Sized to the room left under the note rather than to taste. Measured: 128px between the
 * note and the end of the section at 1440 and above, 145 at 768. At 150px tall on a 24px
 * offset the square reached 25px into the note’s last line.
 *
 * 104 plus a 20px offset is 124, which clears it at every width the section takes.
 */
main > .smeweb-tint.smeweb-vector::before {
	content: "";
	position: absolute;
	left: 0;
	bottom: 1.25rem;
	width: clamp(72px, 7vw, 104px);
	height: clamp(72px, 7vw, 104px);
	background-image: radial-gradient(var(--wp--preset--color--primary) 2px, transparent 2px);
	background-size: 21px 21px;
	opacity: 0.3;
	pointer-events: none;
}


/*
 * Red band, white type — the supplied design.
 *
 * The band is a database-rendered group carrying has-base-background-color, which
 * core writes with !important, so the override needs it too.
 *
 * The border colours carry !important for a different reason: the width and colour
 * are on the element’s own style attribute, put there by whoever edited the page, and
 * an inline style outranks every selector regardless of specificity. Setting the
 * colour without it left the grey hairline showing along the top of the red.
 *
 * Reached with :has() because the group has nothing else to identify it — alignfull
 * and a base background are shared with other sections on the page, and the pricing
 * page renders from the database, so a class cannot be added to the markup.
 *
 * Background, type colour and the white mark above all hang off the same :has() on
 * purpose. A browser without it drops them together and shows the band as it was —
 * white, dark type, red mark — rather than white type on a band that stayed white.
 */
.wp-block-group:has( > .smeweb-marquee ) {
	background-color: var(--wp--preset--color--accent) !important;
	border-top-color: var(--wp--preset--color--accent) !important;
	border-bottom-color: var(--wp--preset--color--accent) !important;
}

.wp-block-group:has( > .smeweb-marquee ) .smeweb-marquee {
	color: var(--wp--preset--color--base);
}

/*
 * Five services, not six.
 *
 * patterns/marquee.php lists five now, which is the real fix and the one that applies
 * the day the pricing page stops rendering from the database. Until then that file is
 * not read and the sixth item is in the database copy, so it is hidden here too.
 *
 * Scoped to tracks without data-smeweb-base — the attribute assets/js/marquee.js
 * stamps on a track once it has trimmed it to five and repeated the content. Without
 * that scope this rule kept firing on the repeated list, where the sixth position is
 * no longer the unwanted service but the first item of the second copy, and it hid
 * Web E-Learning out of every repeat. The band read five, four, five, four.
 *
 * So the two halves do not overlap: the script owns the list once it has touched it,
 * and this rule covers the untouched case — no JavaScript, or a track already wide
 * enough that nothing was copied.
 *
 * nth-child(6) rather than last-child, on purpose. Aimed at the last item it would
 * start hiding WordPress Development the moment the sixth is removed in the editor,
 * quietly leaving four. Aimed at the sixth position it matches nothing once there are
 * five, and retires itself.
 *
 * display: none rather than visibility or opacity, so the track actually gets shorter
 * and no hidden label is left to be read aloud.
 */
.smeweb-marquee__track:not([data-smeweb-base]) .smeweb-marquee__item:nth-child(6) {
	display: none;
}

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

/* ------------------------------------------------------------------ *
 * 7. Pricing packages
 * ------------------------------------------------------------------ */

/*
 * Pricing hero background.
 *
 * Set here rather than in patterns/hero-pricing.php because that page renders from
 * the database. What makes it reachable at all is that the hero is a plain group
 * carrying a gradient class rather than a cover block with an <img> inside it — an
 * image element in the markup could not have been swapped from a stylesheet.
 *
 * Two layers, photograph over gradient. The gradient is the same `blue-deep` the
 * hero already had, kept underneath so a slow or missing image leaves the section
 * looking as it did rather than blank.
 *
 * The photograph scrolls with the section. A fixed attachment was tried in 1.1.34
 * to 1.1.36 and taken out again — asked for as parallax, then not wanted once it
 * was on screen, where a background holding still under a moving section reads as
 * stuck rather than deep. `scroll` is the default, and it is written out anyway
 * because it has to carry !important like everything else here.
 *
 * Every longhand needs that !important, and this is the part worth remembering.
 * WordPress writes preset background classes as
 * `.has-blue-deep-gradient-background { background: … !important }` — the
 * *shorthand* — and a shorthand hands its priority to every longhand it implies. So
 * `background-size: auto !important`, `background-position: 0% 0% !important` and
 * `background-repeat: repeat !important` all exist without being written anywhere.
 * 1.1.34 marked only background-image and shipped a photograph at natural size in
 * the top-left corner, tiling, while every value in this file was correct.
 *
 * Two classes and an element here against core's single class, so this wins the tie
 * between two important declarations. Scoped by the body class WordPress puts on the
 * pricing page, so it cannot reach another section using the same gradient.
 *
 * The file is a 347 KB JPEG converted from the 2.7 MB PNG that was uploaded. At 3x
 * magnification the red swoosh edge, the dot matrix and the cyan hairline are clean
 * — compared side by side before settling on quality 92 — and this sits above the
 * fold, where 2.7 MB would have been the largest thing on the page by far.
 */
.page-template-page-pricing main > .has-blue-deep-gradient-background {
	background-image:
		url("../../uploads/2026/08/Hero-BG.webp"),
		var(--wp--preset--gradient--blue-deep) !important;
	background-repeat: no-repeat, no-repeat !important;
	background-size: cover, cover !important;
	background-position: center top, center center !important;
	background-attachment: scroll, scroll !important;

	/*
	 * The section is the frame the photograph is cropped to, so its height decides
	 * how much of the composition survives. 1920x1050 is a wide picture: at 1440 the
	 * whole of it wants 787px, and the 400px left after the illustration below was
	 * hidden would have cut the composition to a strip. 100vh is the same measure the
	 * home hero uses.
	 */
	min-height: 100vh;

	/* Positioning context for the floating layer in 7b. */
	position: relative;
}

/*
 * The hero's placeholder illustration, hidden at every width.
 *
 * hero-pricing.svg drew a browser mock-up of its own, directly over the one inside
 * the photograph — two illustrations of the same idea fighting each other, and the
 * comp shows neither. One line to bring back if the artwork ever leaves the
 * background.
 */
.page-template-page-pricing main > .has-blue-deep-gradient-background > .wp-block-image {
	display: none;
}

/*
 * Narrow screens keep the picture but need less room for it.
 *
 * A portrait viewport cannot show a 1.83 composition whole: once `cover` has filled
 * the height it crops the width to roughly a third, which lands on the two people
 * in the middle and is the part worth keeping. 80vh gives that crop enough height
 * to read while leaving the headline clear of it.
 *
 * A portrait cut of the artwork would serve this better than a crop of the wide
 * one. Left until the floating elements arrive, since they will change what the
 * composition has to fit around.
 */
@media (max-width: 781px) {
	.page-template-page-pricing main > .has-blue-deep-gradient-background {
		min-height: 80vh;
	}
}

.smeweb-package {
	height: 100%;
	position: relative;
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.smeweb-package:hover {
	transform: translateY(-6px);
	box-shadow: 0 24px 50px rgba(31, 42, 205, 0.18);
}

.smeweb-package__strike {
	text-decoration: line-through;
	opacity: 0.6;
}

/*
 * Card titles on one line at every width the four sit side by side.
 *
 * Not a fixed size: measured across the range, the large preset holds from about 1280 up
 * and wraps below it — Premium and E-Commerce at 1024, E-Commerce alone at 1100 and 1200
 * — because the row shrinks with the window while the type does not. A title on two
 * lines pushes that card’s price, list and button out of step with the other three.
 *
 * The ceiling is the large preset itself, so nothing changes from about 1467px up, where
 * 1.5vw passes 22px. Below that it tracks the card. 0.95rem is the floor, reached at 1013
 * — just under the width where the cards stop being a row at all.
 *
 * !important because has-large-font-size is one of core’s preset classes, and those are
 * written with !important.
 */
.smeweb-package > .wp-block-heading {
	font-size: clamp(0.95rem, 1.5vw, 1.375rem) !important;
}

/*
 * Pricing cards: a shadow and no outline.
 *
 * Both need !important, because the border width and the shadow are on each card’s own
 * style attribute — put there by the editor — and an inline style outranks every
 * selector. border: 0 rather than a transparent colour, so the 1px stops taking up
 * space as well as stopping being visible.
 *
 * The value is the one the service cards already use, rather than a new one written to
 * match: same figure, same intent, and it is not in theme.json as a preset either.
 *
 * All four cards, the highlighted one included. At 8% on a blue card the shadow is
 * barely there, which is what the comp shows — a flat blue block beside three lifted
 * white ones.
 */
.smeweb-package {
	border: 0 !important;
	box-shadow: 0 4px 20px 9px rgba(84, 90, 255, 0.08) !important;
}

/*
 * Wider cards, and a little more air between them.
 *
 * The row was capped at the 1200px content measure like every other child of the
 * section, which left each card 282px wide. The wide measure is 1320, which takes them
 * to 309 — and the gap goes from 24 to 28, because the same gap between wider cards
 * reads tighter than it did.
 *
 * Scoped to this section: .smeweb-card-grid is shared with the services and features
 * grids, which are meant to stay on the content measure. Core caps children through
 * :where(), which contributes no specificity, so a plain rule is enough.
 */
main > .has-lavender-wash-gradient-background > .smeweb-card-grid {
	max-width: var(--wp--style--global--wide-size);
	gap: 1.75rem;
}


/*
 * Package cards: what is in the plan and what is not.
 *
 * The comp marks every row, included or not — a blue disc with a white tick, or a bare
 * grey cross. Which rows are which is in the markup, as .smeweb-off on the list item,
 * because it is a fact about the package and not about how the page looks.
 *
 * Every row reads at the same weight. Excluded rows drop to muted, so the tick and the
 * cross are backed by colour rather than by weight — bolding the included half made the
 * lists look like two different kinds of text.
 */
.smeweb-package .smeweb-checklist li.smeweb-off {
	color: var(--wp--preset--color--muted);
}

/*
 * The cross replaces the disc rather than sitting on it, so background-color has to be
 * cleared: the badge style sets a solid blue circle, and a cross drawn over that would
 * read as another kind of yes.
 */
.smeweb-checklist.is-style-smeweb-check-badge li.smeweb-off::before {
	background-color: transparent;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6e85' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6 18 18M18 6 6 18'/%3E%3C/svg%3E");
}

/*
 * On the highlighted card the disc cannot be brand blue — that is the card. White disc,
 * blue tick; and the cross goes to a dimmed white, since muted grey disappears against
 * the blue.
 */
.smeweb-package.is-featured .smeweb-checklist.is-style-smeweb-check-badge li::before {
	background-color: var(--wp--preset--color--base);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f2acd' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.6 9 17.6 20 6.6'/%3E%3C/svg%3E");
}

.smeweb-package.is-featured .smeweb-checklist li.smeweb-off {
	color: rgba(255, 255, 255, 0.62);
}

.smeweb-package.is-featured .smeweb-checklist.is-style-smeweb-check-badge li.smeweb-off::before {
	background-color: transparent;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6 18 18M18 6 6 18'/%3E%3C/svg%3E");
}

/*
 * A rule between the storage line and the list, as the comp has it. On the border of the
 * list rather than a separate element, so it moves with the list and disappears with it.
 */
.smeweb-package .smeweb-checklist {
	border-top: 1px solid var(--wp--preset--color--outline);
	padding-top: var(--wp--preset--spacing--30);
}

.smeweb-package.is-featured .smeweb-checklist {
	border-top-color: rgba(255, 255, 255, 0.28);
}

/*
 * The figures the comp picks out in red — storage per plan, form count where there is
 * one. On the highlighted card red against blue is unreadable, so it keeps the card’s
 * own white and the emphasis comes from the surrounding text being dimmer.
 */
.smeweb-hl {
	color: var(--wp--preset--color--accent);
}

.smeweb-package.is-featured .smeweb-hl {
	color: inherit;
}

/*
 * The storage line under the price: dimmer than the figure it carries, so the GB reads
 * first. Muted through the paragraph would take the figure with it, which is why the
 * colour is here and not on the block.
 */
.smeweb-package__storage {
	color: var(--wp--preset--color--muted);
}

.smeweb-package.is-featured .smeweb-package__storage {
	color: rgba(255, 255, 255, 0.78);
}

/*
 * The foot of the packages: the note on the left, the closing call to action on the
 * right, as the comp has them.
 *
 * The wide measure, not the content measure. Widening the card row to 1320 moved the
 * cards out to 60px at 1440 and left the note behind on 120 — flush with nothing. Both
 * now sit in the same box, so the note starts where the first card starts at any width.
 *
 * Bottom-aligned, so the button sits on the note’s last line rather than floating
 * halfway up a three-line paragraph.
 */
main > .has-lavender-wash-gradient-background > .smeweb-package-foot {
	max-width: var(--wp--style--global--wide-size);
	align-items: flex-end;
	gap: var(--wp--preset--spacing--30);
}

/*
 * The note takes the row and the button takes what it needs. 34em of basis with a 62em
 * cap: at 14px the cap is about 75 characters, and without it a short note on a wide
 * window would run to 90 or more.
 *
 * box-sizing because a paragraph here is content-box, which is what made an earlier
 * attempt at this widen its own box instead of shortening its line.
 */
.smeweb-package-foot .smeweb-package-note {
	box-sizing: border-box;
	flex: 1 1 34em;
	max-width: 62em;
	margin-block: 0;
	line-height: 1.9;
}

.smeweb-package-foot .wp-block-buttons {
	flex: 0 0 auto;
}
/*
 * The "popular" tag on the highlighted plan — a diagonal band across the top-right
 * corner, as the comp has it, in place of the rounded pill that was here before.
 *
 * The label still comes from data-badge rather than from content, so it stays in the
 * markup where it can be translated and edited. The database copy of the page had no
 * such attribute, and attr() on a missing attribute is an empty string rather than
 * nothing, so the pill used to render as a bare red blob; the attribute is set on the
 * card now and the rule below keeps that from coming back.
 *
 * overflow: hidden on the card is what makes it a corner banner: the band is wider than
 * the corner it crosses and its ends are cut by the card, border radius included. The
 * card has nothing that needs to overflow.
 *
 * #F5B92B is read off the comp. Nothing in the palette matches it, and every gold in
 * the theme would be a new brand colour, so it is written here rather than added to
 * theme.json until the value is confirmed.
 */
.smeweb-package.is-featured {
	overflow: hidden;
}

.smeweb-package.is-featured::after {
	content: attr(data-badge);
	position: absolute;
	top: 1.15rem;
	right: -2.9rem;
	width: 10rem;
	padding: 0.28rem 0;
	transform: rotate(45deg);
	text-align: center;
	font-size: 0.62rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	background-color: #F5B92B;
	color: var(--wp--preset--color--contrast);
}

/* No label, no band. content: none removes the box; an empty attr() would only empty it. */
.smeweb-package.is-featured:not([data-badge])::after,
.smeweb-package.is-featured[data-badge=""]::after {
	content: none;
}

/* ------------------------------------------------------------------ *
 * 7b. Pricing hero — floating elements
 * ------------------------------------------------------------------ */

/*
 * The cards and social marks that float over the hero, laid out from the supplied
 * comp and moved by assets/js/hero-fx.js.
 *
 * The script builds the nodes and sets one transform each; everything about how
 * they look and where they sit is here. Re-placing an element is a number in this
 * file and nothing else.
 *
 * The comp is 1920x1050 and the background is drawn with `cover`, so at any other
 * ratio the artwork is cropped and a percentage of the *section* would drift away
 * from it. The stage below is sized exactly as the background is — as wide as the
 * viewport or as wide as its own height demands, whichever is greater — and
 * centred the same way. Percentages inside it are therefore percentages of the
 * artwork, and every position here is read straight off the comp.
 */
/*
 * The layer has to escape the content measure.
 *
 * The hero is a constrained group, so WordPress caps every direct child of it:
 *
 *   .is-layout-constrained > :where(:not(.alignleft)…) {
 *     max-width: var(--wp--style--global--content-size);
 *     margin-left: auto;
 *   }
 *
 * which made this layer 1200px wide and centred inside a 1920px section — and since
 * it also clips, everything outside that band went with it: 173px off the colour
 * picker, 144px off the X, 133px off the cart. Exactly the slicing that was reported
 * and that four rounds of measuring failed to find, because those checks compared
 * each element against the *section* while the box doing the cutting was this one.
 *
 * Core's selector is one class plus a :where(), which contributes nothing, so it
 * sits at the same weight as a single class here and would be settled by order.
 * Written at three classes and an element instead, so the outcome does not depend on
 * which stylesheet the browser reads last.
 */
.page-template-page-pricing main > .has-blue-deep-gradient-background > .smeweb-hero-fx {
	max-width: none;
	margin-inline: 0;
}

.smeweb-hero-fx {
	position: absolute;
	inset: 0;
	overflow: hidden;
	pointer-events: none;
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__stage {
	position: absolute;
	top: 50%;
	left: 50%;

	/*
	 * 1920 / 1050 = 1.828571 — the width the background has at this height, which is
	 * what makes percentages inside this box percentages of the artwork.
	 *
	 * The cap is a guard against window shapes, not screens. Measured across eleven
	 * standard resolutions from 1280x800 to 2560x1440, every element sits inside the
	 * section with room for its full travel, and the cap changes the stage on none of
	 * them. It bites only when a window is dragged narrow and tall — at 1280x900 the
	 * crop reaches 183px a side and the colour picker loses 70px of its edge, which
	 * reads as a mistake in a way a cropped photograph does not.
	 *
	 * 1.15 is the widest the stage can be relative to the window before the outermost
	 * element plus its 47.5px of travel crosses the edge. Above that ratio the stage
	 * simply follows the background, as it should.
	 *
	 * One case is left: a window wider than about 2:1 crops the composition top and
	 * bottom instead, and the cart loses roughly 24px of its lower edge. A height cap
	 * would fix it and would also need a floor to stay positive in short windows, for
	 * a case rarer than the one it guards.
	 */
	width: min(max(100vw, calc(100vh * 1.828571)), calc(100vw * 1.15));
	aspect-ratio: 1920 / 1050;
	transform: translate(-50%, -50%);
}

.smeweb-hero-fx__item {
	position: absolute;
	background-repeat: no-repeat;
	background-size: contain;
	background-position: center;

	/*
	 * The script writes `transform` on every frame, so the ease belongs on the
	 * property and not on a class. Short enough to smooth a jumpy pointer without
	 * lagging behind a slow one.
	 */
	transition: transform 0.12s ease-out;
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--ads {
	left: 14.036%;
	top: 40.524%;
	width: 9.948%;
	aspect-ratio: 191 / 93;
	background-image: url("../../uploads/2026/08/Google-Ads.png");
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--views {
	left: 27.969%;
	top: 42.905%;
	width: 10.417%;
	aspect-ratio: 200 / 123;
	background-image: url("../../uploads/2026/08/Container.png");
}

/*
 * The cart sits 25 comp pixels above where the comp puts it — 737 rather than 762.
 *
 * It is the lowest element in the composition, and a window shorter than about 950
 * crops the artwork top and bottom, so its lower edge plus the 50px it travels was
 * crossing the section: 15px at 1920x920, 5px at 1920x940. That is a 1920x1080
 * screen with a browser on it, which is to say the common case rather than an odd
 * one.
 *
 * 25px out of 1050 is 2.4% of the composition and reads as the same layout. It is
 * a smaller price than a height cap, which would have had to shrink the stage
 * narrower than the window and pull every element out of line horizontally to fix
 * one edge vertically.
 */
.smeweb-hero-fx--pricing .smeweb-hero-fx__item--cart {
	left: 11.849%;
	top: 52.476%;
	width: 15.052%;
	aspect-ratio: 289 / 372;
	background-image: url("../../uploads/2026/08/Pop-up-Cart.webp");
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--google {
	left: 63.906%;
	top: 45.905%;
	width: 5.208%;
	aspect-ratio: 100 / 100;
	background-image: url("../../uploads/2026/08/Google.png");
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--facebook {
	left: 69.271%;
	top: 37.333%;
	width: 4.688%;
	aspect-ratio: 90 / 90;
	background-image: url("../../uploads/2026/08/Facebook.png");
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--tiktok {
	left: 76.25%;
	top: 33.238%;
	width: 4.271%;
	aspect-ratio: 82 / 82;
	background-image: url("../../uploads/2026/08/Tiktok.png");
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--line {
	left: 80.938%;
	top: 42.286%;
	width: 4.479%;
	aspect-ratio: 86 / 86;
	background-image: url("../../uploads/2026/08/Line.png");
}

.smeweb-hero-fx--pricing .smeweb-hero-fx__item--x {
	left: 85.208%;
	top: 37.238%;
	width: 3.542%;
	aspect-ratio: 68 / 68;
	background-image: url("../../uploads/2026/08/X.png");
}

/*
 * The panel opposite the cart. Its file arrived as Color-Picker-1.png — WordPress
 * added the -1 itself, and the name is used as uploaded rather than tidied, so this
 * URL and the media library agree.
 */
.smeweb-hero-fx--pricing .smeweb-hero-fx__item--picker {
	left: 75.99%;
	top: 56.476%;
	width: 14.271%;
	aspect-ratio: 274 / 358;
	background-image: url("../../uploads/2026/08/Color-Picker-1.webp");
}

/*
 * Nothing floats on a phone. The script already declines to build any of it
 * without a fine pointer, so this is the belt to that braces: a narrow window
 * shows about a third of the composition, and eight cards sized against the full
 * width of it would land on top of each other and on the headline.

 */
@media (max-width: 781px) {
	.smeweb-hero-fx {
		display: none;
	}
}

/* ------------------------------------------------------------------ *
 * 7c. Website templates page
 * ------------------------------------------------------------------ */

/*
 * The dotted corners from the design. Two pseudo-elements on a full-bleed section,
 * so they sit against the window edge rather than the content measure, and a
 * repeating radial gradient rather than an image — eleven rows of dots is a pattern,
 * not artwork, and this way it takes the brand blue from the palette.
 */
.smeweb-tpl-hero {
	position: relative;
}

/*
 * The intro sits on two lines, which needs a longer measure than the 42em every
 * other centred paragraph gets in section 1.
 *
 * Measured rather than guessed: at the size Global Styles gives this paragraph,
 * 17.6px, the wrap falls to three lines at 820px and to two at 830. 52em is 915px
 * here, so there is 85px of headroom — enough that a different font metric on
 * another platform cannot tip it back to three, which is the thing being fixed.
 *
 * Written in em, not px, so it keeps tracking the font: this size comes from
 * Global Styles in the database, not from theme.json, and can change without this
 * file knowing.
 *
 * It is a longer line than the 30-40em a paragraph normally wants, and that is the
 * trade being made deliberately for the two-line shape. It applies to this one
 * intro and nothing else.
 *
 * Element plus two classes here against the class pair in section 1, so this wins
 * on specificity rather than on which rule happens to come later in the file.
 */
section.smeweb-tpl-hero > p.has-text-align-center {
	max-width: 52em;
}

.smeweb-tpl-hero::before,
.smeweb-tpl-hero::after {
	content: "";
	position: absolute;
	top: 2.5rem;
	width: clamp(88px, 9vw, 150px);
	height: clamp(88px, 9vw, 150px);
	background-image: radial-gradient(var(--wp--preset--color--primary) 2px, transparent 2px);
	background-size: 21px 21px;
	opacity: 0.3;
	pointer-events: none;
}

.smeweb-tpl-hero::before {
	left: 0;
}

.smeweb-tpl-hero::after {
	right: 0;
}

/*
 * Sidebar beside results.
 *
 * The group is a flow container, so its children carry core's block gap; zeroed
 * here because the grid gap below is doing that job and the two would stack.
 *
 * Full width with the shell inset rather than the 1320px wide measure, so the page
 * starts on the same vertical as the navigation row and the footer bands — 67px at
 * 1440 and 82px at 1920, where the wide measure put it at 60 and 300. `alignfull`
 * does the escaping: core already cancels the root padding for it, which is exactly
 * how the header and footer reach the window edge.
 */
.smeweb-tpl-body {
	padding-inline: var(--smeweb-shell-inset);
	display: grid;
	/*
	 * 18rem rather than 15rem, so the longest category fits on one line.
	 *
	 * Measured: at 15rem a row had 211px of usable width, and
	 * "(Original Equipment Manufacturer)" needs 199px at 12px and 166px at 10px —
	 * so the old width only fit it at a size too small to read. 18rem gives 259px,
	 * which takes the acronym plus the gloss at 12px with 18px to spare.
	 *
	 * It costs the grid 48px, which at 1440 takes each card from 340px to 324px.
	 */
	grid-template-columns: 18rem minmax(0, 1fr);
	gap: clamp(1.5rem, 3vw, 3.5rem);
	align-items: start;
}

.smeweb-tpl-body > * {
	margin-block-start: 0;
}

@media (max-width: 781px) {
	.smeweb-tpl-body {
		grid-template-columns: minmax(0, 1fr);
	}
}

/*
 * Group headings carry more of the spacing than they did.
 *
 * A filter column reads as three groups, so the gap above a heading has to be
 * clearly larger than the gap between the rows under it, or the whole column looks
 * like one long list. 2.75rem above against 1rem below, against a row pitch of
 * about 0.4rem.
 */
.smeweb-tpl-filters__title {
	margin: 0 0 1rem;
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
}

.smeweb-tpl-filters__title:not(:first-child) {
	margin-top: 2.75rem;
}

/* Search */

.smeweb-tpl-search {
	margin: 0;
}

.smeweb-tpl-search__field {
	position: relative;
	display: block;
}

/*
 * The magnifier is drawn as a background image on the field rather than added as an
 * element, so the input stays the only thing in the label and nothing has to be
 * hidden from assistive software.
 */
.smeweb-tpl-search__field input {
	width: 100%;
	padding: 0.7rem 0.9rem 0.7rem 2.4rem;
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 8px;
	background-color: var(--wp--preset--color--base);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6e85' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.6-3.6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: 0.75rem center;
	background-size: 16px 16px;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
}

.smeweb-tpl-search__field input::placeholder {
	color: var(--wp--preset--color--muted);
}

/* Categories */

.smeweb-tpl-cats,
.smeweb-tpl-colours {
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The rows were touching — measured at 0px between them, so eight items read as one
 * block of text rather than eight targets. A flex column puts a real gap between
 * them without margins that collapse or need a :last-child exception.
 */
.smeweb-tpl-cats {
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
}

/*
 * line-height 1.5 rather than the 1.3 Global Styles hands down. One category runs
 * to three lines — OEM (Original Equipment Manufacturer) — and at 1.3 those lines
 * sat closer to each other than the rows sat to their neighbours, which made the
 * wrapped item read as three separate entries.
 *
 * The padding is vertical breathing room for a target, not decoration: every row is
 * clickable across its full width, so it wants to feel like a row and not like a
 * line of text that happens to be a link.
 */
.smeweb-tpl-cats__link {
	display: block;
	padding: 0.6rem 0.9rem;
	border-radius: 8px;
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	text-decoration: none;
	transition: background-color 0.18s ease, color 0.18s ease;
}

/*
 * The expansion after an acronym, drawn as a gloss rather than as part of the label.
 *
 * 0.68em against the row, which is 12px here. In em so it tracks the row if Global
 * Styles changes the size out from under it, and inheriting the colour so the two
 * halves still read as one link — only the size separates them.
 *
 * No nowrap. If a longer term ever exceeds the column it should wrap and be read,
 * not run out of the box and be cut.
 */
.smeweb-tpl-cats__note {
	font-size: 0.68em;
}

.smeweb-tpl-cats__link:hover {
	background-color: var(--wp--preset--color--surface);
}

/*
 * The selected category takes the blue-to-red gradient from the palette, which is
 * the one place in the theme those two brand colours meet — the same pairing the
 * hero cards use on hover.
 */
.smeweb-tpl-cats__link.is-active {
	background-image: var(--wp--preset--gradient--blue-red);
	color: var(--wp--preset--color--base);
	font-weight: 500;
}

/* Colours */

/*
 * The colours flow rather than sitting in two fixed columns.
 *
 * Two equal columns meant every row broke at the same place regardless of how long
 * the words were, so Red sat beside Yellow with a gap wide enough to park a third
 * swatch in. Each item takes the width of its own label now and the next one starts
 * where it ends, so rows hold two or three depending on the words and the block
 * reads as a set of tags rather than a table with empty cells.
 *
 * The row gap stays larger than the column gap. Wrapped rows need to be told apart
 * from each other more than neighbours within a row do, and with uneven breaks that
 * matters more, not less.
 */
.smeweb-tpl-colours {
	display: flex;
	flex-wrap: wrap;
	gap: 0.7rem 0.5rem;
}

.smeweb-tpl-colours__link {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.4rem 0.5rem;
	border-radius: 6px;
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
}

.smeweb-tpl-colours__link:hover,
.smeweb-tpl-colours__link.is-active {
	background-color: var(--wp--preset--color--surface);
}

.smeweb-tpl-colours__link.is-active {
	font-weight: 500;
}

/*
 * A 1px border on every swatch, not only the white one: without it White is an
 * invisible square, and giving it a border the others lack would make it read as
 * selected.
 */
.smeweb-tpl-colours__swatch {
	flex: 0 0 auto;
	width: 1.1rem;
	height: 1.1rem;
	border: 1px solid rgba(20, 20, 43, 0.15);
	border-radius: 3px;
}

/*
 * A template's pages in a browser frame, scrollable, one tab each.
 *
 * The frame is as wide as the header, which is the widest thing on the page.
 *
 * It lives in its own alignfull section now rather than inside the 720px reading column, and
 * that section is inset by --smeweb-shell-inset — the same variable the trending card and the
 * blog grid use, and the same value the header logo sits at: 67px at 1440, 82 at 1920. So the
 * frame lines up with the navbar above it rather than approximating it.
 *
 * Getting there took four tries and the failures are worth keeping. A negative margin with a
 * percentage resolves against the 720px column, so it came to zero. The same with vw lost to
 * the margin-left/right: auto !important core writes on every child of a constrained layout.
 * alignwide does nothing where the group declares a contentSize and no wideSize. max-width:
 * none worked but only reached 1200 — the group's own measure, not the page's. Moving the
 * frame out of that group is what actually answers it.
 */
/*
 * The section the frame sits in: full bleed, inset by the shell so its edges meet the header's.
 *
 * max-width and the auto margins both have to go on the child, for the reasons in the note
 * below. !important on the margin because that is how core writes it.
 */
.smeweb-tpl-stage {
	padding-inline: var(--smeweb-shell-inset);
}

.smeweb-tpl-stage > * {
	max-width: none;
	margin-inline: 0 !important;
}

.smeweb-tpl-preview {
	position: relative;
	max-width: none;
	margin-block: 0 var(--wp--preset--spacing--50);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 16px;
	overflow: hidden;
	background-color: var(--wp--preset--color--base);
	box-shadow: 0 22px 50px rgba(20, 20, 43, 0.12);
}

/*
 * The radios are the switch. Off-screen rather than display: none, because a hidden input
 * cannot take focus and the arrow keys are how this is operated without a mouse.
 */
.smeweb-tpl-preview__radio {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

/* A window bar, and the words in it say what this is: a screenshot, not a live site. */
.smeweb-tpl-preview__chrome {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.7rem 1rem;
	background-color: var(--wp--preset--color--surface);
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

.smeweb-tpl-preview__dots {
	flex: 0 0 auto;
	width: 2.6rem;
	height: 0.6rem;
	background-image: radial-gradient(circle, #d9d6e6 45%, transparent 46%);
	background-size: 0.87rem 100%;
	background-repeat: repeat-x;
}

.smeweb-tpl-preview__note {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
}

/*
 * The gallery: every page of the template at a glance, under the frame that shows one in full.
 *
 * These are the same radio labels the text tabs were — the switching mechanism has not changed,
 * only what the label looks like. A picture of the page is a better label than its name, and it
 * is the thing a visitor is actually scanning for.
 *
 * Below the stage rather than above it: the frame is what the section is for, and a strip of
 * cards above it would read as the subject rather than the index.
 */
.smeweb-tpl-preview__tabs {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
	gap: 0.75rem;
	padding: 1rem;
	border-top: 1px solid var(--wp--preset--color--outline);
	background-color: var(--wp--preset--color--base);
}

.smeweb-tpl-preview__tab {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 10px;
	cursor: pointer;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.smeweb-tpl-preview__tab:hover {
	border-color: var(--wp--preset--color--primary);
}

/* The top of the page, which is the part that identifies it. */
.smeweb-tpl-preview__thumb {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	object-position: top center;
}

.smeweb-tpl-preview__caption {
	padding: 0.45rem 0.6rem;
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.3;
	color: var(--wp--preset--color--contrast);
	text-align: center;
}

/*
 * The stage is a window the page scrolls inside, and the window is the shape of a real screen.
 *
 * It was clamp(24rem, 62vh, 40rem) — a height picked to look right, which meant the frame was
 * never quite the proportions of anything. 16:9 is what the design was drawn for and what the
 * visitor is sitting in front of, so the preview and the thing being previewed are the same shape.
 *
 * height: auto is not optional next to aspect-ratio; a height of any kind wins over it.
 *
 * The page inside is still 4000 to 8500px tall, so it still scrolls — the ratio decides how much
 * of it you see at once, not how much there is. overscroll-behavior keeps a flick at the end of
 * the shot from carrying on down the article.
 */
.smeweb-tpl-preview__stage {
	height: auto;
	aspect-ratio: 16 / 9;
	overflow-y: auto;
	overscroll-behavior: contain;
	background-color: var(--wp--preset--color--surface);
}

.smeweb-tpl-preview__pane {
	display: none;
}

.smeweb-tpl-preview__shot {
	display: block;
	width: 100%;
	height: auto;
}

/*
 * Eight of each, one per tab position, generated rather than typed. Sapsin has six pages; the
 * spare two are so a template with more of them works without anyone editing this.
 *
 * nth-of-type on the radios counts among the inputs, which are the first children of the
 * frame — that is what lets the rules be positional instead of naming ids that change per
 * template.
 */
.smeweb-tpl-preview__radio:nth-of-type(1):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(1),
.smeweb-tpl-preview__radio:nth-of-type(2):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(2),
.smeweb-tpl-preview__radio:nth-of-type(3):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(3),
.smeweb-tpl-preview__radio:nth-of-type(4):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(4),
.smeweb-tpl-preview__radio:nth-of-type(5):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(5),
.smeweb-tpl-preview__radio:nth-of-type(6):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(6),
.smeweb-tpl-preview__radio:nth-of-type(7):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(7),
.smeweb-tpl-preview__radio:nth-of-type(8):checked ~ .smeweb-tpl-preview__stage .smeweb-tpl-preview__pane:nth-child(8) {
	display: block;
}

.smeweb-tpl-preview__radio:nth-of-type(1):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(1),
.smeweb-tpl-preview__radio:nth-of-type(2):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(2),
.smeweb-tpl-preview__radio:nth-of-type(3):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(3),
.smeweb-tpl-preview__radio:nth-of-type(4):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(4),
.smeweb-tpl-preview__radio:nth-of-type(5):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(5),
.smeweb-tpl-preview__radio:nth-of-type(6):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(6),
.smeweb-tpl-preview__radio:nth-of-type(7):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(7),
.smeweb-tpl-preview__radio:nth-of-type(8):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(8) {
	border-color: var(--wp--preset--color--primary);
	box-shadow: inset 0 0 0 1px var(--wp--preset--color--primary);
}

.smeweb-tpl-preview__radio:nth-of-type(1):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(1),
.smeweb-tpl-preview__radio:nth-of-type(2):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(2),
.smeweb-tpl-preview__radio:nth-of-type(3):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(3),
.smeweb-tpl-preview__radio:nth-of-type(4):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(4),
.smeweb-tpl-preview__radio:nth-of-type(5):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(5),
.smeweb-tpl-preview__radio:nth-of-type(6):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(6),
.smeweb-tpl-preview__radio:nth-of-type(7):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(7),
.smeweb-tpl-preview__radio:nth-of-type(8):focus-visible ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(8) {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

/* The caption of the chosen card, so the ring is not the only thing saying which one it is. */
.smeweb-tpl-preview__radio:nth-of-type(1):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(1) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(2):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(2) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(3):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(3) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(4):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(4) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(5):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(5) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(6):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(6) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(7):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(7) .smeweb-tpl-preview__caption,
.smeweb-tpl-preview__radio:nth-of-type(8):checked ~ .smeweb-tpl-preview__tabs .smeweb-tpl-preview__tab:nth-child(8) .smeweb-tpl-preview__caption {
	font-weight: 600;
	color: var(--wp--preset--color--primary);
}

@media (max-width: 781px) {
	.smeweb-tpl-preview {
		margin-inline: 0;
	}

	/*
	 * Portrait on a phone, which is both more useful and more honest: 16:9 of a 341px frame is
	 * 192px tall and shows nothing, and a phone screen is not 16:9 landscape anyway.
	 */
	.smeweb-tpl-preview__stage {
		aspect-ratio: 3 / 4;
	}
}

/*
 * The badges under a template title: what it is for, what colour it is, what to search for.
 *
 * Three kinds on one row, and they have to be told apart at a glance without three different
 * shapes. The category is the loudest because it is the one fact a visitor is browsing by; the
 * colour carries its own swatch, which does the telling for it; the keyword is quietest, because
 * there can be several and they are the detail rather than the heading.
 *
 * Every one is a link to the archive filtered by that term. Not on the listing cards — sixteen
 * cards with up to six of these is noise, and the sidebar beside them already filters.
 */
.smeweb-tpl-badges {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.5rem;
	margin-top: var(--wp--preset--spacing--30);
}

.smeweb-tpl-badge {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.35rem 0.85rem;
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.4;
	text-decoration: none;
	border-radius: 999px;
	transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

/* The category, filled: it is the one thing on the row worth reading first. */
.smeweb-tpl-badge--cat {
	font-weight: 500;
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
}

.smeweb-tpl-badge--cat:hover {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary-dark);
}

/* The colour, outlined, because the swatch inside it is already doing the signalling. */
.smeweb-tpl-badge--colour {
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--outline);
}

.smeweb-tpl-badge--colour:hover {
	color: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
}

/* Same swatch the filter sidebar draws, from the same term meta. */
.smeweb-tpl-badge__swatch {
	flex: 0 0 auto;
	width: 0.85rem;
	height: 0.85rem;
	border: 1px solid rgba(20, 20, 43, 0.15);
	border-radius: 3px;
}

/*
 * The keyword, quietest of the three. There can be several, they are Thai and longer than the
 * other two, and a row of filled pills in three colours would read as a control panel.
 */
.smeweb-tpl-badge--tag {
	color: var(--wp--preset--color--muted);
	background-color: var(--wp--preset--color--surface);
}

.smeweb-tpl-badge--tag::before {
	content: "#";
	color: var(--wp--preset--color--primary);
}

.smeweb-tpl-badge--tag:hover {
	color: var(--wp--preset--color--primary);
	background-color: var(--wp--preset--color--outline);
}

/* The way back to the grid, in the same shape the auth screens use for theirs. */
.smeweb-tpl-back a {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

.smeweb-tpl-back a:hover {
	text-decoration: underline;
}

.smeweb-tpl-reset {
	display: block;
	margin-top: var(--wp--preset--spacing--40);
	padding: 0.7rem 1rem;
	border-radius: 8px;
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	text-align: center;
	text-decoration: none;
}

.smeweb-tpl-reset:hover {
	background-color: var(--wp--preset--color--primary-dark);
}

/* Results */

/*
 * The package tabs over the grid.
 *
 * Drawn as an underline row rather than as the pill group the demo overlay uses, which is the
 * shape the supplied reference has and the right one here: the pills in that overlay pick a
 * device inside one page, and these five change what the page is showing. An underline reads
 * as navigation, a pill as a toggle.
 *
 * The hairline is on the row and the active colour overlaps it, so the two never mismatch by a
 * pixel the way a border on each tab plus a border on the row would.
 */
.smeweb-tpl-tabs {
	display: flex;
	gap: clamp(0.5rem, 2vw, 2rem);
	margin-bottom: var(--wp--preset--spacing--30);
	box-shadow: inset 0 -1px 0 var(--wp--preset--color--outline);

	/*
	 * Five tabs do not fit a phone, and wrapping them puts a stray one on a line of its own
	 * under a row that reads as complete. Scrolling keeps them one row and keeps the hairline
	 * continuous. The scrollbar is left visible: hiding it is how a row like this becomes a
	 * thing nobody knows they can move.
	 */
	overflow-x: auto;
	overscroll-behavior-x: contain;
}

.smeweb-tpl-tabs__tab {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	flex: 0 0 auto;
	padding: 0.7rem 0.25rem 0.85rem;

	/*
	 * 20px flat, because of ทั้งหมด.
	 *
	 * That word stacks ั and ้ over the same ท, and at the small preset — 1.1rem, 17.6px —
	 * LINE Seed Sans TH draws the two as one blob: สระจม. Rendered at 17.6 / 19 / 20 / 22 and
	 * compared at 8x, they separate from 19px up, so small is below this font's threshold for a
	 * two-mark stack.
	 *
	 * A literal rem rather than the medium preset. Fluid typography is on, so medium computes
	 * to a clamp() — measured 20.8px at 1440 but 17.27px at 390, which is back under the
	 * threshold on exactly the screens where the row is already tightest. A flat value holds
	 * 20px everywhere.
	 *
	 * Nothing is being clipped — that was the first theory and it was wrong. The row's
	 * overflow-x: auto does make overflow-y compute to auto, so it is a vertical clipper, but
	 * the same tab rendered with overflow: visible produced identical glyphs and the line box
	 * has 11.8px of clearance above the text either way. It is the type size, not the box.
	 *
	 * The same threshold applies to any Thai on this site set at small over a stacked vowel and
	 * tone mark — ตั้ง, ขั้น, ทั่ว — so this is a local fix to a general fact.
	 */
	font-size: 1.25rem;

	/*
	 * 400 on the label and 400 on the number, asked for as one weight across the row. The
	 * active tab is not heavier either — it is already the only blue one with an underline
	 * under it, and a third signal on top of those two only makes the row look uneven.
	 */
	font-weight: 400;
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	white-space: nowrap;
	border-bottom: 3px solid transparent;
	transition: color 0.18s ease, border-color 0.18s ease;
}

.smeweb-tpl-tabs__tab:hover {
	color: var(--wp--preset--color--primary);
}

.smeweb-tpl-tabs__tab:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

.smeweb-tpl-tabs__tab.is-active {
	color: var(--wp--preset--color--primary);
	border-bottom-color: var(--wp--preset--color--primary);
}

/*
 * The count, so four of the five tabs do not look identical while three of them hold nothing.
 * surface on the resting tab and the brand tint on the active one, both at the pill radius the
 * rest of the site uses for a number like this.
 */
.smeweb-tpl-tabs__count {
	min-width: 1.5rem;
	padding: 0.05rem 0.4rem;
	font-size: 0.75rem;
	font-weight: 400;
	line-height: 1.5;
	text-align: center;
	color: var(--wp--preset--color--muted);
	background-color: var(--wp--preset--color--surface);
	border-radius: 999px;
}

.smeweb-tpl-tabs__tab.is-active .smeweb-tpl-tabs__count,
.smeweb-tpl-tabs__tab:hover .smeweb-tpl-tabs__count {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
}

.smeweb-tpl-count {
	margin: 0 0 var(--wp--preset--spacing--30);
	padding: 0.8rem 1.2rem;
	border-radius: 8px;
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

.smeweb-tpl-grid {
	gap: clamp(1.25rem, 2.5vw, 2rem);
}

/*
 * Each card is three blocks the Query Loop repeats, so there is no wrapper to hang
 * a hover on. The shot carries it, and the title darkens with it through a sibling
 * selector rather than by wrapping the pair in another element.
 *
 * No shadow, and no radius. Every screenshot in the library is a device mockup on
 * transparency — corners and edges read alpha 0, and 9% of each file is partial alpha,
 * which is the mockups’ own soft shadows. A box-shadow on top of that outlined the
 * image’s rectangle in blue-grey and turned the transparent area inside it into what
 * looked like a white panel behind the artwork. The panel was never a background: the
 * whole parent chain is transparent and the page there is white.
 *
 * The block’s own 12px radius went with it, as duplicate: theme.json already gives every
 * featured image 14px. That one stays, and it is invisible here either way — it clips
 * corners that carry no ink.
 *
 * Hover keeps the lift. Putting the shadow back only on hover would have drawn the same
 * phantom rectangle, one card at a time.
 */
/*
 * The whole picture, not a crop of it.
 *
 * A 1.5x zoom was tried to make the text inside the mockups legible and it was the wrong answer:
 * it magnified rather than sharpened, and it cut the right edge off every composition — the third
 * device in each one. Asked for sharper, delivered bigger. Reverted.
 *
 * Sharpness here is now capped by the source, not by the theme. Every original is 1080x659 and
 * the page serves that whole file at any display scaling above 1x, which is the most detail that
 * exists. More would need the mockups re-exported larger.
 */
.smeweb-tpl-shot img {
	width: 100%;
	transition: transform 0.22s ease;
}

.smeweb-tpl-shot:hover img {
	transform: translateY(-4px);
}

.smeweb-tpl-grid .wp-block-post-title a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.smeweb-tpl-grid .wp-block-post-title a:hover {
	color: var(--wp--preset--color--primary);
}

/*
 * The title and its description are one group; the image is not.
 *
 * Measured before touching it: 19px from image to title, 20px from title to
 * description. Two gaps that near-identical say nothing about what belongs with
 * what, so the three parts read as a list of three rather than a picture with a
 * caption under it. The title carried a 19.2px bottom margin doing that.
 *
 * 6px between the pair now against the 19px above them — close to the 1:3 that
 * makes grouping read without being thought about.
 */
.smeweb-tpl-grid .wp-block-post-title {
	margin-bottom: 0;
}

.smeweb-tpl-grid .wp-block-post-excerpt {
	margin-top: 0.375rem;
}

.smeweb-tpl-pagination {
	margin-top: var(--wp--preset--spacing--50);
	gap: 0.75rem;
	font-size: var(--wp--preset--font-size--small);
}

.smeweb-tpl-pagination .page-numbers,
.smeweb-tpl-pagination .wp-block-query-pagination-next {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

.smeweb-tpl-pagination .page-numbers.current {
	color: var(--wp--preset--color--accent);
	font-weight: 600;
}


/* ------------------------------------------------------------------ *
 * 7d. Contact hero — background and floating icons
 * ------------------------------------------------------------------ */

/*
 * The supplied Contact-us-BG over the gradient the section already carries.
 *
 * Served from the theme as WebP rather than from the media library as PNG: the upload is a
 * 940KB PNG of a photograph with not one translucent pixel in it, and the same picture is
 * 86KB as WebP at quality 0.85. The original is left in the library untouched.
 *
 * Every longhand is !important. The gradient arrives as `background` — a shorthand —
 * with !important, and a shorthand marked important hands that priority to every
 * longhand it implies, so size, position, repeat and attachment all have to be claimed
 * back or the gradient keeps them.
 *
 * `100% auto`, not `cover`. The composition runs the full width of the artwork and both
 * ends carry something — the dotted square on the left, the curl of the sweep on the
 * right — and cover was cutting 151px off each side at 1440, taking the dots with it.
 * Filling the width keeps the whole composition at every size; where the hero is taller
 * than the artwork the gradient shows above and below it, which is a band of the same
 * wash the artwork fades into.
 *
 * Capped at 1920px, the artwork’s own width, so it is never scaled up. Past that the
 * hero keeps growing wider while its height stays with the form, and an uncapped artwork
 * grew taller than the section it sits in: at 2560 it stood 1243px against a 750px hero
 * and the crop took the top of the figure’s head and most of the phone icon with it.
 * Above 1920 the artwork holds its size and the gradient fills the sides.
 *
 * The artwork carries the whole composition: the figure, the red sweep, the dotted
 * square and the speech bubble. patterns/contact-hero.php no longer places an
 * illustration in the left column, because it would sit on top of the figure.
 */
.page-template-page-contact main > .has-hero-wash-gradient-background {
	background-image:
		url("assets/img/contact-hero.webp"),
		var(--wp--preset--gradient--hero-wash) !important;
	background-repeat: no-repeat, no-repeat !important;
	background-size: min(100%, 1920px) auto, cover !important;
	background-position: center center, center center !important;
	background-attachment: scroll, scroll !important;
	position: relative;

	/*
	 * Tall enough to hold the artwork at whatever width it is drawn.
	 *
	 * Without this the hero took its height from the form — 750px at every width — while
	 * the artwork grew with the window: 932px at 1920, which the section then cropped by
	 * 91px top and bottom. That took the figure’s shoes and the space above his head.
	 *
	 * min-height, not height, so below about 1545px the form still sets the height and the
	 * artwork letterboxes instead. Capped with the artwork at 1920px for the same reason it
	 * is: past its own width there is nothing more to show.
	 */
	min-height: calc(min(100vw, 1920px) / 2.0601);
}

/*
 * Less empty space above the figure.
 *
 * Measured first, by hiding everything in the section and scanning down the column
 * through the head for the first pixel that is not the wash: 142px of clear space at
 * 1280, 114 at 1440, 117 at 1920. At 1280 and 1440 most of it was the band the artwork
 * leaves when the hero is taller than it, and background-position: center top puts that
 * below the artwork instead. At 1920 there was no band at all — all 117px is space the
 * artwork carries above the head.
 *
 * So above 1600px the hero is deliberately 3rem shorter than the artwork and the artwork
 * is anchored to its foot, which trims the top. No more than that: the phone icon is the
 * highest thing on the stage and it travels 50px up when the cursor pulls it, so the trim
 * plus 50 has to stay inside the space above it. Closing the gap entirely would cut the
 * icon in half every time it moved.
 *
 * 1600px is where the two regimes meet — below it the form is the taller of the two and
 * there is a band to place, above it the artwork is.
 *
 * All of this only became predictable once the hero’s own vertical padding moved onto
 * the columns inside it. background-origin is padding-box, so while the hero carried
 * padding the background was placed against a box 48px in from the top and bottom and the
 * icon layer against the border box; `top` meant two different things at once.
 */
@media (min-width: 1600px) {
	.page-template-page-contact main > .has-hero-wash-gradient-background {
		min-height: calc(min(100vw, 1920px) / 2.0601 - 3rem);
		background-position: center bottom, center center !important;
	}
}

/*
 * The wash across the foot of the hero: 320px tall, transparent to #EBF1FF, so the
 * figure dissolves into the section instead of standing on a hard edge.
 *
 * The spec this came from also carried backdrop-filter: blur(2px). Removed by request —
 * the gradient does the dissolving on its own, and the blur was costing a compositing
 * layer for it.
 *
 * z-index: -1 keeps it off the form. A generated box is out of flow and would otherwise
 * paint over the card; at -1 it paints after the section’s own background and before the
 * section’s content, so the artwork is behind it and the card in front.
 *
 * isolation: isolate on the section is what makes that true. Painting order puts
 * negative z-index children after the background of their *stacking context*, and a
 * position: relative element with z-index: auto is not one — without this the wash would
 * join the root stacking context and paint before the section’s background, where
 * nothing would ever see it.
 */
.page-template-page-contact main > .has-hero-wash-gradient-background {
	isolation: isolate;
}

.page-template-page-contact main > .has-hero-wash-gradient-background::after {
	content: "";
	position: absolute;
	z-index: -1;
	left: 0;
	right: 0;
	bottom: 0;
	height: 320px;
	background: linear-gradient(180deg, rgba(235, 241, 255, 0) 0%, #EBF1FF 100%);
	pointer-events: none;
}

/*
 * The layer has to escape the content measure, as on the pricing hero — and its margins
 * have to go, not just the side ones.
 *
 * The hero is a group with a block gap, so its children get a margin-block-start. On an
 * absolutely positioned child that offsets the box: the layer sat 24px low, which put its
 * centre 12px below the hero’s and carried the whole stage down with it. The icons were
 * 12px out against the artwork they are placed on, and the top and bottom of the stage
 * were being clipped unevenly.
 */
.page-template-page-contact main > .has-hero-wash-gradient-background > .smeweb-hero-fx {
	max-width: none;
	margin: 0;
}

/*
 * The stage is the artwork’s box, so a percentage inside it is a percentage of the
 * artwork and every position below can be read against the composition itself.
 *
 * The background fills the width, so that box is the hero’s width by the artwork’s own
 * ratio — no comparison of aspects, and nothing for JavaScript to measure. An earlier
 * pass at this used `cover` and had the script pass the hero’s box in as custom
 * properties so max() could work out which axis cover had chosen; filling the width
 * instead removed the question.
 */
.smeweb-hero-fx--contact .smeweb-hero-fx__stage {
	position: absolute;
	top: 0;
	left: 50%;
	transform: translateX(-50%);

	width: min(100%, 1920px);
	aspect-ratio: 1920 / 932;
}

/*
 * Anchored the same way the artwork is, in both regimes. A stage centred against a
 * bottom-anchored artwork would put every icon half the trim out of place.
 */
@media (min-width: 1600px) {
	.smeweb-hero-fx--contact .smeweb-hero-fx__stage {
		top: auto;
		bottom: 0;
	}
}

/*
 * Five icons from the media library. Squares, so aspect-ratio: 1 and one width each; the
 * top is worked back from the centre, which is why none of these are round numbers.
 *
 * Read off a reference that shows the artwork whole — full width and full height, so a
 * percentage of that frame is a percentage of the artwork and no correction is needed.
 *
 * Two earlier attempts got this wrong in opposite directions. The first read percentages
 * off a reference whose own hero cropped the sides, which put every icon low. The second
 * corrected that with a linear fit through two landmarks, which fixed the horizontal
 * placement but left the vertical between 2 and 6 percent low and shrank the icons by
 * about 15% along the way — the fit was applied to the sizes as well, where it did not
 * belong.
 */
.smeweb-hero-fx--contact .smeweb-hero-fx__item--facebook {
	left: 12.160%;
	top: 22.666%;
	width: 4.78%;
	aspect-ratio: 1;
	background-image: url("../../uploads/2026/08/Icon-2.png");
}

.smeweb-hero-fx--contact .smeweb-hero-fx__item--phone {
	left: 32.875%;
	top: 10.663%;
	width: 4.55%;
	aspect-ratio: 1;
	background-image: url("../../uploads/2026/08/Icon-3.png");
}

.smeweb-hero-fx--contact .smeweb-hero-fx__item--gmail {
	left: 40.880%;
	top: 22.046%;
	width: 4.78%;
	aspect-ratio: 1;
	background-image: url("../../uploads/2026/08/Icon-4.png");
}

.smeweb-hero-fx--contact .smeweb-hero-fx__item--maps {
	left: 10.295%;
	top: 39.503%;
	width: 4.55%;
	aspect-ratio: 1;
	background-image: url("../../uploads/2026/08/Icon-1.png");
}

.smeweb-hero-fx--contact .smeweb-hero-fx__item--line {
	left: 39.520%;
	top: 39.530%;
	width: 4.32%;
	aspect-ratio: 1;
	background-image: url("../../uploads/2026/08/Icon-5.png");
}
/* ------------------------------------------------------------------ *
 * 8. FAQ accordion (native details/summary — no JavaScript)
 * ------------------------------------------------------------------ */

/*
 * Constrained to 800px so the accordion rows remain balanced with the
 * heading above and easy to scan, without stretching out into empty space.
 * Responsive down to mobile viewports.
 */

.smeweb-faq__item {
	max-width: 800px;
	margin-inline: auto;
	width: 100%;
	border-radius: 16px;
	background-color: var(--wp--preset--color--surface);
	margin-bottom: 1rem;
	overflow: hidden;
	transition: background-color 0.2s ease, box-shadow 0.2s ease;
}

.smeweb-faq__item[open] {
	background-color: var(--wp--preset--color--base);
	box-shadow: 0 14px 34px rgba(20, 20, 43, 0.1);
}

/*
 * The question carries the weight, because it is the heading of the pair.
 *
 * It was 500 against an answer at 400 — one step, at 19.2px against 17.6, and the two
 * read as the same text in two colours. The site-wide pass that took every 600 down to
 * 500 flattened this on its way through; here the two-step gap is the point, so this one
 * goes back up.
 */
.smeweb-faq__item summary {
	list-style: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.35rem 1.75rem;
	font-weight: 600;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--contrast);
}

.smeweb-faq__item summary::-webkit-details-marker {
	display: none;
}

.smeweb-faq__item[open] summary {
	color: var(--wp--preset--color--primary);
}

.smeweb-faq__item summary::after {
	content: "";
	flex: 0 0 auto;
	width: 1.15rem;
	height: 1.15rem;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2314142b' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
	transition: transform 0.22s ease;
}

.smeweb-faq__item[open] summary::after {
	transform: rotate(45deg);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f2acd' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
}

/*
 * The core/details block places answer content as direct children of
 * <details>, so pad everything that is not the summary row.
 */
.smeweb-faq__item > :not(summary),
.smeweb-faq__answer {
	padding: 0 1.75rem 1.5rem;
	color: var(--wp--preset--color--muted);
	line-height: 1.75;
	margin-block: 0;
}

.smeweb-faq__item > :not(summary) + :not(summary) {
	padding-top: 0.75rem;
}

/* Responsive adjustments for mobile/tablet */
@media (max-width: 781px) {
	.smeweb-faq__item {
		border-radius: 14px;
		margin-bottom: 0.85rem;
	}

	.smeweb-faq__item summary {
		padding: 1.15rem 1.35rem;
		gap: 1rem;
		font-size: 1rem;
	}

	.smeweb-faq__item > :not(summary),
	.smeweb-faq__answer {
		padding: 0 1.35rem 1.35rem;
	}
}

@media (max-width: 480px) {
	.smeweb-faq__item {
		border-radius: 12px;
		margin-bottom: 0.75rem;
	}

	.smeweb-faq__item summary {
		padding: 1rem 1.15rem;
		gap: 0.75rem;
		font-size: 0.95rem;
	}

	.smeweb-faq__item > :not(summary),
	.smeweb-faq__answer {
		padding: 0 1.15rem 1.15rem;
		font-size: 0.875rem;
	}
}

/* ------------------------------------------------------------------ *
 * 9. Posts
 * ------------------------------------------------------------------ */

.smeweb-post-card {
	height: 100%;
	overflow: hidden;
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.smeweb-post-card:hover {
	transform: translateY(-5px);
	box-shadow: 0 20px 42px rgba(20, 20, 43, 0.14);
}

.smeweb-post-card .wp-block-post-featured-image img {
	aspect-ratio: 16 / 10;
	object-fit: cover;
	width: 100%;
	transition: transform 0.4s ease;
}

.smeweb-post-card:hover .wp-block-post-featured-image img {
	transform: scale(1.04);
}

.smeweb-post-card .wp-block-post-title a {
	text-decoration: none;
}

.smeweb-post-card .wp-block-post-title a:hover {
	color: var(--wp--preset--color--accent-dark);
}

/* "Read More »" link */
.smeweb-readmore,
a.wp-block-read-more.smeweb-readmore {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-weight: 500;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--accent-dark);
	text-decoration: none;
}

.smeweb-readmore::after,
a.wp-block-read-more.smeweb-readmore::after {
	content: "\00bb";
	transition: transform 0.18s ease;
}

.smeweb-readmore:hover::after,
a.wp-block-read-more.smeweb-readmore:hover::after {
	transform: translateX(3px);
}

/* ------------------------------------------------------------------ *
 * Latest posts — the scrolling list and the highlight card
 * ------------------------------------------------------------------ */

/*
 * The section takes the shell inset instead of the 1200px content measure, so it starts on
 * the same vertical as the navigation row and the footer bands.
 *
 * Measured before and after, because the two were further apart the wider the window got:
 * the footer content runs 1155, 1306, 1456, 1757 and 2384 at 1280, 1440, 1600, 1920 and
 * 2560, while a fixed 1200 measure stayed 1200 — 1184px narrower than the footer at 2560,
 * and 45px wider than it at 1280. --smeweb-shell-inset is the number all three already
 * share, so this is the same inset rather than a copy of it.
 *
 * margin-inline needs !important. The constrained layout writes margin-left and margin-right
 * as auto with it, and auto margins re-centre a child inside the padding — lifting the cap
 * on its own leaves the row centred at its old width.
 */
.smeweb-posts-latest {
	padding-inline: var(--smeweb-shell-inset);
}

.smeweb-posts-latest > * {
	max-width: none;
	margin-inline: 0 !important;
}

/*
 * The list scrolls in a box of its own, as the design has it, rather than running the
 * section as long as the number of posts.
 *
 * The height is the highlight card beside it (560) plus its own padding, so the two
 * columns finish level however many posts the query returns. Anything past that is behind
 * the scrollbar, which the design draws — hence a visible thin track rather than the
 * overlay scrollbar the platform would give it.
 */
.smeweb-post-scroll {
	/*
	 * Three stories, and the rest behind the scrollbar.
	 *
	 * Three rows is not a fixed number of pixels — the excerpts wrap to two or three lines
	 * depending on the copy and the width — so assets/js/post-list.js measures the rows and
	 * sets the height from them. This value is the fallback that applies until it runs, and
	 * for anyone without JavaScript: three typical rows at 1440.
	 */
	max-height: 620px;

	/*
	 * scroll rather than auto, so the track is there whether or not it is needed. The design
	 * draws it, and with auto the platform hides it until the list is touched.
	 */
	overflow-y: scroll;
	padding-right: var(--wp--preset--spacing--30);
	scrollbar-width: thin;
	scrollbar-color: #cfd3e8 transparent;
	overscroll-behavior: contain;
}

.smeweb-post-scroll::-webkit-scrollbar {
	width: 6px;
}

.smeweb-post-scroll::-webkit-scrollbar-track {
	background-color: #f1f0f8;
	border-radius: 999px;
}

.smeweb-post-scroll::-webkit-scrollbar-thumb {
	background-color: #cfd3e8;
	border-radius: 999px;
}

/*
 * A row, not a card. The design separates them with one hairline and nothing else, so the
 * border, the shadow and the fill the post cards carry elsewhere are all dropped here.
 *
 * !important on three of them because they arrive as inline styles from the block itself.
 * The alternative was editing the block attributes, which the database copy of the front
 * page would not have picked up.
 */
.smeweb-post-scroll .smeweb-post-row {
	border: 0 !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	background-color: transparent !important;
	padding: 0 !important;
}

/*
 * No rule between stories. The design puts it inside each one, across the text column,
 * between the excerpt and the Read More line — see the rule on .smeweb-post-meta below.
 * A story is separated from the next by the gap and by its own thumbnail starting, which is
 * what the design relies on.
 */

/*
 * spacing-40 between stories rather than spacing-30 — 40px against 24px.
 *
 * The footer row of each story now sits on its floor, so the only thing telling one story
 * from the next is this gap: at 24px the next thumbnail started closer to the rule above it
 * than the rule was to its own excerpt, which read as one long list rather than three items.
 *
 * The box grows with it and stays three stories, because assets/js/post-list.js measures the
 * rows rather than holding a height.
 */
.smeweb-post-scroll li + li {
	margin-top: var(--wp--preset--spacing--40);
}

/*
 * The thumbnail keeps its shape whether or not the post has one.
 *
 * Seven of the eight posts have no featured image today, and the block renders nothing at
 * all in that case — which collapsed the column and left those rows a different shape from
 * the one with a picture. A tinted box of the right proportions holds the slot open. It is
 * visibly empty on purpose: it is a missing image, not a decoration, and it disappears the
 * moment one is set.
 */
.smeweb-post-scroll .wp-block-post-featured-image {
	margin: 0;
}

.smeweb-post-scroll .wp-block-post-featured-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.smeweb-post-scroll .wp-block-column:first-child:not(:has(img))::before {
	content: "";
	display: block;
	aspect-ratio: 3 / 2;
	border-radius: 20px;
	background-color: var(--wp--preset--color--surface-2);
}

/*
 * 24px for the title and 18px for the excerpt, as asked, and px rather than the presets
 * because the presets are not what they say here: small resolves to 17.6 rather than the
 * 15 its 0.9375rem asks for, so the size arrives from the database styles and not from
 * theme.json. A rem would be a guess at the root, and a preset would be a guess at the
 * database.
 *
 * !important on both, because each block carries its size as has-medium-font-size or
 * has-x-small-font-size, which core writes with it.
 *
 * The title sits tight to its excerpt, as the design has it.
 */
.smeweb-post-scroll .wp-block-post-title {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: 1.5rem !important;
	line-height: 1.4;
}

.smeweb-post-scroll .wp-block-post-excerpt__excerpt,
.smeweb-post-scroll .wp-block-post-excerpt {
	/*
	 * 18px at weight 400, both asked for, and the second one is a decision rather than a
	 * default — leave it alone unless it is revisited on purpose.
	 *
	 * At 400 the vowel and the tone mark stacked on ชั้น touch each other at DPR 1: a large
	 * monitor at 100%. A laptop at 125% has the device pixels to hold them apart, so it only
	 * shows on some screens. 300 separates them at 18px and was tried here first; 400 was chosen
	 * over it with that known.
	 *
	 * Weight is the only lever, not size — the marks sit at a fixed position relative to the
	 * letter, so how thick they are is all that decides whether they bridge. If this is ever
	 * revisited: blow the DPR-1 render up with nearest-neighbour and look. Counting bands of ink
	 * cannot answer it, because ช and น have gaps of their own.
	 */
	font-size: 1.125rem !important;
	font-weight: 400;
}


/*
 * Three lines, cut by lines rather than by words.
 *
 * The block trims by word count, which does nothing useful in Thai: there are no spaces to
 * count, so a whole sentence is one word and the excerpt came out a single short line
 * whatever number was set. The block is given a generous length and the clamp does the
 * cutting, which also means the three rows end level.
 */
.smeweb-post-scroll .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	overflow: hidden;
	color: var(--wp--preset--color--muted);
	line-height: 1.7;
}

/*
 * The rule the design draws: across the text column, over the Read More line. It sits on
 * the footer of each story rather than between two of them, which is why it stops at the
 * text column and does not run back under the thumbnail.
 */
/*
 * The footer row sits on the floor of its story, level with the foot of the thumbnail,
 * rather than trailing the excerpt.
 *
 * The thumbnail is the taller of the two columns — 3:2 against two or three lines of text —
 * so there was a gap under the Read More line that grew as the excerpt got shorter. An auto
 * top margin puts that gap above the rule instead of below the row.
 *
 * Two things have to be true for that margin to have anywhere to go: the column has to be
 * a column-direction flex box, and it has to stretch. The block writes
 * align-self: flex-start for its top alignment, which is exactly what would have left the
 * column its content height and the auto margin nothing to absorb.
 *
 * The excerpt keeps a margin of its own so the rule never lands against it when the text
 * runs long and the auto margin collapses to nothing.
 */
.smeweb-post-scroll .smeweb-post-row .wp-block-column:last-child {
	align-self: stretch;
	display: flex;
	flex-direction: column;
}

/*
 * The excerpt gives up its top margin, so the gap under the title is the title’s own 12px
 * and nothing else. It was 36: 12 from the title plus 24 the flow layout puts above every
 * sibling. An earlier pass zeroed both margins on this block and the bottom one had to come
 * back for the rule below it, which is how the top one returned as well.
 */
.smeweb-post-scroll .wp-block-post-excerpt {
	margin-top: 0;
	margin-bottom: var(--wp--preset--spacing--30);
}

.smeweb-post-scroll .smeweb-post-meta {
	margin-top: auto;
	border-top: 1px solid var(--wp--preset--color--outline);

	/*
	 * spacing-30 rather than spacing-20 above the row, which lifts the rule off the Read More
	 * line — 27px of air over it instead of 14. The auto margin above takes the difference out
	 * of the space over the rule, so the row stays on the floor of the story.
	 */
	padding-top: var(--wp--preset--spacing--30);
}

/* 16px on the link, over the x-small it inherits — core writes that preset with !important. */
.smeweb-post-scroll .smeweb-post-meta .wp-block-read-more {
	font-size: 1rem !important;
}

.smeweb-post-scroll .smeweb-post-meta p,
.smeweb-post-scroll .smeweb-post-meta time {
	margin: 0;
}



.smeweb-post-meta-right {
	column-gap: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--muted);
}

/*
 * The date and the comment count read as one line with a dot between them, which is what
 * the design draws.
 *
 * The dot hangs off the end of the first item, not the start of the second, and that is not
 * a style choice. Written as `> * + *::before` it landed on the very pseudo-element the
 * comment count uses for its own opening bracket, and being later in the file it won — the
 * count rendered as "0)" with the word missing.
 */
.smeweb-post-meta-right > *:first-child::after {
	content: "•";
	margin-left: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--outline);
}

/* ---- the highlight card ---- */

/*
 * The card is as tall as the list beside it, whatever the list comes to.
 *
 * Columns stretch to the tallest of them, so the column holding this one already has the
 * list’s height — the work is passing that height down to the cover, which needs a definite
 * height above it before a percentage means anything. Hence the chain: the wrapper, the
 * query, the post template and the slide’s own list item all take the full height, and the
 * cover then fills it.
 *
 * !important on the cover, because minHeight is on the block’s style attribute — 560px,
 * which was the fixed height this card used to have.
 */
.smeweb-highlight {
	position: relative;
	height: 100%;
}

.smeweb-highlight > .wp-block-query,
.smeweb-highlight .wp-block-post-template,
.smeweb-highlight .wp-block-post-template > li {
	height: 100%;
}

.smeweb-highlight-slide {
	min-height: 100% !important;
}

/*
 * The picture is the card, with the copy over it — a cover with useFeaturedImage, not an
 * image block under a heading. The dim is the design’s: enough to hold white type over a
 * photograph without turning it grey.
 */
.smeweb-highlight-slide {
	overflow: hidden;
}

.smeweb-highlight .wp-block-post-template,
.smeweb-highlight .wp-block-query {
	margin: 0;
}

/*
 * 34px rather than the xx-large preset it comes in on. At 44 a four-line title covered the
 * face in the photograph and ran past where the design has it finishing; the design sets it
 * a little over twice the label.
 *
 * !important because the size arrives as has-xx-large-font-size, which core writes with it.
 */
.smeweb-highlight-title {
	margin-top: var(--wp--preset--spacing--30);
	/*
	 * 34px on a desktop as before, 22 on a phone. It was fixed at 34, and at 390 that made the
	 * title 229px tall inside a 420px card — more than half of it. The clamp keeps the size that
	 * was chosen for the wide case and gives the narrow one a floor.
	 */
	font-size: clamp(1.375rem, 1rem + 2vw, 2.125rem) !important;
	line-height: 1.35;
	max-width: 20ch;
	text-wrap: balance;
}

/*
 * The label wears the uploaded pin on a white disc.
 *
 * Painted, not masked. The file carries the brand gradient itself — magenta into blue on a
 * transparent ground — and a mask throws colour away and keeps only the shape, which would
 * have left a flat silhouette. So the disc supplies the white and the file supplies both the
 * shape and its colours.
 *
 * That is the other way round from what was here: a gradient disc with a white spark masked
 * out of it, drawn in CSS with no asset at all. Both the disc rule and the spark on ::after
 * go with it — nothing else used them.
 */
.smeweb-highlight-label {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin: 0;
}

.smeweb-highlight-label::before {
	content: "";
	flex: 0 0 auto;
	width: 1.6em;
	height: 1.6em;
	border-radius: 50%;
	background-color: #fff;
	background-image: url("../../uploads/2026/08/Pin-Icon.png");
	background-repeat: no-repeat;
	background-position: center;

	/*
	 * 0.95em of a 1.6em disc, which leaves the mark about a third of the disc clear on every
	 * side. The upload is 72px square against the ~17px it draws at, so there is room for a 4x
	 * screen without it softening.
	 */
	background-size: 0.95em 0.95em;
}

/* ---- the two controls ---- */

/*
 * Sat on the card rather than under it, bottom left, where the design puts them. They are
 * on the wrapper and not inside the cover because the cover is inside the loop — one pair
 * of buttons steering five slides.
 */
.smeweb-highlight-nav {
	position: absolute;
	z-index: 2;
	left: var(--wp--preset--spacing--40);
	bottom: var(--wp--preset--spacing--40);
	display: flex;
	gap: 0.6rem;
}

.smeweb-highlight-nav button {
	width: 2.5rem;
	height: 2.5rem;
	padding: 0;
	border: 1px solid rgba(255, 255, 255, 0.55);
	border-radius: 50%;
	background-color: rgba(255, 255, 255, 0.16);
	background-repeat: no-repeat;
	background-position: center;
	background-size: 0.85rem 0.85rem;
	cursor: pointer;
	transition: background-color 0.18s ease, border-color 0.18s ease;
}

.smeweb-highlight-nav button:hover {
	border-color: #fff;
	background-color: rgba(255, 255, 255, 0.3);
}

.smeweb-highlight-prev {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 4 7 12l8 8'/%3E%3C/svg%3E");
}

.smeweb-highlight-next {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 4l8 8-8 8'/%3E%3C/svg%3E");
}

@media (max-width: 781px) {
	/*
	 * Stacked, the list gives up its own scrollbar — a scrolling box inside a scrolling page
	 * is a fight on a touchscreen. But letting all eight rows out ran the section to 4358px on
	 * a 390 viewport, so it shows the same three the desktop list does and stops. The button
	 * above goes to the full archive.
	 */
	.smeweb-post-scroll {
		max-height: none;
		overflow-y: visible;
		padding-right: 0;
	}

	.smeweb-post-scroll li:nth-child(n + 4) {
		display: none;
	}

	.smeweb-highlight-slide {
		min-height: 420px !important;
	}
}

.smeweb-post-card .wp-block-read-more {
	color: var(--wp--preset--color--accent-dark);
	font-weight: 500;
	text-decoration: none;
}

.smeweb-post-card .wp-block-read-more:hover {
	text-decoration: underline;
}

/* Post meta row */
.smeweb-post-meta {
	font-size: 0.8rem;
	color: var(--wp--preset--color--muted);
}

/* Category filter pills */
.smeweb-pills .wp-block-button__link {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	padding: 0.5rem 1.15rem;
}

/*
 * The core Categories block renders a plain list; reshape it into the pill
 * row from the design. Links stay real category archives.
 */
.smeweb-cat-pills {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.smeweb-cat-pills li {
	margin: 0;
}

.smeweb-cat-pills a {
	display: inline-block;
	padding: 0.45rem 1.1rem;
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
	text-decoration: none;
	transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.smeweb-cat-pills a:hover,
.smeweb-cat-pills .current-cat a {
	background-color: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: #fff;
	text-decoration: none;
}

/*
 * The blog hero wears the supplied artwork.
 *
 * Two layers, artwork over gradient. The gradient is not dead weight: it is what fills the
 * band while the file is still loading and what is left if the file ever goes missing, and a
 * gradient costs nothing to keep.
 *
 * The upload is a 1920×814 PNG at 713KB, which is not a file to put behind a hero on a site
 * already carrying 9.8MB of oversized images. This is the same artwork as WebP at q85: 29KB,
 * a 96% saving, and a maximum channel difference of 5 with 0.02% of channels off by more
 * than 3 — measured against the PNG, not assumed. Its alpha reads 254 with no pixel under
 * 250, so it is opaque and covers the gradient completely.
 *
 * 100% 100% rather than cover, which is the one place non-uniform scaling is the right answer.
 * The artwork is 2.36:1 and the band runs 1017px tall at 1440, so cover scaled it to 2400 wide
 * and cropped 480px off each side — taking the pink blooms at the left and right edges with it,
 * which are the whole composition. Stretching an out-of-focus wash distorts nothing the eye can
 * see and keeps the blooms at the edges and the fade at the foot where they were drawn.
 *
 * Two classes and !important on every line, and both are needed. Core writes the gradient
 * preset as `background: var(--…) !important` — the shorthand, which resets every background
 * longhand to its initial value and marks those important too, so a plain rule here lost
 * background-size and background-position outright: computed read `auto` and `0% 0%` while
 * the stylesheet said cover and center top. Found with CSS.getMatchedStylesForNode rather
 * than guessed at. !important alone would not settle it either — both rules would be
 * important at one class each, and source order decides that, with core printing after the
 * theme. The second class puts this above it for good.
 *
 * The gradient is restated as the lower layer for the same reason: core supplies it through
 * the declaration this one replaces, so it has to be named here or it is gone.
 */
/*
 * smeweb-wash is the same ground under another name, because the ตัวอย่างเว็บไซต์ page was
 * asked for with the blog header's background. Listed here rather than copied so the two
 * cannot drift: everything the long note above works out — the stretch, the two classes, the
 * restated gradient — applies to both or to neither.
 *
 * Two classes on this one too. One would lose to core's important gradient shorthand exactly
 * as the blog rule did.
 */
/*
 * A section that opens a page does not need the gap that separates it from the section above.
 *
 * smeweb-showcase carries spacing|70 — 128px at 1440 — which is right on the pricing page,
 * where it follows the package table. On the ตัวอย่างเว็บไซต์ page it is the first thing under
 * the header, so those 128px were empty wash and the eyebrow sat 152px down.
 *
 * !important because the pattern writes its padding as an inline style, and the pattern is
 * shared: editing it would move the pricing page too. Scoped to a first child of the wash so
 * it can only ever affect a section that actually opens a page.
 */
.smeweb-wash > .smeweb-showcase:first-child {
	padding-top: var(--wp--preset--spacing--50) !important;
}
.wp-block-group.smeweb-blog-hero,
.wp-block-group.smeweb-wash {
	background-image: url("assets/img/blog-hero.webp"), var(--wp--preset--gradient--hero-wash) !important;
	background-size: 100% 100% !important;
	background-position: center top !important;
	background-repeat: no-repeat !important;
}

/*
 * The picture reaches the frame.
 *
 * The card carried 12px of padding, so the picture floated in a white margin inside the
 * gradient hairline. With that gone the picture is flush on three sides and the card clips it
 * to its own 22px corners — overflow rather than a radius on the picture, because the radius
 * has to be 22 on the outside corners and 0 where it meets the words, which one value cannot
 * say.
 */
.smeweb-trending .smeweb-gradient-border {
	overflow: hidden;
}

@media (min-width: 782px) {
	.smeweb-trending .wp-block-post-featured-image img {
		border-radius: 0 !important;
	}
}

/*
 * The description holds three lines, and all of them reach the right edge.
 *
 * It was capped at 34rem, which is a reading measure and was there to force the wrap: on a wide
 * window the whole excerpt fitted on one line and the card read short. But the column is 1155px
 * at 1920, so a 544px paragraph left 611px of white beside it while the heading above ran the
 * full width — the eye read the card as half empty rather than as a bounded line of prose.
 *
 * The clamp is what forces the wrap now, and it always was: two lines of the column instead of
 * two lines of 544px simply shows twice as much of the excerpt. min-height holds the two open
 * when a post has a short one, so the card is the same height whatever is in it.
 */
/*
 * Two lines, and both of them run the full width of the column.
 *
 * text-wrap is turned off for this one alongside every other clamped card, up beside the rule
 * it excepts. Balance is right for a standalone paragraph, wrong for a clamped one: it evens
 * every line including the ones the clamp hides, so at 1850 it produced 941/932/919 inside a
 * 1086 box and left about 150px of white down the right of a card whose picture bleeds flush
 * to the border on the left. The eye read that as the card being lopsided, and it was.
 *
 * Filling normally gives 1085/1074 and then a short line, and the short line is the one the
 * clamp drops — so both visible lines reach the edge and the ragged one is never shown.
 *
 * min-height holds the two open when a post has a short excerpt, so every post makes a card
 * the same height — the picture is cropped to whatever the words come to, so without this one
 * thin post would shrink the whole row.
 */
.smeweb-trending .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	min-height: calc(2 * 1.7em);
	line-height: 1.7;
}

/*
 * The words set the height of this card and the picture fills whatever that comes to.
 *
 * Narrowing the column to 32% was meant to hand the height to the text, and at 1440 it did.
 * At 1920 it did not: height: 100% on the picture is a cyclic dependency — the row height
 * depends on the item and the item on the row — so the browser falls back to the intrinsic
 * height the 4:3 gives it, 416px against 297 of text, and the picture was setting the height
 * again. Measured, not assumed: the card went up to 440 at 1920 while going down to 390 at
 * 1440.
 *
 * Taking the figure out of flow removes it from the calculation altogether. The column keeps
 * its 32% width and stretches to the line, the text column alone decides how tall that line
 * is, and the picture is cropped to fit it.
 */
@media (min-width: 782px) {
	.smeweb-trending .wp-block-column:first-child {
		align-self: stretch;
		position: relative;
	}

	.smeweb-trending .wp-block-post-featured-image {
		position: absolute;
		inset: 0;
		margin: 0;
	}

	.smeweb-trending .wp-block-post-featured-image img {
		width: 100%;
		height: 100%;
		aspect-ratio: auto;
		object-fit: cover;
	}
}

/*
 * The picture column widens on the way down to the stack.
 *
 * 32% of a 1440 card is 410px and reads well; 32% of a 735 card is 212px against 409 of height,
 * a vertical strip. The card only stacks below 782, so the band between there and about 1100 is
 * where the proportion falls apart. 40% gives 294px at 782 and 366 at 1024.
 *
 * !important because the width is an inline style on the column, written from the block’s own
 * attribute, and an inline style outranks every selector.
 */
@media (min-width: 782px) and (max-width: 1100px) {
	.smeweb-trending .wp-block-column:first-child {
		flex-basis: 40% !important;
	}
}

/*
 * Stacked there is no card height to fill, so the 4:3 the block asks for is what it gets —
 * and 4:3 of the full card width is a very tall picture over a short paragraph. 21rem caps
 * it. 782px is core’s own breakpoint for stacking columns, so the two halves meet exactly.
 */
@media (max-width: 781px) {
	.smeweb-trending .wp-block-post-featured-image img {
		max-height: 21rem;
		object-fit: cover;
	}
}

/*
 * The rule over Read More sits closer to it.
 *
 * There was 73px between the excerpt and the link: 24 down to the rule, then the rule’s own
 * 24 below plus the 24 the flow layout puts over every sibling, which do not collapse here.
 * 24 above and 12 below reads as a divider belonging to the line under it rather than a band
 * of empty space, and takes 36px out of the card.
 */
.smeweb-trending .wp-block-separator {
	margin-block: var(--wp--preset--spacing--30) 0;
}

.smeweb-trending .wp-block-read-more {
	margin-top: var(--wp--preset--spacing--20);
}

/*
 * The two gaps around the search field are one number.
 *
 * They were 40px above it and 104 below, which read as the field belonging to the headline
 * and the card being somewhere else entirely. Both are 32 now.
 *
 * Above is set by the headline’s own bottom margin, which collapses against the 24px the
 * layout puts over every sibling and wins at 32.
 *
 * Below was three numbers added together — the field’s bottom margin, the header group’s
 * bottom padding and the section’s top padding, 24 + 40 + 40. The first two are zero now and
 * the section’s 32 is the whole of it, so the gap is one value to change rather than a sum to
 * work back through.
 */
.smeweb-blog-hero .wp-block-search {
	margin-bottom: 0;
}

/*
 * And the 24px the constrained layout puts over every sibling, which is the third number in
 * that sum and the one that is easiest to miss: zeroing the two paddings left the gap at 56
 * rather than the 32 the arithmetic said. The section owns the whole distance now.
 */
.smeweb-blog-hero > .smeweb-trending {
	margin-top: 0;
}

/*
 * On the search page the wash ends where the results begin, so its own root padding is one
 * gap too many: 32 under the field, then 24 here, then the 40 the results section opens with.
 * 96px between a search field and the first card it found. Zeroed, which leaves 72 — the
 * section break still reads, without a hole in it.
 *
 * Only on search. On the blog the same padding sits under the trending card, where it is the
 * foot of the band and wanted.
 */
.search .smeweb-blog-hero {
	padding-bottom: 0;
}

/*
 * Trending Now runs to the same verticals as Recent Blog under it.
 *
 * It was on the 1200px content measure — 120–1320 of a 1440 window against the 67–1373 the
 * grid, the header and the footer share, and 360–1560 against 82–1838 at 1920, so the gap
 * grew with the window. Same --smeweb-shell-inset as the rest of the shell.
 *
 * margin-inline needs !important here for the reason it does in every other place this is
 * done: the constrained layout writes the side margins as auto, and auto margins re-centre
 * the child at its old width.
 */
.smeweb-trending {
	padding-inline: var(--smeweb-shell-inset);
}

.smeweb-trending > * {
	max-width: none;
	margin-inline: 0 !important;
}

/*
 * Recent Blog runs to the same verticals as the picks band below it.
 *
 * It was on the 1200px content measure while the band is the window less the shell inset —
 * 1306 of a 1440 window, 1757 of 1920 — so the two sections started 53px apart at 1440 and
 * 278px apart at 1920. Same inset, not a copy of it: --smeweb-shell-inset is the number the
 * navigation row, the footer bands, the picks band and the front page post list already
 * share, so they move together when it changes.
 *
 * margin-inline needs !important for the reason it does everywhere else this is done: the
 * constrained layout writes the side margins as auto, and auto margins re-centre a child at
 * its old width, so lifting the cap alone changes nothing.
 */
/*
 * Everything below that shapes a card is written for two sections, not one.
 *
 * The related-posts band under an article was asked for with the same card the blog grid
 * draws — 6px corners, no border, the softer shadow, the rule above a bottom-aligned Read
 * More. That is fifteen rules deep, so the selectors take :is() rather than a second copy;
 * :is() of two single classes has the same specificity as one, so nothing else moves.
 *
 * The two rules below widen the section to the shell inset and lift the constrained cap off
 * its children. They were held back from the related band at first, on the reasoning that a
 * page of cards wants the extra width and a band inside an article does not. That was wrong:
 * asked side by side, the related cards read as a squeezed copy — 282px against the 420 the
 * Recent Blog row gives — so the two sections now share these as well and the card is the same
 * card at the same size in both places.
 */
:is(.smeweb-blog-grid, .smeweb-related) {
	padding-inline: var(--smeweb-shell-inset);
}

:is(.smeweb-blog-grid, .smeweb-related) > * {
	max-width: none;
	margin-inline: 0 !important;
}

/*
 * The row of cards steps down before it gets to a phone.
 *
 * Core only breaks this grid at 600px, straight from four columns to one, so every width
 * between 601 and 1100 held four: 150px cards at 768, which is a thumbnail with a headline
 * squeezed under it. Widening the section above made that 15px worse, so it is fixed here
 * rather than left as it was found.
 *
 * Three columns to 1100 and two to 900 keeps the card between 225 and 350px the whole way
 * down. Both queries start at 601 so core keeps the single column it already draws below
 * that — these selectors are two classes against its one and would otherwise win there too.
 */
@media (min-width: 601px) and (max-width: 1100px) {
	:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-template {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (min-width: 601px) and (max-width: 900px) {
	:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-template {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/*
 * Recent Blog — the card grid, to the supplied design.
 *
 * The picture is meant to run the full width of the card, and it was inset by 45.6px on
 * each side. That padding is not ours and not in the markup: core ships
 * :where(.wp-block-group.has-background) { padding: 1.25em 2.375em }, and the card has a
 * background, so it inherits it. Found with CSS.getMatchedStylesForNode — two passes of
 * walking document.styleSheets had come back empty, which is worth remembering next time a
 * scan says "no rule does this".
 *
 * So the card gives its padding up and the group inside keeps its own, which is where the
 * copy should be inset anyway.
 */
:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card {
	padding: 0;
	border: 0 !important;
	border-radius: 6px !important;
	box-shadow: 0 2px 12px rgba(20, 20, 43, 0.07) !important;
}

:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card:hover {
	box-shadow: 0 12px 28px rgba(20, 20, 43, 0.12) !important;
}

/*
 * The card is a column so the Read More line can sit on its floor. The grid gives every
 * card the height of the tallest, and without this the link trailed the title and the row
 * looked ragged — the same fix the list on the front page needed.
 */
:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card > .wp-block-group {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card {
	display: flex;
	flex-direction: column;
}

:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-meta-right {
	margin-bottom: var(--wp--preset--spacing--20);
}

/*
 * Two lines of title, clamped. The design shows every card the same shape with an ellipsis
 * where a headline runs long, and it is what keeps the meta line and the rule on one
 * baseline across the row.
 */
/*
 * Two lines of title, clamped on the link inside the heading rather than on the heading.
 *
 * It has to go there. The card is a flex column so the Read More line can sit on its floor,
 * which makes the heading a flex item — and Chrome blockifies display: -webkit-box on a flex
 * item to flow-root, so the clamp was set and ignored. !important made no difference, because
 * nothing was overriding it: computed read line-clamp 2, box-orient vertical, display
 * flow-root. The link is not a flex item, so the same three declarations work on it.
 */
:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-title {
	/*
	 * The title sits tight to the description under it — 12px, where it was 24 back when the
	 * Read More rule was the next thing down and needed the air. The declared gap still has to
	 * be here rather than left to the auto margin below: the title is clamped to two lines and
	 * the tallest card in a row has no slack for that margin to open.
	 */
	margin: 0 0 var(--wp--preset--spacing--20);
	line-height: 1.5;
}

/*
 * The description under a card title.
 *
 * Three lines, cut by lines rather than by words, for the reason spelled out beside the
 * block: the count the block uses is words, and Thai gives it nothing to count. Clamping
 * also lands every card in a row on the same height, which is what keeps the Read More rules
 * across a row on one line.
 *
 * The bottom margin is the gap over that rule. It cannot come from the auto margin on the
 * Read More block, which has no slack left in the tallest card of a row.
 */
:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-excerpt {
	margin: 0 0 var(--wp--preset--spacing--30);
}

/*
 * Two lines, because two is what the posts have.
 *
 * The box was open for three and the cards were showing one and two, which read as the grid
 * being broken. It is not: the excerpts run 56, 62, 62, 71, 73, 107 and 375 characters, and at
 * this column width 107 comes to two lines. Three was a box waiting for words nobody had
 * written.
 *
 * min-height holds both lines open so every card in a row is the same height whatever is in it.
 * The shortest excerpts still fill only one of the two — that is a writing job, not a CSS one,
 * and filling it from the article body is not available: four of the eight posts still carry
 * placeholder text, so the cards would advertise "sample content for testing the theme".
 */
:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	min-height: calc(2 * 1.7em);
	line-height: 1.7;
}

/* The block ships a "Read more" of its own under the text; the card already has one. */
:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-excerpt__more-text {
	display: none;
}

:is(.smeweb-blog-grid, .smeweb-related) .wp-block-post-title a {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

/*
 * The rule over the Read More line spans the card. The block sizes itself to its words —
 * 83px of a 282px card — so the border stopped under the label and read as an underline
 * rather than a divider. align-self rather than a width, since the card is a flex column and
 * stretch is what that means here.
 */
:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card .wp-block-read-more {
	align-self: stretch;
	width: auto;
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--20);
	border-top: 1px solid var(--wp--preset--color--outline);
}

:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card .wp-block-post-featured-image {
	margin: 0;
}

/*
 * A card with no picture holds the band open, the same tinted 16:10 box the list on the
 * front page uses. Without it a card with a picture and a card without are different shapes,
 * and in a four-across grid that is the first thing the eye catches.
 */
:is(.smeweb-blog-grid, .smeweb-related) .smeweb-post-card:not(:has(.wp-block-post-featured-image))::before {
	content: "";
	display: block;
	aspect-ratio: 16 / 10;
	background-color: var(--wp--preset--color--surface-2);
}

/*
 * The band is as wide as the closing banner, which is the page gutter and nothing more.
 *
 * This rule used to inset it by --smeweb-shell-inset to match the footer, on the reasoning
 * that the footer was the measure to follow. That was the wrong reference: the other two
 * bands on this site are not inset at all. Measured at 1440, the consultation band on
 * /contact/ and the closing cover on the front page both run 24→1416, and this one ran
 * 67→1373 — 1306 against 1392, so the picks band was the only one of the three that did not
 * line up, and the gap grew with the window because the inset carries 3vw.
 *
 * spacing|30 rather than a bare 24px because it is the value theme.json sets as the root
 * padding, so the band keeps tracking the page gutter if that ever changes. The root
 * padding custom property is not an option — WordPress writes it on .wp-site-blocks, not
 * on :root, and it reads as empty here.
 *
 * margin-inline still needs !important on the band: the constrained layout writes the side
 * margins as auto, and auto margins re-centre the child inside the new padding.
 */
.smeweb-picks-shell {
	padding-inline: var(--wp--preset--spacing--30);
}

.smeweb-picks-shell > .smeweb-picks {
	margin-inline: 0 !important;
}

/*
 * The copy sits in the middle of the band rather than at the top of it.
 *
 * The row of cards sets the height — 514px against about 250 of heading and paragraph — so
 * left at the top the column read as half empty. Centring it balances the two sides without
 * inventing anything to fill the space with.
 */
.smeweb-picks > .wp-block-columns > .wp-block-column:first-child {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

/*
 * Editor’s picks — the card row inside the blue band, to the supplied design.
 *
 * The cards are the same object as the ones in the grid above, so the rules read the same:
 * the padding core gives any group with a background comes off, the picture runs the full
 * width, the title clamps to two lines on its link, and the Read More line sits on the
 * floor under a rule that spans the card.
 */
.smeweb-picks .smeweb-post-card {
	display: flex;
	flex-direction: column;
	padding: 0;
	border: 0;
	border-radius: 6px !important;
}

.smeweb-picks .smeweb-post-card > .wp-block-group {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

.smeweb-picks .smeweb-post-card .wp-block-post-featured-image {
	margin: 0;
}

.smeweb-picks .smeweb-post-card:not(:has(.wp-block-post-featured-image))::before {
	content: "";
	display: block;
	aspect-ratio: 16 / 10;
	background-color: var(--wp--preset--color--surface-2);
}

/*
 * The meta line holds one line in the narrower card.
 *
 * At three cards to a track the card came to 238px, which leaves 190 inside its padding, and
 * the date and the comment count need about 200 at the x-small preset — so both wrapped and
 * the line became four. 0.8125rem and no wrapping fits them in 180.
 *
 * rem, not the 13px it was written as. The number is the same at a default root and now
 * follows a reader who has set their browser larger, which px could not: measured 13px against
 * 13px at a 24px root, so this line was the one piece of the card that ignored them entirely.
 * nowrap stays on the children — it stops a date breaking across lines mid-way — and the
 * container is already a wrapping flex row, so when the words no longer fit they stack instead
 * of spilling out of the card.
 */
.smeweb-picks .smeweb-post-meta-right {
	margin-bottom: var(--wp--preset--spacing--20);
	font-size: 0.8125rem;
}

/*
 * No nowrap, because it turned into an overflow the moment the size stopped being fixed.
 *
 * It was holding the date and the comment count each on one line, which is right at 13px in a
 * 180px card. In rem the same line is 19.5px when a reader sets their browser larger, and a
 * nowrap item wider than its card does not wrap — it spills. Measured once on a comment count
 * outside the card at a 24px root.
 *
 * Letting them wrap costs nothing at the default size, where each still fits on its own line,
 * and at any larger size they break rather than escape. The container is a wrapping flex row,
 * so the two of them stack before either has to break internally.
 */
.smeweb-picks .smeweb-post-meta-right > * {
	font-size: inherit !important;
}

.smeweb-picks .wp-block-post-title {
	/* Tight to the description under it, as on the Recent Blog card. */
	margin: 0 0 var(--wp--preset--spacing--20);
	line-height: 1.5;
}

/*
 * The description, two lines and clamped — now actually the same treatment the Recent Blog
 * card gets. It was three here, and the comment that set it claimed the grid card was three
 * too; the grid clamps at two, so the two cards were a line apart the whole time.
 *
 * min-height with it, as the grid has, so a description that comes in under two lines still
 * holds the box open and the rule above Read More sits at the same height on every card.
 */
.smeweb-picks .wp-block-post-excerpt {
	margin: 0 0 var(--wp--preset--spacing--30);
}

.smeweb-picks .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	min-height: calc(2 * 1.7em);
	line-height: 1.7;
}

.smeweb-picks .wp-block-post-excerpt__more-text {
	display: none;
}

/* On the link, not the heading — the heading is a flex item, and Chrome blockifies
   -webkit-box on one of those to flow-root. Same reason as the grid above. */
.smeweb-picks .wp-block-post-title a {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

.smeweb-picks .smeweb-post-card .wp-block-read-more {
	align-self: stretch;
	width: auto;
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--20);
	border-top: 1px solid var(--wp--preset--color--outline);
}

/*
 * The row scrolls sideways and finishes inside the band, three whole cards in view.
 *
 * It used to hang past the band’s right padding so the third card was cut, which is what the
 * design showed — that was dropped on purpose: three whole cards was asked for instead, and
 * the buttons below already say there is more.
 *
 * Cards take a third of the track and do not shrink, so three sit in view whatever the window
 * does. scroll-snap keeps a card edge against the left after a swipe.
 */
.smeweb-picks .wp-block-post-template {
	display: flex;
	flex-wrap: nowrap;
	gap: var(--wp--preset--spacing--30);
	margin: 0;

	/*
	 * stretch, not the centre core writes for a flex layout.
	 *
	 * It never showed until the cards carried a description: every card was the same height,
	 * so centring them and stretching them looked identical. With a description the height
	 * follows the text — 429px at three lines, 405 at two — and centring sat the short ones
	 * 12px low with their tops out of line. Stretch puts every card on the height of the
	 * tallest, which is what the card is already built for: it is a flex column with the
	 * Read More line on an auto margin.
	 */
	align-items: stretch;

	max-width: none;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	overscroll-behavior-x: contain;

	/* the design draws no track here, and the band has no room for one */
	scrollbar-width: none;
}

.smeweb-picks .wp-block-post-template::-webkit-scrollbar {
	display: none;
}

/*
 * min-width: 0 so the basis is what decides the width.
 *
 * A flex item will not go below its min-content width without it, and the meta line above is
 * set not to wrap — which made the card’s min-content 238px. At 1280 the basis works out to
 * 206 and the cards refused to shrink to it, so they overflowed and the third was cut after
 * all. The media query below drops to two cards rather than letting them squeeze.
 */
.smeweb-picks .wp-block-post-template > li {
	flex: 0 0 calc((100% - 2 * var(--wp--preset--spacing--30)) / 3);
	min-width: 0;
	margin: 0;
	scroll-snap-align: start;

	/* The item is stretched by the track; this passes that height to the card inside it. */
	display: flex;
}

.smeweb-picks .wp-block-post-template > li > .smeweb-post-card {
	flex: 1 1 auto;
}

/*
 * Two cards below 1300px. Three would take the card under the width its own meta line needs,
 * and a date that wraps in the middle looks worse than one card fewer.
 */
@media (max-width: 1300px) and (min-width: 782px) {
	.smeweb-picks .wp-block-post-template > li {
		flex-basis: calc((100% - var(--wp--preset--spacing--30)) / 2);
	}
}

/* ---- the two controls ---- */

.smeweb-picks-nav {
	display: flex;
	gap: 0.6rem;
	margin-top: var(--wp--preset--spacing--40);
}

.smeweb-picks-nav button {
	width: 2.5rem;
	height: 2.5rem;
	padding: 0;
	border: 1px solid rgba(255, 255, 255, 0.55);
	border-radius: 50%;
	background-color: rgba(255, 255, 255, 0.16);
	background-repeat: no-repeat;
	background-position: center;
	background-size: 0.85rem 0.85rem;
	cursor: pointer;
	transition: background-color 0.18s ease, border-color 0.18s ease, opacity 0.18s ease;
}

.smeweb-picks-nav button:hover:not(:disabled) {
	border-color: #fff;
	background-color: rgba(255, 255, 255, 0.3);
}

/* At an end the button stays in place and stops inviting a press. */
.smeweb-picks-nav button:disabled {
	opacity: 0.35;
	cursor: default;
}

.smeweb-picks-prev {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 4 7 12l8 8'/%3E%3C/svg%3E");
}

.smeweb-picks-next {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 4l8 8-8 8'/%3E%3C/svg%3E");
}

@media (max-width: 781px) {
	.smeweb-picks .wp-block-post-template {
		margin-right: 0;
	}

	.smeweb-picks .wp-block-post-template > li {
		flex-basis: 82%;
	}
}

/* Pagination */
.wp-block-query-pagination {
	font-weight: 500;
}

.wp-block-query-pagination .page-numbers.current {
	color: var(--wp--preset--color--accent-dark);
}

.wp-block-query-pagination a:hover {
	color: var(--wp--preset--color--primary);
}

/* Editor content spacing on single posts */
.smeweb-entry-content > * + * {
	margin-top: 1.5rem;
}

.smeweb-entry-content blockquote {
	border-left: 4px solid var(--wp--preset--color--accent);
	padding-left: 1.5rem;
	font-style: italic;
	color: var(--wp--preset--color--muted);
}

/* ------------------------------------------------------------------ *
 * 10. Footer
 * ------------------------------------------------------------------ */

/*
 * The footer is two stacked full-width bands: a lavender link area and the blue
 * copyright bar. Core's flow-layout rule gives every non-first child
 * `margin-block-start: var(--wp--style--block-gap)` — 1.5rem — and the wrapper
 * itself has no background, so that margin showed the white page through as a
 * seam between the two bands.
 *
 * Done in CSS rather than the group's blockGap attribute: WordPress emits no
 * layout CSS for a flow container's blockGap here, with or without a unit, so
 * the attribute alone leaves the seam in place. Two classes beat core's
 * `:root :where(…)` selector on specificity, so load order cannot undo it.
 */
.smeweb-footer.wp-block-group > * {
	margin-block-start: 0;
}

/*
 * Both footer bands take the same inset as the navigation row, so the logo, the
 * link columns and the copyright line all start on one vertical.
 *
 * The lavender band needs `!important`: the database markup carries
 * `padding-left/right: var(--wp--preset--spacing--80)` — 158px at 1440 — as an
 * inline style, and an inline style outranks every selector. This is the one
 * place in the theme where that is true, and it is only true because the markup
 * is not editable from here.
 */
.smeweb-footer > .wp-block-group:not(.smeweb-footer__bottom) {
	padding-inline: var(--smeweb-shell-inset) !important;

	/*
	 * The same space above the block and below it.
	 *
	 * The markup asks for spacing-60 on top and a flat 0 underneath, as an inline style, so the
	 * logo sat 96px clear of the top while the newsletter pill finished hard against the blue
	 * bar. Both ends take spacing-60 now, and because that is a clamp they stay equal as the
	 * window changes rather than only at one width.
	 *
	 * !important for the padding-bottom: 0px it is overriding, which is inline.
	 */
	padding-block: var(--wp--preset--spacing--60) !important;
}

.smeweb-footer__bottom {
	padding-inline: var(--smeweb-shell-inset);
}

/* Both bands' inner content then fills the inset rather than re-centring in it. */
.smeweb-footer .wp-block-columns,
.smeweb-footer__bottom > .wp-block-group {
	max-width: none;
	padding-inline: 0;
}

/* Bullet-free link lists (footer columns). */
ul.is-style-smeweb-plain,
ol.is-style-smeweb-plain {
	list-style: none;
	margin: 0;
	padding: 0;
}

.smeweb-footer a {
	text-decoration: none;
	transition: color 0.18s ease;
}

/*
 * The link columns.
 *
 * The contrast token, which is #14142b — near-black. It was briefly #1414b2, a blue, from a
 * transposition in the hex; the token says what is meant and cannot be mistyped the same way.
 */
.smeweb-footer ul.is-style-smeweb-plain {
	/*
	 * The rows are spaced by a margin between items, with the line-height left at a normal 1.6.
	 *
	 * It was the other way round — a 2.2 line-height and no margin — and that was wrong twice
	 * over. It made no visible difference, because 2.1 to 2.2 is 1.76px a row and nobody sees
	 * that; and stretching each line box is the wrong tool anyway, since an item long enough to
	 * wrap would read as two loose lines rather than one entry. A margin separates entries and
	 * leaves the words inside one entry together.
	 *
	 * 1.6 plus 1rem comes to a 44px pitch against the 38.7 that was there.
	 *
	 * !important because the ul carries line-height: 2.1 as an inline style out of the footer
	 * template part in the database, and an inline style outranks every selector.
	 */
	line-height: 1.6 !important;
}

.smeweb-footer ul.is-style-smeweb-plain li + li {
	margin-top: 1rem;
}

.smeweb-footer ul.is-style-smeweb-plain a {
	color: var(--wp--preset--color--contrast);
}

/*
 * The line under the logo reads in the same near-black as the columns.
 *
 * !important because the paragraph carries has-muted-color, and core writes its colour
 * presets with it.
 */
.smeweb-footer .wp-block-column > p.has-muted-color {
	color: var(--wp--preset--color--contrast) !important;
}

/*
 * The first column reads narrower than the 418px it is given.
 *
 * A cap on the copy and the field rather than on the column: the four link columns keep the
 * positions the design puts them in, and the extra room turns into space between the block and
 * the first of them instead of moving everything along.
 *
 * The cap travels with the window rather than sitting at one number. 21rem was too tight and
 * the 418px the column gives was too wide, so it runs between: 26vw, floored at 20rem and
 * capped at 25rem — 374px at 1440, 400 at 1920, and the column’s own width below that.
 *
 * min(100%, …) is what keeps it inside the column. Stacked on a phone the column is the page,
 * so the block fills it rather than sitting at 320px in the middle of nothing.
 */
.smeweb-footer .wp-block-column:first-child > p,
.smeweb-footer .wp-block-column:first-child > .smeweb-form-inline {
	max-width: min(100%, clamp(20rem, 26vw, 25rem));
}

/*
 * A heading sits closer to its own list than to the column beside it — 20px under the
 * heading against the 35px between links, so each column reads as one block rather than a
 * heading floating over five separate lines.
 */
.smeweb-footer .wp-block-column ul.is-style-smeweb-plain {
	/* !important: the 24px it had is the flow layout’s block gap, written through its own
	   container class, so a sibling selector loses to it. */
	margin-top: 1.25rem !important;
}

.smeweb-footer a:hover {
	color: var(--wp--preset--color--accent-dark);
}

/*
 * Footer column links inherit the muted list colour rather than the global
 * blue link colour, matching the design.
 */
.smeweb-footer .is-style-smeweb-plain a {
	color: inherit;
}

.smeweb-footer .is-style-smeweb-plain a:hover {
	color: var(--wp--preset--color--accent-dark);
}

/* The bottom bar sits on brand blue, so links must be white, not blue. */
.smeweb-footer__bottom a {
	color: currentColor;
}

/*
 * The supplied social marks, in place of the ones core draws.
 *
 * Each upload is the whole badge — a filled disc with the glyph knocked out of it — so the
 * disc core paints underneath has to go, or there are two. The svg goes with it: hidden
 * rather than removed, because this markup is a database template part and the block writes
 * that svg itself.
 *
 * 36px because that is what the files are. Core had them at 24 with a 16px glyph inside.
 */
.smeweb-footer .wp-block-social-links .wp-social-link {
	transition: transform 0.18s ease;
	width: 36px;
	height: 36px;
	background-color: transparent !important;
	background-repeat: no-repeat;
	background-position: center;
	background-size: 36px 36px;
}

.smeweb-footer .wp-block-social-links .wp-social-link a {
	width: 100%;
	height: 100%;
	padding: 0;
}

.smeweb-footer .wp-block-social-links .wp-social-link svg {
	display: none;
}

.smeweb-footer .wp-social-link-facebook {
	background-image: url("../../uploads/2026/08/Facebook-Icon.png");
}

.smeweb-footer .wp-social-link-instagram {
	background-image: url("../../uploads/2026/08/IG-icon.png");
}

.smeweb-footer .wp-social-link-youtube {
	background-image: url("../../uploads/2026/08/Youtube-Icon.png");
}

/*
 * In the footer the submit is the send mark and nothing else — no fill, no label, no arrow
 * disc. The same form runs in the consultation bands, where it keeps its red pill, so every
 * rule here is scoped to the footer.
 *
 * font-size: 0 hides the label without taking it out of the accessible name, and the button
 * carries an aria-label of its own, so the name survives either way.
 *
 * min-width and the fill need !important for the same reason they did in the bands: Fluent
 * Forms writes per-form CSS into the markup with three classes and an element.
 */
.smeweb-footer .smeweb-form-inline .fluentform .ff-btn-submit {
	width: 2.75rem;

	/*
	 * A height, because font-size: 0 leaves the button no line box to stand on — it measured
	 * 44 by 0 and the mark had nowhere to show.
	 */
	height: 2.75rem;
	min-width: 0 !important;
	padding: 0 !important;
	font-size: 0;
	background-color: transparent !important;
	background-image: url("../../uploads/2026/08/Send-Icon.png");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 22px 22px;
	box-shadow: none !important;
}

.smeweb-footer .smeweb-form-inline .fluentform .ff-btn-submit::after {
	display: none;
}

.smeweb-footer .smeweb-form-inline .fluentform .ff-btn-submit:hover {
	transform: none;
	opacity: 0.7;
}

/*
 * The line above the field sits on it rather than a paragraph away.
 *
 * It was 43px clear: 12 from the paragraph’s own margin, which is an inline style on the
 * database markup, and the rest from the block gap the flow layout puts above the form. Both
 * have to come down, which is why one carries !important.
 */
.smeweb-footer .wp-block-column > p:has(+ .smeweb-form-inline) {
	margin-bottom: 0.5rem !important;
}

.smeweb-footer .smeweb-form-inline {
	/* !important: the flow layout writes this margin through its own container class. */
	margin-top: 0 !important;
}

/*
 * The empty paragraph the shortcode leaves behind.
 *
 * wpautop wraps the newlines around [smeweb_form] into a <p> of its own, which renders 0px
 * tall with 19.2px of margin above and below it — 19 of the 27px that were still sitting
 * between the line and the field after both real margins had been taken down. It only shows up
 * where the shortcode has blank lines around it, which today is the footer part in the
 * database and not the patterns.
 *
 * Not :empty — that wants no children at all and these paragraphs hold the newline, so the
 * selector matched nothing. A classless <p> anywhere inside the form is the tell: Fluent Forms
 * puts an ff- class on everything of its own, so anything without one came from wpautop.
 *
 * Anywhere, not just under the fieldset. There are two of them and they are at different
 * depths — one beside the pill, one inside the submit’s own group, which on a phone was adding
 * 32px to the cell and leaving the pill 72px tall against the 56 it should be.
 */
.smeweb-form-inline .fluentform p:not([class]) {
	display: none;
}

.smeweb-footer .wp-block-social-links .wp-social-link:hover {
	transform: translateY(-2px);
}

.smeweb-footer__bottom a:hover {
	color: #fff;
	text-decoration: underline;
}

/* ------------------------------------------------------------------ *
 * 11. Fluent Forms
 * ------------------------------------------------------------------ *
 * Fluent Forms ships its own stylesheet; these rules re-skin its fields
 * to the theme tokens without relying on plugin-internal markup beyond
 * its documented, stable class names.
 */

.fluentform .ff-el-group {
	margin-bottom: 1.1rem;
}

.fluentform .ff-el-input--label label {
	font-weight: 500;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
	margin-bottom: 0.4rem;
}

/*
 * The field is the fill and nothing else, which is how the auth screens draw theirs.
 *
 * The border is transparent rather than gone so the focus rule below has one to colour — same
 * arrangement as .fs_input_wrap, and it also keeps the box the same size focused and not.
 *
 * The trade the whole site now makes here: --surface on white is about 1.06:1, where WCAG asks
 * 3:1 for the edge of a control. What marks the field is the fill, which is legal but thin, and
 * the focus ring is what carries it once someone is in the field. Putting an edge back is one
 * line — the value that used to be here was --outline.
 */
.fluentform .ff-el-form-control {
	width: 100%;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--surface);
	border: 1px solid transparent;
	border-radius: 10px;
	padding: 0.85rem 1.1rem;
	box-shadow: none;
	transition: border-color 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}

.fluentform .ff-el-form-control::placeholder {
	color: var(--wp--preset--color--muted);
	opacity: 1;
}

.fluentform .ff-el-form-control:focus {
	background-color: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.14);
	outline: none;
}

.fluentform textarea.ff-el-form-control {
	min-height: 8.5rem;
	resize: vertical;
}

/*
 * Submit button, matching the buttons the rest of the site uses.
 *
 * The colour is set through Fluent Forms’ own variable rather than by declaring a
 * background here. Its stylesheet paints the button with
 * `form.fluent_form_1 .ff-btn-submit:not(.ff_btn_no_style)`, which outranks anything
 * scoped to .fluentform — the declaration below was being ignored and the button came
 * out rgb(26, 126, 251), the plugin’s blue, next to the theme’s rgb(31, 42, 205).
 * Redefining the variable reaches that rule and every other place the plugin reads it.
 *
 * 2rem of side padding rather than 2.5, which is what the block buttons measure.
 */
.fluentform {
	--fluentform-primary: var(--wp--preset--color--primary);
}

.fluentform .ff-btn-submit,
.fluentform .ff_submit_btn_wrapper button {
	font-family: inherit;
	font-weight: 500;
	font-size: var(--wp--preset--font-size--small);
	background-color: var(--wp--preset--color--primary);
	color: #fff;
	border: 0;
	border-radius: 999px;
	padding: 0.9rem 2rem;
	cursor: pointer;
	transition: transform 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}

/*
 * The contact submit fills its column, as the ones on the auth screens do. It was 118px in a
 * 528px card, the shortest thing in it and hard against the left edge.
 *
 * Per-form rather than on .fluentform, because the other form on the site is the footer pill,
 * where the button is a mark at the end of a row and a full width one would swallow the field.
 */
form.fluent_form_1 .ff-btn-submit {
	width: 100%;
}

.fluentform .ff-btn-submit:hover,
.fluentform .ff_submit_btn_wrapper button:hover {
	background-color: var(--wp--preset--color--primary-dark);
	transform: translateY(-2px);
	box-shadow: 0 12px 26px rgba(31, 42, 205, 0.28);
}

/*
 * The consent note, once assets/js/contact-form.js has moved it inside the fieldset.
 *
 * It arrives among the form’s rows, which space themselves with 17.6px of bottom margin,
 * so it takes the same rhythm rather than the card’s 24px block gap. A little more above
 * it than below, because it reads as a note on the fields it follows and the button it
 * precedes should stay attached to it.
 *
 * Only when it has been moved. In the position the pattern gives it — above the form,
 * which is where it stays without JavaScript — the card’s own gap is right.
 */
.smeweb-form-consent.is-in-form {
	/*
	 * Measured: 18px clear above and 18px below, against 17.6px between the fields, so nothing
	 * on the card said this was a note rather than a sixth box to fill in. The comment above has
	 * always described more above than below; this is that, built.
	 */
	margin-top: 1.75rem;
	margin-bottom: 1.5rem;
}

/*
 * The button ends the card, so nothing should follow it but the padding.
 *
 * Measured: the heading sat 64px below the top edge and the button 106px above the
 * bottom. The 42px difference was two things — the submit row keeping the 17.6px
 * margin it uses to separate itself from the row above, where it has nothing below it
 * to separate from, and an empty paragraph wpautop leaves after the shortcode, whose
 * 24px top margin lands between the form and the padding. Neither is visible; both
 * take up space.
 */
.fluentform .ff_submit_btn_wrapper {
	margin-bottom: 0;
}

.page-template-page-contact main > .has-hero-wash-gradient-background p:empty {
	display: none;
}

/* Validation + response messages */
.fluentform .ff-el-is-error .ff-el-form-control {
	border-color: var(--wp--preset--color--accent);
}

.fluentform .error.text-danger,
.fluentform .ff-el-is-error .error {
	color: var(--wp--preset--color--accent-dark);
	font-size: 0.8rem;
	margin-top: 0.3rem;
}

.ff-message-success,
.fluentform .ff_submit_success {
	background-color: rgba(31, 42, 205, 0.07);
	border: 1px solid var(--wp--preset--color--primary);
	border-radius: 12px;
	color: var(--wp--preset--color--primary);
	padding: 1rem 1.25rem;
}

.ff-errors-in-stack,
.fluentform .ff-errors-in-stack {
	background-color: rgba(255, 0, 0, 0.07);
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: 12px;
	color: var(--wp--preset--color--accent-dark);
	padding: 1rem 1.25rem;
}

/*
 * Inline variant — a single row of "email + button", used by the
 * newsletter field in the footer and the blue consultation banners.
 */
.smeweb-form-inline .fluentform .ff-el-group,
.smeweb-form-inline .fluentform .ff-t-container {
	margin-bottom: 0;
}

/*
 * One pill holding the field and the button, as the design has it, rather than a white
 * field with a red button standing beside it.
 *
 * The plugin gives this form a two-cell flex row, so the row itself becomes the pill and
 * the field inside it goes transparent. 6px of padding is what sets the inset the button
 * sits at, and the cells lose their gutter so it finishes flush against the right end.
 */
.smeweb-form-inline .fluentform .ff-t-container {
	background-color: #fff;
	border-radius: 999px;
	padding: 6px;
	align-items: center;

	/*
	 * One row at every width. Below 768px the plugin switches this container to display: block,
	 * which stacked the cells — on a phone the pill came out 114px tall with the field on one
	 * line and the send mark on its own underneath. There is room for both: at 390 the row has
	 * 307px and the mark takes 44.
	 *
	 * !important because that rule wins on specificity, media query or not.
	 */
	display: flex !important;
}

.smeweb-form-inline .fluentform .ff-t-cell {
	padding: 0;
}

/*
 * The pill was 81px tall around a 49px button, which is what made it read as a white slab
 * with a button floating in it. 20px of it was a bottom margin the plugin puts on the
 * submit — measured, not guessed: the button was 49 tall, its cell 69, and the pill 69
 * plus its own 12. Clearing that margin brings the pill to 61, which is the button and the
 * 6px inset either side of it.
 *
 * !important because the plugin sets that margin inside a media query. Worth recording how
 * that was found: a rule of ours was already setting it to 0 and matching, and the computed
 * value stayed 20px — the scan that went looking for the culprit only walked top-level
 * rules and never saw inside @media, so it reported our own rule as the only one there.
 *
 * min-width for the same kind of reason. The button was 217px wide around 151px of content,
 * so the label sat in the middle of 66px of spare red — read as too much padding, and it was
 * not padding at all. The per-form CSS Fluent Forms writes into the markup carries
 * min-width: 100%, which fills the cell the plugin allots the submit. Zeroing it lets the
 * button shrink to its label, and the auto margin puts it back against the right end of the
 * pill so the 6px inset is all that shows.
 *
 * Worth knowing the fill and this both need !important for the same reason: that per-form
 * block is form.fluent_form_2 .wpf_has_custom_css.ff-btn-submit — three classes and an
 * element, so it outranks anything scoped to .smeweb-form-inline.
 */
.smeweb-form-inline .fluentform .ff-btn-submit {
	margin-bottom: 0 !important;
	min-width: 0 !important;
	margin-left: auto;
}

.smeweb-form-inline .fluentform .ff-el-form-control {
	background-color: transparent;
	border-color: transparent;
	border-radius: 999px;
	padding: 0.55rem 1.4rem;
}

.smeweb-form-inline .fluentform .ff-el-form-control:focus {
	box-shadow: none;
}

/*
 * The arrow disc the design puts on this button, drawn the same way the block buttons
 * draw theirs — a white circle with the arrow knocked out in the button’s own colour.
 *
 * inline-flex on the button so the label and the disc sit on one line with a gap, and
 * asymmetric padding so the disc, not the padding, sets the right-hand inset. Same
 * geometry as .is-style-smeweb-arrow; it cannot be reused directly because that style
 * hangs off the block button class and this is the plugin’s own element.
 *
 * The arrow is stroked in #FF0000 to match the fill the spec asks for — it was #FF001A
 * while the plugin’s own per-form colour was still winning.
 */
.smeweb-form-inline .fluentform .ff-btn-submit {
	/*
	 * The supplied spec, which is the same geometry the block buttons already use:
	 * inline-flex, 10px gap, and 6px 8px 6px 16px — asymmetric, so the disc rather than the
	 * padding sets the right-hand inset. With a 40px disc that comes to the 52px height the
	 * spec is measured at.
	 *
	 * border-radius: 74px as given. Past half the height it renders identically to the
	 * theme’s 999px pill, so this is the spec’s number rather than a different shape.
	 *
	 * The fill needs !important. Fluent Forms paints this button from custom CSS saved
	 * against the form — form.fluent_form_2 .wpf_has_custom_css.ff-btn-submit, three classes
	 * and an element — which outranks anything scoped to .smeweb-form-inline, and it was
	 * painting rgb(255, 0, 26) where the spec asks for #F00.
	 *
	 * backdrop-filter: blur(39.25px) is in the spec and is not reproduced, for the same
	 * reason it was left off the block buttons: the fill is opaque, so there is no backdrop
	 * left to blur, and the declaration would only cost a compositing layer.
	 */
	background-color: #FF0000 !important;
	white-space: nowrap;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 6px 8px 6px 16px;
	border-radius: 74px;
}

.smeweb-form-inline .fluentform .ff-btn-submit::after {
	content: "";
	flex: 0 0 auto;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background-color: #fff;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FF0000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M12 5l7 7-7 7'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 1em 1em;
	transition: transform 0.18s ease;
}

.smeweb-form-inline .fluentform .ff-btn-submit:hover::after {
	transform: translateX(3px);
}

/*
 * Lift rather than darken: accent-dark is the same red as accent now, so the
 * background swap this rule used to make was invisible.
 *
 * The label holds its colour. The per-form CSS Fluent Forms writes into the markup has a
 * hover state of its own — background #ffffff, colour #1a7efb — and the fill was already
 * pinned red with !important, so only the text was still flipping: white to blue on hover,
 * over red. Measured on the rendered button, not read off the rule: colour went
 * rgb(255, 255, 255) to rgb(26, 126, 251) while the background stayed rgb(255, 0, 0).
 *
 * border-color flips with it and is left alone, because the border is 0px wide.
 */
.smeweb-form-inline .fluentform .ff-btn-submit:hover {
	color: #fff !important;
	transform: translateY(-2px);
	box-shadow: 0 12px 26px rgba(255, 0, 0, 0.3);
}

/* Two-column field rows inside the contact card (Fluent Forms grid). */
.fluentform .ff-t-cell {
	padding-right: 0.6rem;
}

.fluentform .ff-t-cell:last-child {
	padding-right: 0;
}

/*
 * One column below 1024, not below 600.
 *
 * The contact card is half of the hero row, so it is 363px wide at 782 and two cells of that
 * are 127px each. Measured there: the Phone Number placeholder wants 114px and has 89px of
 * room, so it was being cut off. At 900 it fits with 11px to spare, which is not room, and
 * Thai labels are no shorter. From 1024 the cells are 191px with 156px of room, which is.
 *
 * The footer pill is unaffected: it forces display: flex !important on this same container so
 * it stays one row at every width.
 */
@media (max-width: 1023px) {
	.fluentform .ff-t-container {
		display: block;
	}

	.fluentform .ff-t-cell {
		width: 100% !important;
		padding-right: 0;
	}
}

/* Fluent Forms inside a dark/blue section */
.has-primary-background-color .fluentform .ff-el-input--label label,
.smeweb-on-dark .fluentform .ff-el-input--label label {
	color: #fff;
}

/* ------------------------------------------------------------------ *
 * 12. Utilities & decorations
 * ------------------------------------------------------------------ */

/* Small red eyebrow label above section headings. */
.smeweb-eyebrow {
	display: block;
	font-size: 0.8rem;
	font-weight: 500;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--muted);
	margin-bottom: 0.35rem;
}

/*
 * Step chips ("สั่ง / รอ / รับ") that sit under a section heading.
 * Paragraphs rather than buttons on purpose: they label a flow, they are not
 * links, so nothing here should look or behave like one. The parent group
 * supplies the flex layout and gap.
 */
.smeweb-steps__item {
	margin: 0;
	/*
	 * Horizontal padding is tight on purpose: all three chips have to clear one
	 * line inside the ~530px text column, and the labels are long. It grows on
	 * wider screens where there is room to spare.
	 */
	padding: 0.4rem clamp(0.7rem, 1vw, 1.1rem);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: var(--smeweb-radius-pill, 999px);
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
	line-height: 1.5;
	/*
	 * Keep each label intact. The row itself may still wrap on narrow screens —
	 * that is preferred to forcing one line and overflowing the column.
	 */
	white-space: nowrap;
}

/*
 * The first step carries the brand red to mark where the journey starts.
 *
 * Still named accent-dark, though that token is the same #FF0000 as accent
 * today. White on #FF0000 measures 4.39 and this chip's label is 14px, where
 * WCAG AA wants 4.5 — a known cost of running one red. The small-text roles are
 * deliberately left pointing at accent-dark so that giving that token a darker
 * value again, one line in theme.json, puts every one of them back over AA
 * without touching this stylesheet.
 */
.smeweb-steps__item--accent {
	border-color: var(--wp--preset--color--accent-dark);
	background-color: var(--wp--preset--color--accent-dark);
	color: var(--wp--preset--color--base);
}

/* Red asterisk/starburst decoration from the design. */
.smeweb-starburst {
	display: inline-block;
	width: 2.5rem;
	height: 2.5rem;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23FF0000'%3E%3Cpath d='M12 1.5 13.9 8.5l6.4-3.6-4.4 5.7 7.1 1.4-7.1 1.4 4.4 5.7-6.4-3.6L12 22.5l-1.9-7-6.4 3.6 4.4-5.7L1 12l7.1-1.4-4.4-5.7 6.4 3.6z'/%3E%3C/svg%3E");
}

/* Dotted grid decoration. */
.smeweb-dots {
	background-image: radial-gradient(currentColor 1.6px, transparent 1.6px);
	background-size: 12px 12px;
	opacity: 0.35;
}

/* Full-bleed rounded blue band used by the consultation CTA. */
/*
 * The consultation band, to the supplied design.
 *
 * Everything on the right is a background layer rather than markup, because the section
 * renders from two places: patterns/cta-consult.php on the contact and blog pages, and
 * the database copy of the pricing template. One rule reaches both, and none of it is
 * content — it is the picture the band is printed on.
 *
 * Layers paint first-listed on top, so the order below is front to back: the mark, the
 * figure, the dot grid, the sweep, then the noise over the fill.
 *
 * The noise is the supplied filter rebuilt as its own SVG: fractalNoise at the same
 * baseFrequency and seed, luminanceToAlpha to turn brightness into coverage, then a
 * discrete transfer that keeps 51 of every 100 steps and drops the rest — which is what
 * the 100 tableValues in the original say. Black at 0.2 over the blue, as the flood in
 * the original does. Tiled at 200px with stitchTiles, so the seams line up.
 *
 * #1725CC is the design’s blue, a little deeper than the primary token this band used
 * (rgb(31, 42, 205)). !important because has-primary-background-color is written with it.
 *
 * The width and the height are the front page’s closing cover: full bleed less the page
 * gutter, and 416px tall. Measured there — 1392 wide at 1440 and 1872 at 1920, both 417
 * tall, on a 40px radius — and the supplied design is 1807 by 416, which is the same band
 * at 1920. max-width: none is all it takes: the section is already a full-bleed group with
 * the gutter as padding, and the constrained layout was capping the band at the content
 * measure inside it.
 */
.smeweb-band {
	max-width: none;

	/*
	 * 416px whatever the copy inside comes to, so the three pages that carry this section
	 * are the same band rather than three heights — the paragraph wraps differently on each,
	 * and left to the content they measured 300, 319 and 378.
	 *
	 * A one-column grid to centre that copy in the extra room, not a flex column. Flex was
	 * the first attempt and it collapsed the row: the constrained layout gives every child
	 * auto side margins, and auto margins on a flex item absorb the free space, so the row
	 * shrank to its content — 793px of a 1234px box — and centred itself. A single
	 * minmax(0, 1fr) track leaves no free space for them to take.
	 *
	 * The side inset is the design’s: its heading starts 5.6% in, which is 105px at 1872 and
	 * what 5.5vw comes to there. Clamped so it stays sensible either side of that.
	 *
	 * !important on the padding because it is on the block’s own style attribute.
	 */
	min-height: 416px;
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-content: center;

	padding-block: 2.25rem !important;
	padding-inline: clamp(2rem, 5.5vw, 6.5rem) !important;
	border-radius: 40px;
	overflow: hidden;

	background-color: #1725CC !important;
}

/*
 * The artwork is the consultation band only, not every .smeweb-band.
 *
 * That class is shared: patterns/blog-picks.php uses it for the blue band of article
 * picks on the blog page, and it was getting all of this — the figure stood over the
 * cards with the sweep behind them. Found by grepping for the class rather than by
 * looking, which is the lesson: a rule written for one section landed on two.
 *
 * .smeweb-on-dark is what separates them. The pattern and the database copy of the
 * pricing section both carry it; blog-picks does not.
 *
 * The geometry above stays shared on purpose. The blog band renders correctly on it
 * today — 416px, the 40px radius, the same inset — so pulling it back would trade a
 * fixed bug for a new one.
 */
.smeweb-band.smeweb-on-dark {
	background-image:
		url("../../uploads/2026/08/Icon-Slide-02.png"),
		url("../../uploads/2026/08/CTA-Point.png"),
		url("../../uploads/2026/08/CTA-Element.png"),
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.43478262' numOctaves='3' stitchTiles='stitch' seed='2636'/%3E%3CfeColorMatrix type='luminanceToAlpha'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.2'/%3E%3C/svg%3E") !important;
	background-repeat: no-repeat, no-repeat, no-repeat, repeat !important;
	background-size:
		auto 13%,
		auto 36%,
		auto 100%,
		200px 200px !important;
	/*
	 * Anchored to the right edge by distance, not by percentage.
	 *
	 * A percentage in background-position is a share of the free space — container width
	 * minus image width — so the same value lands differently as the band widens. It showed:
	 * at 136% the sweep covered a quarter of the band at 1440 and had all but left the frame
	 * at 1920. Distances from the right keep every layer the same distance from the corner it
	 * belongs to, and vw in the clamps lets them breathe with the window without drifting.
	 *
	 * The sweep is the band’s own height, hung 40px past the right edge and dropped 30px.
	 * What decides those is where the artwork’s ink sits, not how much of the file shows:
	 * CTA-Element is 431x397 of three hooks, whose bends are at x=20, 270 and 390. A negative
	 * offset hangs the file off the right edge and keeps its LEFT side, so the old -460px at
	 * 150% showed the left hook alone — two straight legs entering the corner, no bend, which
	 * is what read as wrong against the design. At 100% and -40px the right hook’s bend lands
	 * inside the band with its legs running out of the bottom corner, and the other two sit
	 * behind the figure, exactly as the design has them.
	 *
	 * The mark moved for a reason worth keeping: it was at clamp(105px, 13vw, 250px), and the
	 * figure is anchored at clamp(60px, 10vw, 200px), so the mark ran left faster than she did
	 * and she began to cover it — 1% of it at 1280, 6% at 1512, 15% at 1920. Sampled from the
	 * render rather than compared as boxes, because she is a transparent PNG. A fixed 114px
	 * from the corner is clear at every width.
	 */
	background-position:
		right 114px top 47px,
		right clamp(200px, 25vw, 480px) bottom -6%,
		right -40px top 30px,
		0 0 !important;
}

/*
 * The figure stands above the band’s top edge, as the design has her.
 *
 * She cannot be one of the band’s background layers for that: the band clips, and it has
 * to — the sweep and the noise both need the rounded corners to cut them. So she is drawn
 * on the section around it, which does not clip, and is anchored to the band’s foot by the
 * section’s own bottom padding.
 *
 * :has() because that section has no class of its own, and the same section is what the
 * pattern and the database copy both produce.
 *
 * 5.3rem taller than the band, so its top edge crosses her at about ear height, which is
 * where it was asked to sit. Worked back from the drawing rather than tried: at 1.75rem
 * only 11px of her hair cleared the edge, her head measures about 105px, and her ears are
 * roughly two thirds down it — so she had to rise another 57px.
 *
 * The box widened with her. She is fitted by height, and at 501px tall she wants 563px of
 * width; a 544px box would have started fitting her by width instead and shrunk her back.
 * Sized by
 * height with contain and pinned right-bottom, so the offsets match the layers she used to
 * sit among.
 */
.wp-block-group:has(> .smeweb-band.smeweb-on-dark) {
	position: relative;
}

.wp-block-group:has(> .smeweb-band.smeweb-on-dark)::after {
	content: "";
	position: absolute;
	z-index: 1;
	right: clamp(60px, 10vw, 200px);
	bottom: var(--wp--preset--spacing--60);
	width: 36rem;
	height: calc(416px + 5.3rem);
	background-image: url("../../uploads/2026/08/CTA-people.webp");
	background-repeat: no-repeat;
	background-position: right bottom;
	background-size: contain;
	pointer-events: none;
}

/*
 * The copy starts at the band’s own inset rather than at the content measure.
 *
 * The row is a constrained child, so it was capped at 1200 and centred — which puts the
 * heading 96px in at 1440 but 336px in at 1920, while the design has it at 105 either way.
 * Filling the inset instead makes the inset the only thing deciding it.
 *
 * The paragraph then needs a measure of its own, or at 1920 it would have a 965px column
 * to run across and would stop wrapping to the two lines the design shows.
 *
 * margin-inline needs !important, and it is the whole reason the row kept collapsing. The
 * constrained layout writes margin-left and margin-right as auto with !important, and auto
 * margins absorb free space — in a flex item and in a grid item alike — so the row shrank
 * to its content and centred itself no matter which display the band used. Lifting the
 * cap was never going to be enough on its own.
 */
.smeweb-band > .wp-block-columns {
	max-width: none;
	margin-inline: 0 !important;
}

/*
 * 36px for the heading, as asked, and px rather than rem deliberately: the small preset
 * renders at 17.6 rather than the 15 its 0.9375rem asks for, so a rem here would not be
 * the 32 that was specified.
 *
 * !important because the size comes from has-x-large-font-size, which core writes with it.
 */
.smeweb-band.smeweb-on-dark .wp-block-heading {
	/*
	 * 36px on a desktop, as asked, and 24 on a phone: at 390 the fixed 36 wrapped to two lines
	 * 94px deep. The max is the number that was specified, so nothing changes on a wide screen.
	 */
	font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem) !important;
}

.smeweb-band .wp-block-column:first-child p {
	max-width: 34em;
}

/*
 * On the consultation band the paragraph runs to the width of the field instead — asked
 * for, and it is the better rule here: the paragraph and the pill are siblings in the same
 * column, so with no cap of its own the paragraph measures exactly what the pill measures,
 * at every width, with nothing to keep in step by hand.
 *
 * That is what the 34em above was standing in for. It capped the line at 598px against a
 * 716px pill, which is the ragged right edge in the design review. The cap stays for
 * blog-picks, which shares the class and has no field to line up with.
 */
.smeweb-band.smeweb-on-dark .wp-block-column:first-child p {
	max-width: none;
}

/*
 * The illustration the band used to carry on the right. The pattern no longer places it;
 * the database copy of the pricing page still does, and the layers above are drawn in its
 * place, so it is hidden rather than left to sit on top of them.
 *
 * figure.wp-block-image, not figure. Core sets display: table on .wp-block-image.aligncenter
 * — two classes against the one class and one element a bare `figure` gives, so the first
 * attempt lost and the placeholder went on painting over the artwork on the pricing page.
 * The contact page hid its own copy fine, because the pattern no longer emits one at all.
 */
.smeweb-band figure.wp-block-image {
	display: none;
}

/*
 * The figure goes below 1024, because by then she is standing on the words.
 *
 * She is 36rem wide and anchored a fixed distance from the right edge, so as the window
 * narrows her box eats into the text rather than moving out of its way. Measured against the
 * text block: 14% of it covered at 1440, which is the proportion the design was drawn at and
 * reads as depth; 30% at 1200, 47% at 1024, 63% at 900, 84% at 782. At 414 she covers the
 * whole band and the white heading sits on her face.
 *
 * A smaller figure was the other option. She is fitted by height with contain, so a narrower
 * box fits her by width instead and she stops standing above the band top edge — which is the
 * one thing the composition is about. Better gone than turned into something else.
 */
@media (max-width: 1023px) {
	.wp-block-group:has(> .smeweb-band.smeweb-on-dark)::after {
		display: none;
	}
}

@media (max-width: 781px) {
	.smeweb-band {
		border-radius: 20px;
	}
}

/*
 * And below 600 the band carries no artwork at all.
 *
 * Its own layers are sized to the band, so they narrow with it and end up where the figure
 * was: at 414 the mark lands in the middle of the heading and the sweep crosses all of it.
 * There is about 85px of slack at the foot of a 416px band once the heading, the paragraph and
 * the pill have had their room, which is not enough to put anything in without it touching
 * something. Flat brand blue with the noise, the corners, and the copy legible.
 *
 * Zero sizes rather than a shorter list, so the four layers stay in the order the rule above
 * declares them and the noise keeps its place as the fourth. !important because that rule uses
 * it, and a media query does not change specificity.
 */
@media (max-width: 600px) {
	.smeweb-band.smeweb-on-dark {
		background-size: 0 0, 0 0, 0 0, 200px 200px !important;
	}

	/*
	 * And the button gives the field back some room.
	 *
	 * The pill is 302px at 414 and the button was taking 204 of it, which left 86 for the
	 * address — about eight characters visible while typing one. The disc is 40 of those 204,
	 * plus the 10px gap before it, and the label carries the arrow well enough on its own at
	 * this size. With the label a step down too the field comes to about 140.
	 *
	 * Scoped to this band. The footer runs the same form through the same classes, but there the
	 * button is the mark and nothing else — a label at any size would break it.
	 */
	.smeweb-band.smeweb-on-dark .smeweb-form-inline .fluentform .ff-btn-submit {
		/*
		 * The vertical padding is what the disc used to set. Without it 6px left a 32px button
		 * floating in a 54px pill; 11px brings it back to 41, which is the field beside it.
		 */
		padding: 11px 16px;
		font-size: var(--wp--preset--font-size--x-small);
	}

	.smeweb-band.smeweb-on-dark .smeweb-form-inline .fluentform .ff-btn-submit::after {
		display: none;
	}
}

/*
 * Text over photography keeps to the reading width, so a headline centred on a
 * full-bleed banner does not run the width of the screen. 720px is the same
 * measure the article, archive, search, FAQ and 404 columns use — see the
 * "Content widths" note in readme.md.
 */
.smeweb-cover-cta .wp-block-cover__inner-container {
	max-width: 720px;
}

/*
 * The closing banner is alignfull so it spans the page, but a rounded band whose
 * corners touch the viewport edges reads as a mistake rather than a decision.
 * Core breaks alignfull children out of the root padding with a negative inline
 * margin; cancelling it leaves the banner inset by exactly the page gutter, so
 * its edges line up with the content above instead of bleeding past it.
 *
 * Three classes on the element itself, so this outranks core's
 * `.has-global-padding > .alignfull` no matter which stylesheet loads first.
 */
/*
 * Every other page ends on a section with generous bottom padding — faq and
 * blog-picks at spacing-70, cta-consult at spacing-60 — so the footer never
 * arrives abruptly. The closing banner has none: it is a cover, and its padding
 * is interior, spacing the text away from the banner's own edge. The banner's
 * edge was the section's edge, so it sat straight on the footer.
 *
 * spacing-60 matches what cta-consult leaves on the contact page, which keeps
 * the run-in to the footer consistent across the site.
 */
.wp-block-cover.smeweb-cover-cta.alignfull {
	margin-inline: 0;
	margin-block-end: var(--wp--preset--spacing--60);
}

/* Stat figures */
/* Colour comes from the block's own preset class so editors can change it. */
.smeweb-stat__value {
	font-weight: 600;
	line-height: 1;
}

.smeweb-stat__label {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

/*
 * Search field.
 *
 * The magnifier is drawn inside the field rather than sat in a button beside it, which is how
 * the templates page does it and what the blog design asks for. Same icon and the same 38px
 * of left padding as .smeweb-tpl-search, so the two read as one control in two places.
 *
 * The block renders no button now (buttonPosition: no-button), and the form still submits on
 * Enter — which is what the templates page has always relied on.
 */
.wp-block-search__input {
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	padding: 0.85rem 1.4rem 0.85rem 2.6rem;
	background-color: var(--wp--preset--color--base);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6e85' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.2-4.2'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: 1.1rem 50%;
	background-size: 16px 16px;
}

.wp-block-search__input:focus {
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.14);
	outline: none;
}

.wp-block-search.wp-block-search__button-inside .wp-block-search__inside-wrapper {
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	padding: 0.25rem 0.25rem 0.25rem 1.25rem;
	background-color: var(--wp--preset--color--base);
}

.wp-block-search.wp-block-search__button-inside .wp-block-search__input {
	border: 0;
	padding-left: 0;
	box-shadow: none;
}

.wp-block-search__button {
	border-radius: 999px;
	font-weight: 500;
}

/*
 * The showcase runs as wide as the consultation band.
 *
 * Both sit in a full-width group, so the outer box already matched — 24 to 1416 of a 1440
 * window. What did not was the content: the constrained layout capped the heading and the
 * row of cards at the 1200px measure, which put them at 120–1320 while the blue band beside
 * them ran the full 1392. Lifting the cap is all this is; the 24px either side is core’s own
 * root padding, which the band uses too, so the two now start and finish on the same line.
 *
 * Not the shell inset the blog page uses. That is a different measure — wider than this one —
 * and the band asked for here is on root padding.
 *
 * On both skins, because they are one design: the blue one on the front page and the white
 * one on pricing have been kept to the same twenty blocks and the same card size since 1.2.79
 * and a width that applied to one of them would be the first thing to part them again.
 *
 * margin-inline needs !important for the reason it always does here: the constrained layout
 * writes the side margins as auto, and auto margins re-centre a child at its old width.
 *
 * The row of cards, and only the row of cards. The headline and the two lines around it keep
 * a measure, because a centred sentence 1392px wide is not a sentence anyone reads: the
 * eyebrow and the description are held at 42em by the measure rule further up this file, and
 * the headline is given the 720px below.
 *
 * An earlier pass swept every child in with `> *`, which lifted that cap and — worse — the
 * !important margin killed the auto that centres them, so both paragraphs sat hard against
 * the left edge. Naming the one block that should be wide is what this wants, not a list of
 * exceptions.
 */
.smeweb-showcase > .wp-block-columns {
	max-width: none;
	margin-inline: 0 !important;
}

/*
 * The headline reads at the width the blog hero uses.
 *
 * Widening the section to the band took the headline with it, and at 1392px it came out as a
 * single line running the whole window — measured, one line where it had been two. 720px is
 * the blog page’s own headline box, and its search field, so this is that number rather than
 * a new one. It lands beside the 739px the description already sits at, which puts the three
 * lines of copy over the cards as one block.
 */
.smeweb-showcase > .wp-block-heading {
	max-width: 720px;
	margin-inline: auto;
}

/*
 * Client / portfolio thumbnails.
 *
 * Square corners: the comp shows the screenshots cut straight, and a 14px radius on a
 * picture of a browser window rounds off the window chrome inside it, which reads as a
 * mistake rather than a style.
 *
 * Written as 0 rather than left out. theme.json sets core/image to a 14px radius for the
 * whole site, so deleting the declaration here does not give square corners — it hands
 * them back to the global rule. Measured at 14px on both pages after the first attempt.
 * The global stays as it is: every other image on the site is meant to be rounded.
 */
.smeweb-shot img {
	border-radius: 0;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	object-position: top center;
	width: 100%;
	box-shadow: 0 14px 34px rgba(20, 20, 43, 0.18);
}

/*
 * The three caption lines under a card, in italic.
 *
 * Selected through the column that holds a screenshot rather than through a class of
 * their own, so one rule covers both skins and the paragraphs stay as the pattern writes
 * them. The empty columns that pad the row out to four hold no .smeweb-shot, so they are
 * not matched — and nothing else on either page is.
 */
.wp-block-column:has(> .smeweb-shot) > p {
	font-style: italic;
}

/*
 * The address links out to the client.
 *
 * It takes the colour of the line it sits in rather than the link colour, because that
 * colour is the brand blue and the blue skin would then print brand blue on brand blue.
 * The underline is what says it is a link — on both grounds, without needing two colours.
 */
.wp-block-column:has(> .smeweb-shot) > p a {
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.22em;
	transition: color 0.18s ease;
}

/* Hover goes to full strength: the captions sit at reduced opacity on either ground. */
.wp-block-column:has(> .smeweb-shot) > p a:hover,
.wp-block-column:has(> .smeweb-shot) > p a:focus-visible {
	color: var(--wp--preset--color--primary);
}

.has-primary-background-color .wp-block-column:has(> .smeweb-shot) > p a:hover,
.has-primary-background-color .wp-block-column:has(> .smeweb-shot) > p a:focus-visible {
	color: var(--wp--preset--color--base);
}

.smeweb-shot--wide img {
	aspect-ratio: 4 / 3;
}

/* Horizontal scroller fallback for the picks carousel. */
.smeweb-scroller {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(min(19rem, 82%), 1fr);
	gap: 1.25rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	padding-bottom: 0.75rem;
	scrollbar-width: thin;
}

.smeweb-scroller > * {
	scroll-snap-align: start;
}

@media (min-width: 782px) {
	.smeweb-scroller {
		grid-auto-flow: row;
		grid-template-columns: repeat(3, 1fr);
		overflow-x: visible;
	}
}

/* ------------------------------------------------------------------ *
 * 13. Accessibility & motion
 * ------------------------------------------------------------------ */

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 999;
	padding: 0.75rem 1.25rem;
	background-color: var(--wp--preset--color--primary);
	color: #fff;
	font-weight: 500;
	border-radius: 0 0 8px 0;
}

.skip-link:focus {
	left: 0;
}

.screen-reader-text {
	border: 0;
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}

.screen-reader-text:focus {
	clip-path: none;
	height: auto;
	width: auto;
	display: block;
	padding: 0.75rem 1.25rem;
	background-color: var(--wp--preset--color--base);
	z-index: 100000;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}

	.smeweb-marquee__track {
		animation: none;
	}
}

/*
 * The account page.
 *
 * Figma node 5253:963 puts the customer dashboard inside a white card on the wash. The card is
 * 1320px wide there with a 30px radius, and 1320 is wideSize, so the markup says alignwide and
 * no width gets written down twice. The frame's 1200px inner column is the Content measure,
 * which the dashboard takes by declaring nothing.
 *
 * Side padding is (1320 - 1200) / 2 = 60px, held there on a wide screen and allowed to collapse
 * on a narrow one, where 60px of white either side of a 272px sidebar is most of the screen.
 * Vertical padding is the frame's: about 45 above the container and 56 below.
 */
/*
 * The vertical measurements are read off the frame, which is 1920 wide with an 81px header:
 * the copy block starts at 153, so 72 below the header; the card starts at 356, and the copy
 * block is 30 + 18 + 57 + 18 + 30 = 153 tall, which leaves 50 between the lead and the card.
 *
 * The top padding is clamped rather than flat so 72px of wash above the heading does not
 * become most of a phone screen.
 */
/*
 * ------------------------------------------------------------------ *
 * The console, Dashboard-1-v2 to -6-v2
 * ------------------------------------------------------------------ *
 *
 * All six v2 frames are one shell with one card in it. Off the nodes, at the frames' 1920:
 *
 *   sidebar        390 wide at x0, from under the 81px header down to the footer
 *   main           1530 at x390
 *   content column 1230, so 150 clear of the sidebar and 150 clear of the right edge
 *   heading block  centred in that column, 44px in brand blue with a lead under it
 *   card           the full 1230, 30 below the heading block
 *
 * The two measures are written in vw because 390 and 150 are both fractions of that 1920 —
 * 20.3vw and 7.8vw — and the sidebar's width and the padding that clears it then cannot drift
 * apart the way a percentage would: the sidebar is positioned against the section while the
 * padding resolves against its own box, and those are not the same number.
 */
.smeweb-account-page {
	/*
	 * 320, down from the frames' 390.
	 *
	 * 390 was right beside a 1230 card. Beside a 780 one it is half the width of the thing it
	 * navigates, where the reference runs 275 of nav against a 770 card — 36%, not 50%. 320 is
	 * 41% of this card and 16.7% of a 1920 window against the reference's 14.5%.
	 *
	 * It cannot go much below that: the rail's rows are its width less 30 either side, and
	 * อัปโหลดข้อมูลเว็บไซต์ at 17.6px needs 175 beside a 28px icon, 16 of gap and 28 of row
	 * padding — 247 of the 260 a 320 rail gives them.
	 */
	--smeweb-rail: clamp(300px, 22vw, 320px);

	/*
	 * Where the pinned sidebar starts: the header's height when signed in, which is what every
	 * visitor to this page is. Measured 72.19 — the row is 48 of buttons inside 13.6 either
	 * side, and signed in the two header buttons are replaced by the shorter account chip.
	 */
	--smeweb-account-rail-top: 72px;

	/*
	 * The column is a measure, not a fraction of the window.
	 *
	 * The frames draw it 1230 wide at their 1920, and read against the reference the team asked
	 * for — Canva's account settings — that is 60% too wide: measured off that screen, its nav
	 * is 275 of a 1901 window and the content card 770, centred in what is left with about 400
	 * either side. A 1230 line is long enough that a label and its value stop reading as a pair.
	 *
	 * 780 is that 770 rounded to the nearest ten, and it is fixed rather than proportional for
	 * the same reason Canva fixes it: a vw inset would have squeezed the card to 586 at a 1440
	 * window while leaving it enormous at 2560. The gutter beside it is what gives way instead.
	 */
	/*
	 * 960, up from 780.
	 *
	 * 780 came from the reference's 770 and was right while the card sat on plain white with the
	 * facts as the only thing in it. It reads narrow now that the card has a wash behind it and a
	 * 2px ring around it — the same treatment the blog's Trending card wears at 1756 — so the
	 * measure moves up while staying well short of the 1230 this column started at.
	 */
	--smeweb-account-measure: 960px;
	--smeweb-account-inset: clamp(1.5rem, 3vw, 3rem);

	/* 57 above the heading block, and the footer follows the band directly. */
	padding-top: 3.5625rem;
	padding-bottom: 3.5625rem;
}

/*
 * The band the sidebar fills: 1607 of frame less the 81 header and the 618 footer.
 *
 * A viewport measure was the other candidate and it is wrong here — the frames put the footer
 * immediately under this band rather than below the fold, so the height is the design's own
 * number and not what a window happens to be.
 */
@media (min-width: 807px) {
	/*
	 * The window rather than the frame's 908, now that the sidebar is pinned.
	 *
	 * 908 was the frame's own number and right while the footer sat directly under this band. The
	 * footer is off this page now, so the band is the last thing on it — and a pinned sidebar the
	 * height of the window against a band shorter than the window would show its ground running
	 * past where the page ends. The two are the same measure instead.
	 */
	.smeweb-account-page {
		min-height: calc(100vh - var(--smeweb-account-rail-top));
	}
}

/*
 * The heading block: 44px in brand blue over a 17.6px lead, both centred, 30 clear of the card.
 *
 * Same sizes the hero used before it came off — node 5519:5880 is 57 tall for one line, which
 * is 44 at the 1.3 the title has always carried, and the lead's 30 is the small preset at 1.7.
 * The pattern sets the colour and the sizes through presets; what is left here is the rhythm.
 */
.smeweb-account-head {
	margin-bottom: 1.875rem;
}

.smeweb-account-head__title {
	/*
	 * No bottom margin: this had 10 under it to open up a gap against the lead, and the lead is
	 * gone. The head block's own 30 carries the space to the card.
	 */
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	letter-spacing: -0.01em;
	line-height: 1.3;
}

/*
 * 18px above and below, which is the gap the frame's copy block carries between all three of
 * its lines. Only the heading needs to say so: adjacent margins collapse to the larger of the
 * two, so 18 here beats the eyebrow's own 0.35rem and the lead needs nothing.
 *
 * These were three declarations — a spacing|40 bottom margin, then a spacing|20 top and a
 * spacing|20 bottom appended under it, which quietly won and left the gap at 12.
 *
 * line-height is the frame's 57.2 over 44.
 */
/*
 * .smeweb-account-title and .smeweb-account-lede stood here for the centred hero this page
 * opened with. The v2 frames have no hero; the block above carries what is left of it.
 */

/*
 * The card is the frame's: white, 30px radius, no border, 45px of padding above the dashboard
 * and 57 below, which is what puts a 602px container in a 704px card.
 *
 * This rule had a second set of all four properties appended to it — a 20px radius, a 1px
 * outline border, 40/48 padding and a tighter shadow — and being later they won, which is why
 * the live card measured 20px round and 692 tall against the frame's 30 and 704. Resolved to
 * one value each rather than left as two.
 *
 * The shadow is the one thing here the frame does not draw: node 5255:1076 is flat white. It
 * is kept because the wash behind it is nearly white too, and with no border and no shadow
 * the card has no edge at all — but it is now the front page's own card shadow rather than a
 * softer one of its own, counted there as 0 10px 30px rgba(20, 20, 43, 0.08).
 *
 * The 30px radius stays. The front page's cards are 18 and its full-bleed bands are 40, and
 * this card is 1320 wide — band-sized — so 30 sits where it belongs between the two. It is
 * also the frame's number.
 */
/*
 * Not a card any more — a measure.
 *
 * It was white with a 30px radius and a shadow, holding the plugin's dashboard inside it. Read
 * off the Dashboard-1 frame, that is a frame the design does not have: the sidebar and the panel
 * are two separate cards standing directly on the wash, with about 29px between them and nothing
 * around them. The white wrapper was the outer of the two frames somebody looking at this page
 * sees, and it is what made it read as กรอบซ้อนกรอบ.
 *
 * Measured on the frame render and scaled back to its 1920: the pair spans 202 to 1754, so 1552
 * wide — the sidebar 381, the gap 29, the panel 1142. That is wider than the theme's Wide 1320,
 * so the width is set here rather than by changing wideSize, which every other page uses.
 */
.smeweb-account-card {
	/*
	 * As wide as the footer's content, asked for by name.
	 *
	 * That measure is the window less --smeweb-shell-inset on each side — the number the
	 * navigation row, the footer bands, the latest-posts section and the picks band all share.
	 * Measured on the live footer: content runs 80 to 1771 at a 1850 window and 67 to 1373 at
	 * 1440, so 1691 and 1306. The frame's own pair is 1552 at its 1920, which sits inside this
	 * at that width; matching the footer keeps the account area on the one measure the rest of
	 * the site is built to rather than adding a third.
	 *
	 * v2 places the column against the sidebar instead, so the offset lives on the panel and on
	 * the heading block, and this is only a full-width wrapper now: the padding below is zero.
	 *
	 * The block is alignfull for this to work at all — as alignwide, core caps it at wideSize
	 * (1320) with a max-width the padding cannot escape.
	 */
	padding-inline: 0;
}

/*
 * And the dashboard inside it takes that width too.
 *
 * post-content is a constrained layout, so core caps every child at the Content measure — 1200
 * — which held the pair at 1200 no matter what the card did.
 */
/*
 * The cap is on post-content itself, not on its children.
 *
 * Traced up from the app container: the card is 1850 with 79.5px of shell inset either side, so
 * 1691 of room — the footer measure exactly — and everything under it was pinned to 1200.
 *
 * The cap came from the card being a constrained layout: core gives the children of one a
 * max-width of the Content measure, and its selector ties with a single class of ours and is
 * printed after this stylesheet, so it won both times it was overridden here. The card is a
 * plain flow layout now and emits no cap at all, which is the cause rather than the symptom.
 *
 * These stay because the plugin's own wrappers carry a 1200 of their own once they are inside
 * anything constrained — post-content still is, further up.
 */
.smeweb-account-body,
.smeweb-account-body > * {
	max-width: none;
}

/*
 * post-content also carries the root gutter, which took 24px off each side and left 1643 where
 * the footer has 1691. The card already holds the inset, so this pair of paddings is the same
 * gutter applied twice.
 */
.smeweb-account-body {
	padding-inline: 0;
}

/*
 * The dashboard's own width, 1553, and why it is not the footer's.
 *
 * The frame is 381 of sidebar, 29 of gap and a 1143 panel card, and 1143 less its 42 of padding
 * a side is the 1059 that .smeweb-mysite is capped at. So the three numbers close on each other:
 * cap the outside at 1553 and the panel content lands exactly on its own maximum with nothing
 * spare inside the card.
 *
 * It was the shell measure — 1691 at a 1920 window, the same as the footer — and those extra
 * 138px had nowhere to go but into the panel, which is where the sparse right-hand side of it
 * came from. 1553 also sits inside the band the usual containers use: Bootstrap stops at 1320,
 * this theme's own wideSize is 1320, Tailwind's widest screen is 1536.
 *
 * !important because the plugin's own stylesheet puts max-width: 1200px here and is printed
 * after this one, where two of our classes tie with it and lose on order.
 */
/*
 * No measure here, and it still needs !important because the plugin sets max-width: 1200px from
 * a stylesheet printed after this one.
 *
 * This held 1553 — Dashboard-1's centred pair of cards — with margin-inline: auto under it.
 * Measured on v2 that was the fault behind two others at once: it capped the wrapper and
 * centred it, which put its left edge at 184, and the sidebar is positioned against an ancestor
 * so it went to 184 as well. v2 is not centred at all: the sidebar is at the window's edge and
 * the column is placed by padding on the panel.
 */
.smeweb-account-body .fct_customer_profile_wrap {
	max-width: none !important;
	margin-inline: 0;
}

/*
 * The card ends where the dashboard ends.
 *
 * Fluent Cart prints min-height: 700px inline on the root container, which is right for a
 * dashboard sitting alone on a page and wrong inside a card: the content measured 602px, so
 * the card ran 800px tall with 98px of blank white under the border. The frame's card is 704.
 *
 * Nothing collapses without it. The plugin gives .fct-customer-dashboard-main-content its own
 * min-height: 600px, which is the same floor the frame draws (min-h-[600px] on node 5255:1143),
 * and that one is in a stylesheet rather than inline. !important is here because the 700 is an
 * inline style and there is no other way past it.
 */
.smeweb-account-body .fct-customer-root-container {
	min-height: 0 !important;
}

/*
 * The dashboard's colours, set through the variables the plugin publishes rather than by
 * overriding its rules.
 *
 * Fluent Cart reads a colors attribute on the block and prints it as custom properties on
 * .fct-customer-root-container. Page 30 passes no attribute, so that inline style is empty and
 * these inherit — set them here and the plugin styles itself. Overriding its own selectors
 * instead would mean re-specifying a 393KB stylesheet every time the plugin updates.
 *
 * The frame draws the plugin's defaults: #d6dae1 borders, #565865 nav text, #253241 active,
 * #f5f6f7 active row. Those become the theme's outline, muted, primary and surface — the same
 * roles, in the palette the rest of the site is built from, which is what matching the mood
 * means here. The one deliberate change is the active nav item: the frame has it dark slate and
 * it is brand blue here, because blue is how this site marks the thing you are on.
 *
 * The logout button is left alone, but not because it is fine: measured, the frame's #f04438
 * on #fcebe6 is 3.25:1, and 14px text needs 4.5. The note here used to claim it passed, which
 * was wrong — it was never measured, only assumed from it being the plugin's default.
 *
 * It is still not set to the theme's accent, which is #FF0000 in all three accent slots and
 * comes out worse on pale pink. Reaching 4.5 means a darker red than either, which is a change
 * to the plugin's palette rather than a mapping of it, so it is waiting on a decision.
 *
 * What the variables do not reach: borders on individual controls. The buttons in the panel
 * kept #d6dae1 on their border and neither --fct-border-color nor the btn-border variable
 * moved it — the plugin compiles Tailwind, so that border is a literal
 * rgb(214 218 225 / var(--tw-border-opacity)) with no variable to set. Two vars were added
 * for it and measured to do nothing, so they came back out.
 *
 * That note used to end by saying overriding the plugin's own selectors was not worth it for
 * one grey. It is now done, in the section further down that puts the dashboard in the site's
 * vocabulary — the greys turned out to be several, not one, and each needed the selector
 * rather than a variable.
 * The dashboard's colours and theme tokens bridge.
 */
.smeweb-account-body .fct-customer-root-container {
	--fct-customer-dashboard-border-color: var(--wp--preset--color--outline);
	--fct-customer-dashboard-divider-color: var(--wp--preset--color--outline);
	--fct-customer-dashboard-title-color: var(--wp--preset--color--contrast);
	--fct-customer-dashboard-primary-text-color: var(--wp--preset--color--contrast);
	--fct-customer-dashboard-text-color: var(--wp--preset--color--muted);
	--fct-customer-dashboard-secondary-text-color: var(--wp--preset--color--muted);
	--fct-customer-dashboard-sub-title-color: var(--wp--preset--color--muted);
	--fct-customer-dashboard-nav-text-color: var(--wp--preset--color--contrast);
	--fct-customer-dashboard-nav-active-text-color: var(--wp--preset--color--primary);
	--fct-customer-dashboard-nav-active-bg-color: var(--wp--preset--color--surface);
	--fct-customer-dashboard-nav-active-bar-color: var(--wp--preset--color--primary);
	--fct-customer-dashboard-btn-bg-color: var(--wp--preset--color--base);
	--fct-customer-dashboard-btn-border-color: var(--wp--preset--color--outline);
	--fct-customer-dashboard-btn-text-color: var(--wp--preset--color--contrast);
	--fct-customer-dashboard-paginator-text-color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--body);
}

/* The dashboard is the whole page here, so it needs no prose margin above or below. */
.smeweb-account-body > .fct_customer_profile_wrap {
	margin-block: 0;
}

/*
 * ------------------------------------------------------------------ *
 * Fluent Cart UI Bridge (Match SMEWeb Design System)
 * ------------------------------------------------------------------ */

/* Headings inside customer dashboard */
.smeweb-account-body h2,
.smeweb-account-body h3,
.smeweb-account-body h4 {
	font-family: var(--wp--preset--font-family--display) !important;
	font-weight: 600 !important;
	color: var(--wp--preset--color--contrast) !important;
}

/* Sidebar navigation links and buttons */
.smeweb-account-body .fct-customer-root-container nav a,
.smeweb-account-body .fct-customer-root-container nav button,
.smeweb-account-body [class*="dashboard-sidebar"] a,
.smeweb-account-body [class*="dashboard-sidebar"] button {
	border-radius: 12px !important;
	font-weight: 500 !important;
	padding: 0.65rem 1rem !important;
	transition: background-color 0.18s ease, color 0.18s ease, transform 0.15s ease !important;
}

.smeweb-account-body .fct-customer-root-container nav a:hover,
.smeweb-account-body .fct-customer-root-container nav button:hover {
	background-color: var(--wp--preset--color--surface) !important;
	color: var(--wp--preset--color--primary) !important;
}

/*
 * Buttons inside the dashboard, on the site's pill.
 *
 * The logout link is excluded by name. Its class is fct-customer-logout-btn, which contains
 * "btn", so a[class*="btn"] was matching it — and that selector carries a class, an attribute
 * and a type against the two classes of the rule that styles the logout row, so at equal
 * !important it won on specificity and held the row at a 999px capsule. Which only showed
 * while the hover tint was under it.
 */
.smeweb-account-body button,
.smeweb-account-body a[class*="btn"]:not(.fct-customer-logout-btn),
.smeweb-account-body .fct-btn {
	border-radius: 999px !important;
	font-family: var(--wp--preset--font-family--body) !important;
	font-weight: 500 !important;
	transition: transform 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease, border-color 0.18s ease !important;
}

/* Primary actions */
.smeweb-account-body button[type="submit"],
.smeweb-account-body button[class*="bg-primary"],
.smeweb-account-body button[class*="bg-blue"],
.smeweb-account-body .fct-btn-primary,
.smeweb-account-body .fct-customer-root-container [class*="bg-"][class*="primary"] {
	background-color: var(--wp--preset--color--primary) !important;
	color: #ffffff !important;
	border-color: var(--wp--preset--color--primary) !important;
	padding: 0.6rem 1.4rem !important;
}

.smeweb-account-body button[type="submit"]:hover,
.smeweb-account-body button[class*="bg-primary"]:hover,
.smeweb-account-body button[class*="bg-blue"]:hover,
.smeweb-account-body .fct-btn-primary:hover {
	background-color: var(--wp--preset--color--primary-dark) !important;
	border-color: var(--wp--preset--color--primary-dark) !important;
	transform: translateY(-1px);
	box-shadow: 0 6px 18px rgba(31, 42, 205, 0.22) !important;
}

/* Secondary / Outline buttons */
.smeweb-account-body button[class*="border"],
.smeweb-account-body .fct-btn-secondary,
.smeweb-account-body .fct-btn-outline {
	border: 1.5px solid var(--wp--preset--color--outline) !important;
	background-color: var(--wp--preset--color--base) !important;
	color: var(--wp--preset--color--contrast) !important;
	padding: 0.55rem 1.25rem !important;
}

.smeweb-account-body button[class*="border"]:hover,
.smeweb-account-body .fct-btn-secondary:hover {
	border-color: var(--wp--preset--color--primary) !important;
	color: var(--wp--preset--color--primary) !important;
	background-color: var(--wp--preset--color--surface) !important;
}

/*
 * Form inputs & controls — plain fields only, never an Element Plus one.
 *
 * The profile tab's fields are Element Plus composites: the visible box is drawn on
 * .el-input__wrapper and the <input> inside it is deliberately borderless and unpadded. This
 * rule was reaching that inner input, and measured there it came out 454x53 inside a 488x40
 * wrapper, inset 17px from its left edge — a second rounded box hanging out of the first,
 * which is what the tab looked like.
 *
 * The wrapper is left alone rather than restyled to match, because Fluent Cart stacks these
 * three fields as one group and gives them 8px 8px 0 0 / square / 0 0 8px 8px between them.
 * A uniform radius here would flatten that into three separate boxes.
 *
 * :not() on each selector rather than one wrapping :not(), so the specificity stays where the
 * rest of this section put it.
 */
.smeweb-account-body input[type="text"]:not(.el-input__inner),
.smeweb-account-body input[type="email"]:not(.el-input__inner),
.smeweb-account-body input[type="password"]:not(.el-input__inner),
.smeweb-account-body input[type="tel"]:not(.el-input__inner),
.smeweb-account-body input[type="number"]:not(.el-input__inner),
.smeweb-account-body select:not(.el-select__inner),
.smeweb-account-body textarea:not(.el-textarea__inner) {
	border-radius: 12px !important;
	border: 1px solid var(--wp--preset--color--outline) !important;
	padding: 0.65rem 1rem !important;
	font-size: var(--wp--preset--font-size--small) !important;
	color: var(--wp--preset--color--contrast) !important;
	background-color: var(--wp--preset--color--base) !important;
	transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
}

/* Same exclusion on focus: a 3px ring on the inner input draws it inside the wrapper's own
   ring, so Element Plus keeps the focus style the plugin already gives it. */
.smeweb-account-body input:focus:not(.el-input__inner),
.smeweb-account-body select:focus:not(.el-select__inner),
.smeweb-account-body textarea:focus:not(.el-textarea__inner) {
	border-color: var(--wp--preset--color--primary) !important;
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.12) !important;
	outline: none !important;
}

/* Tables in customer dashboard */
.smeweb-account-body table {
	border-collapse: separate !important;
	border-spacing: 0 !important;
	border: 1px solid var(--wp--preset--color--outline) !important;
	border-radius: 14px !important;
	overflow: hidden !important;
	width: 100% !important;
}

.smeweb-account-body table thead th,
.smeweb-account-body table th {
	background-color: var(--wp--preset--color--surface) !important;
	color: var(--wp--preset--color--contrast) !important;
	font-weight: 600 !important;
	padding: 0.85rem 1.15rem !important;
	border-bottom: 1px solid var(--wp--preset--color--outline) !important;
	font-size: 0.875rem !important;
}

.smeweb-account-body table td {
	padding: 0.95rem 1.15rem !important;
	border-bottom: 1px solid var(--wp--preset--color--outline) !important;
	vertical-align: middle !important;
}

.smeweb-account-body table tr:last-child td {
	border-bottom: none !important;
}

/* Badges & Status pills */
.smeweb-account-body [class*="badge"],
.smeweb-account-body [class*="status"],
.smeweb-account-body span[class*="rounded"] {
	border-radius: 999px !important;
	font-weight: 500 !important;
	padding: 0.25rem 0.85rem !important;
	font-size: 0.8125rem !important;
	display: inline-flex;
	align-items: center;
	line-height: 1.3;
}

/*
 * ------------------------------------------------------------------ *
 * The dashboard in the site's vocabulary, not the plugin's
 * ------------------------------------------------------------------ *
 *
 * The frame the Figma node draws around the dashboard is the plugin's own: an 8px box with a
 * 1px border, sitting inside the theme's 30px white card. Two frames, one inside the other,
 * which is a shape this site does not use anywhere else — every other page is a single card
 * on the wash. That nesting is what reads as wrong on the page, so the inner one goes.
 *
 * The numbers below are counted off the front page rather than chosen. Measuring every box
 * over 60x40 in its <main>: radius 12px on eight of them, 999px on five, 18px on five, 40px
 * on one, and exactly one border colour in the whole page — 1px #e4e0f0, the outline preset.
 * Its cards carry 0 10px 30px rgba(20, 20, 43, 0.08) and its buttons are capsules.
 *
 * So: 12px for the rows, 999px for the buttons, outline for every hairline, surface for every
 * tint. Nothing new is invented; the plugin's greys are swapped for the presets that hold the
 * same role.
 */

/*
 * One frame, not two. The white card is the frame; this keeps only the hairline between the
 * sidebar and the panel, which the plugin already draws in the right colour.
 */
/*
 * !important and a third class, because the plugin's rule is
 * .fluent-cart-customer-profile-app:not(.el-dialog):not(.el-popper):not(…) — one class plus a
 * chain of :not(), and every :not() counts as a class, so it outweighs anything sensible
 * written with plain selectors. It carries no !important of its own, so one here is enough.
 */
.smeweb-account-body .fct-customer-root-container .fct-customer-dashboard-app-container {
	border: 0 !important;
	border-radius: 0 !important;
}

/*
 * The two hairlines the plugin draws off-palette.
 *
 * The divider under the avatar is #EAECF0 and the collapse button's ring is #D6DAE1 — two
 * more greys in a page whose only border colour is #e4e0f0. Neither is reachable through the
 * dashboard variables: measured, --fct-customer-dashboard-border-color moves the container
 * and the table and leaves these two alone.
 *
 * The button has no class of its own, so it is addressed as the one unclassed button inside
 * the dashboard root rather than by a class that does not exist.
 */
.smeweb-account-body .fct-customer-dashboard-customer-info {
	border-bottom-color: var(--wp--preset--color--outline);
}

.smeweb-account-body .fct-customer-root-container button:not([class]) {
	border-color: var(--wp--preset--color--outline);
}

/*
 * The card stops being mostly white.
 *
 * The plugin floors its panel at 600px, and measured, the dashboard tab's content is 96px
 * tall and the downloads tab's is 337 — so the card ran 704px with about 500 of nothing in
 * it. 380 clears the taller of the two and still leaves the sidebar its four rows, the
 * avatar banner and the logout capsule without crowding them.
 *
 * A floor, not a height: a tab with real orders in it grows past this on its own.
 */
.smeweb-account-body .fct-customer-dashboard-main-content {
	min-height: 380px;
}

/* The rows and the table take the radius the front page uses most. */
.smeweb-account-body .fct-customer-nav-link,
.smeweb-account-body .fct-customer-dashboard-table {
	border-radius: 12px;
}

/* Tints come from the palette: the empty-state icon well was the plugin's #F5F6F7. */
.smeweb-account-body .fct-empty-icon-box {
	background-color: var(--wp--preset--color--surface);
}

/*
 * Buttons in the panel become the capsule the rest of the site uses — "กลับไปช้อปปิ้งตอนนี้"
 * and its siblings are Element Plus buttons at 8px with a #D6DAE1 ring.
 *
 * Only the neutral ones. A primary el-button paints its own background, and rounding it is
 * all this needs to match; the border colour would show through as a rim on the wrong side.
 *
 * Three classes and !important here because the plugin's own rule already has both:
 * .fluent-cart-customer-profile-app .el-button sets the radius, the border width and
 * rgb(214 218 225 / var(--tw-border-opacity, 1)) with !important on each. Two classes plus
 * !important would tie on specificity and be decided by load order, so this takes one more.
 */
.smeweb-account-body .fct-customer-root-container .el-button {
	border-radius: 999px !important;
}

.smeweb-account-body .fct-customer-root-container .el-button:not(.el-button--primary) {
	border-color: var(--wp--preset--color--outline) !important;
}

/*
 * Logout keeps its pale pink and loses the failing red.
 *
 * #F04438 on #FCEBE6 measures 3.25:1 and 14px text needs 4.5. Walking the same hue darker:
 * #D92D20 is 4.18 and still short, #C4241A is 5.03. That is the value here — not a palette
 * preset, because the theme's three accent slots are all #FF0000, which is 3.9:1 on this
 * ground and worse than what it replaces.
 *
 * The icon follows the label: the plugin draws it with currentColor.
 */
.smeweb-account-body .fct-customer-logout-btn {
	color: #C4241A;
}

/*
 * ------------------------------------------------------------------ *
 * เว็บไซต์ของฉัน — Figma frame Dashboard-1, node 5381:440
 * ------------------------------------------------------------------ *
 *
 * The panel is printed by smeweb_account_my_website() in place of the plugin's Vue app, so it
 * carries the plugin's own .fct-customer-dashboard-main-content wrapper to inherit the panel
 * padding and the floor the account section sets.
 *
 * Numbers read off the node rather than chosen: card 1px border at 20px radius, heading 24px
 * bold, the two columns 389 and 422 wide with 55 between them, row labels 139px, rows 31px tall
 * with 6px between, and the package on a capsule at 12px by 4px of padding.
 *
 * The frame's #1725cc becomes the theme's primary (#1f2acd) for the border and the capsule. They
 * are the same blue one shade apart and carrying both would put a second one in the palette; the
 * two icons keep the frame's own fills, because those are in the exported SVGs.
 */
/*
 * The panel content is a query container, and it stops growing at the frame's own measure.
 *
 * container-type rather than a viewport query, because what decides whether the two columns
 * fit is the width of this block and not the window's: the sidebar holds its width whatever
 * the window does, so at a 1000px window this box is 396 wide while the old max-width: 900
 * rule still had it in two columns, drawing the screenshot 138 wide beside a column of dates
 * broken onto three lines each. The queries further down read this box instead.
 *
 * 1059 is the frame's own content width — 389 of screenshot, 55 of gap, 615 of facts. Above
 * about a 1750px window the panel is wider than that, and with nothing to stop it the
 * screenshot grew to 469 and the value column to some 700 holding a single date.
 */
/*
 * A query container, and no measure of its own: the column's width is set by the panel's inset
 * now, and 1059 was Dashboard-1's card. The queries below read this box rather than the window,
 * because what decides whether the two columns fit is the card and not the screen.
 */
.smeweb-mysite {
	container-type: inline-size;
	container-name: mysite;
}

/*
 * The heading block spans both columns of the card, because the frame puts it above the two
 * rather than inside either — nodes 5407:526 and 5411:530 sit at 42 by 42 in the card, the
 * same inset as everything else in it.
 */
.smeweb-mysite__head {
	grid-column: 1 / -1;
	margin-bottom: 1.5rem;
}

.smeweb-mysite__title {
	margin: 0 0 0.35rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.5rem;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--wp--preset--color--contrast);
}

.smeweb-mysite__lede {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.7;
	color: var(--wp--preset--color--muted);
}

.smeweb-mysite__card {
	padding: 1.75rem 2rem;
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 12px;
}

.smeweb-mysite__card + .smeweb-mysite__card {
	margin-top: 1rem;
}

/*
 * The site card is the one the frame draws, so it takes the frame's border and radius: a 1px
 * brand-blue outline at 20px, which is what marks it out from the neutral help card under it.
 */
.smeweb-mysite__card--site {
	display: grid;
	/*
	 * The frame is drawn on a 1143px card; the real panel is 888 wide, because the account
	 * card is 1320 less its padding less the 272px sidebar. Measured with the frame’s fixed
	 * 389px shot, that left the value column at 159px and broke both the address and the
	 * expiry warning onto three lines each. So the shot flexes down to 240 and the facts take
	 * the frame’s proportion instead: 389 against 615 is 39 to 61, which holds at any panel
	 * width. minmax(240px, 389px) was the first attempt and did nothing — a track with a max
	 * takes its maximum whenever the row fits, so the shot stayed 389 and the values stayed 159.
	 */
	grid-template-columns: minmax(0, 39fr) minmax(0, 61fr);
	gap: clamp(1.5rem, 4vw, 3.4375rem);
	align-items: start;
	padding: 2.625rem;
	border-color: var(--wp--preset--color--primary);
	border-radius: 20px;
}

/* Left column: the screenshot, the capsule, the manual link. */
.smeweb-mysite__shot {
	display: grid;
	gap: 0.6875rem;
}

/* The frame draws it 355 wide beside the facts; stacked, a ceiling would only leave slack. */
/*
 * ------------------------------------------------------------------ *
 * โดเมนเว็บไซต์ — Dashboard-4-v2
 * ------------------------------------------------------------------ *
 *
 * Three columns in the one card, ruled under the head and under each row. The widths are the
 * frame's, measured off the render and scaled back to its 1920: the columns begin at the card's
 * own 46 inset, then at 586 and at 918 of a 1138 content width, which is 52, 29 and 19.
 *
 * A table because it is one — three headed columns of the same kind of fact, one row per domain.
 */
.smeweb-mysite__card--table {
	display: block;
}

.smeweb-dom {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--small);
	text-align: left;
}

.smeweb-dom th:nth-child(1) {
	width: 52%;
}

.smeweb-dom th:nth-child(2) {
	width: 29%;
}

.smeweb-dom th:nth-child(3) {
	width: 19%;
}

.smeweb-dom th,
.smeweb-dom td {
	padding: 1.125rem 1rem 1.125rem 0;
	vertical-align: middle;
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

/*
 * No band behind the head. The theme tints th for prose tables, and the frame rules this
 * head rather than filling it.
 */
.smeweb-dom th {
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
	background: none;
}

.smeweb-dom td {
	color: var(--wp--preset--color--muted);
}

/* The address is the row's subject, so it carries the text colour and can break anywhere. */
.smeweb-dom__name {
	color: var(--wp--preset--color--contrast) !important;
	font-weight: 500;
	/*
	 * The safety net for an address with no break in it. It is only reached in the stacked layout
	 * below when a host is longer than the card, because until then the head names the columns and
	 * the value has the width to sit on one line.
	 */
	overflow-wrap: anywhere;
}

/* The per-cell labels the markup carries. The head names the columns while there is a head. */
.smeweb-dom__k {
	display: none;
}

/* The empty history's one action, under the sentence that explains why the card is empty. */
.smeweb-mysite__empty--center + .smeweb-mysite__empty--center {
	margin-top: 1.25rem;
}

/*
 * Three columns become three labelled lines once the card cannot hold them side by side.
 *
 * Measured at 430 before this: the head stayed, the cells squeezed to about 100px each, and
 * .smeweb-dom__name's overflow-wrap did what it was asked to — it broke the address wherever it
 * ran out of room, seven lines of "https:/ /jelly- enter- 64189 582.fi gma.si te". The orders
 * table solves the same problem by scrolling sideways inside a wrapper; three short columns do
 * not need that, and a phone should not have to scroll to read two domains.
 *
 * The head goes and the spans in each cell take over naming the values — real text, so it is
 * announced and searchable, which generated content is not.
 */
@container mysite (max-width: 600px) {
	.smeweb-dom thead {
		display: none;
	}

	.smeweb-dom,
	.smeweb-dom tbody,
	.smeweb-dom tr,
	.smeweb-dom td {
		display: block;
		width: auto;
	}

	.smeweb-dom tr {
		padding: 1rem 0;
		border-bottom: 1px solid var(--wp--preset--color--outline);
	}

	.smeweb-dom tr:first-child {
		padding-top: 0;
	}

	.smeweb-dom tr:last-child {
		padding-bottom: 0;
		border-bottom: 0;
	}

	/*
	 * !important and a second class, because .smeweb-account-body table td dresses every table in
	 * the dashboard with padding and a rule and does it with !important — one class and two types,
	 * which outranks a plain .smeweb-dom td whatever the order. Measured before this: each cell
	 * kept its 15.2/18.4 padding and its own hairline, so one domain drew three rules instead of
	 * the row drawing one.
	 */
	.smeweb-account-body .smeweb-dom td {
		padding: 0 !important;
		border-bottom: 0 !important;
	}

	.smeweb-dom td + td {
		margin-top: 0.625rem;
	}

	.smeweb-dom__k {
		display: block;
		margin-bottom: 0.125rem;
		font-size: var(--wp--preset--font-size--x-small);
		font-weight: 500;
		line-height: 1.5;
		color: #6E6E85;
	}
}

/*
 * ------------------------------------------------------------------ *
 * จัดการข้อมูลส่วนตัว — Dashboard-5-v2
 * ------------------------------------------------------------------ *
 *
 * Three titled sections in the one card, each a list of label-over-value rows with the action on
 * the right, ruled between. The frame's own rhythm: the section title at 20px over a small lead,
 * rows about 58 tall, and a hairline under every row and every section but the last.
 *
 * The edit forms are <details>, so the summary is the button and the form is what opens under it.
 * That means the button needs the marker taken off and the cursor put back — a summary is not a
 * button as far as the browser is concerned, only as far as the reader is.
 */
.smeweb-prof__sec {
	margin-inline: calc(var(--smeweb-card-pad) * -1);
	padding: 0 var(--smeweb-card-pad) 1.75rem;
	margin-bottom: 1.75rem;
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

.smeweb-prof__sec--last {
	padding-bottom: 0;
	margin-bottom: 0;
	border-bottom: 0;
}

/* The first row of a section sits under its lead, so it does not need a rule above it as well. */
.smeweb-prof__row:first-of-type {
	padding-top: 0;
}

.smeweb-prof__title {
	margin: 0 0 0.25rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	font-weight: 700;
	color: var(--wp--preset--color--contrast);
}

.smeweb-prof__lede {
	margin: 0 0 1.25rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

/*
 * The rows, at the reference's rhythm rather than the tight one they started with.
 *
 * Two things read as cramped beside Canva's: 16px of vertical padding against its 32, and a rule
 * that stopped at the content's edge while its rules run the full width of the card. The
 * negative margin takes each row back out to the border and the padding brings the content in,
 * so the rule spans the card and the text still lines up with the heading above it.
 */
.smeweb-prof__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	margin-inline: calc(var(--smeweb-card-pad) * -1);
	padding: 1.75rem var(--smeweb-card-pad);
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

.smeweb-prof__row:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.smeweb-prof__cell {
	display: grid;
	gap: 0.15rem;
	min-width: 0;
}

.smeweb-prof__label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
}

.smeweb-prof__value {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	overflow-wrap: anywhere;
}

.smeweb-prof__note {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
}

/* 72, which is both the reference's and the size the sidebar's own avatar is drawn at. */
.smeweb-prof__avatar {
	display: block;
	width: 72px;
	height: 72px;
	border-radius: 999px;
	object-fit: cover;
}

/*
 * The button, and the summary that has to pass for one.
 *
 * list-style and ::marker between them take the triangle off in every engine that ships one —
 * WebKit uses the first and the rest use the second.
 */
.smeweb-prof__btn {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	min-height: 40px;
	padding: 0.4rem 1.1rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	text-decoration: none;
	cursor: pointer;
	list-style: none;
}

.smeweb-prof__btn::-webkit-details-marker {
	display: none;
}

.smeweb-prof__btn::marker {
	content: "";
}

.smeweb-prof__btn:hover,
.smeweb-prof__btn:focus-visible {
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary);
}

.smeweb-prof__btn--primary {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
}

.smeweb-prof__btn--primary:hover,
.smeweb-prof__btn--primary:focus-visible {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary-dark);
	border-color: var(--wp--preset--color--primary-dark);
}

/*
 * The password button is red and filled, as the frame draws it. #C4241A rather than the accent's
 * #FF0000 for the reason the logout row gives: white on #FF0000 measures 3.9:1 and this carries
 * a label.
 */
.smeweb-prof__btn--danger {
	color: var(--wp--preset--color--base);
	background-color: #C4241A;
	border-color: #C4241A;
}

.smeweb-prof__btn--danger:hover,
.smeweb-prof__btn--danger:focus-visible {
	color: var(--wp--preset--color--base);
	background-color: #A21D15;
	border-color: #A21D15;
}

.smeweb-prof__saved {
	margin: 0 0 1.25rem;
	padding: 0.6rem 1rem;
	font-size: var(--wp--preset--font-size--small);
	color: #3F7D0A;
	background-color: #f2f8ea;
	border-radius: 8px;
}

/*
 * The upload's failure notice, in the same shape as the success one.
 *
 * #C4241A on #fdf1f0 measures 5.6:1, which the green above clears too — an error a customer has
 * to read to fix is not the place to spend contrast.
 */
.smeweb-prof__failed {
	margin: 0 0 1.25rem;
	padding: 0.6rem 1rem;
	font-size: var(--wp--preset--font-size--small);
	color: #C4241A;
	background-color: #fdf1f0;
	border-radius: 8px;
}

/*
 * ------------------------------------------------------------------ *
 * The profile dialogs — แก้ไขชื่อ / เปลี่ยนรูปภาพ / เปลี่ยนรหัสผ่าน
 * ------------------------------------------------------------------ *
 *
 * Three forms that used to open inline under their row, as modals over the page — the shape the
 * reference uses for the same three actions.
 *
 * The Popover API, and no JavaScript at all. popovertarget on a button opens the panel it names
 * and popovertargetaction="hide" closes it; the browser gives the rest for free — the top layer,
 * so the panel clears the fixed sidebar and the sticky header without a z-index; ::backdrop for
 * the scrim; Escape and a click outside to dismiss; and focus moved into the panel by autofocus.
 * A <dialog> plus showModal() would need a script for what the attribute does declaratively, and
 * :target — which this theme uses for the template preview — writes the panel into the URL and
 * cannot trap focus.
 *
 * The cost is Safari 17, a year newer than the container queries this stylesheet already needs.
 * Older browsers ignore the attribute and the panel would render inline, so the closed state is
 * pinned shut below rather than left to the UA.
 */
.smeweb-modal[popover] {
	position: fixed;
	inset: 0;
	width: 100vw;
	max-width: 100vw;
	height: 100vh;
	max-height: 100vh;
	margin: 0;
	padding: 1.25rem;
	overflow: auto;
	background: transparent;
	border: 0;
	/* Centring is on the open state, because the UA hides this with display and flex would show it. */
	align-items: center;
	justify-content: center;
}

.smeweb-modal:popover-open {
	display: flex;
}

/* Nothing shows the panel where popover is unsupported, rather than everything showing at once. */
@supports not selector(:popover-open) {
	.smeweb-modal[popover] {
		display: none;
	}
}

/*
 * White and blurred rather than dimmed, which is the reference's own scrim.
 *
 * On a page this light a dark wash reads as a different product; the blur is what separates the
 * panel from the page, and the shadow under the card does the rest.
 */
.smeweb-modal::backdrop {
	background-color: rgba(255, 255, 255, 0.55);
	backdrop-filter: blur(8px) saturate(1.4);
	-webkit-backdrop-filter: blur(8px) saturate(1.4);
}

.smeweb-modal__card {
	width: min(27.5rem, 100%);
	max-height: calc(100vh - 2.5rem);
	overflow-y: auto;
	padding: 1.75rem;
	background-color: var(--wp--preset--color--base);
	border-radius: 16px;
	box-shadow: 0 1.5rem 4rem rgba(20, 20, 43, 0.22);
	/* @starting-style below gives this something to travel from on the way open. */
	transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.33, 1, 0.68, 1);
}

@starting-style {
	.smeweb-modal:popover-open .smeweb-modal__card {
		opacity: 0;
		transform: translateY(0.5rem) scale(0.98);
	}
}

@media (prefers-reduced-motion: reduce) {
	.smeweb-modal__card {
		transition: none;
	}
}

.smeweb-modal__title {
	margin: 0 0 1.25rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: -0.01em;
	color: var(--wp--preset--color--contrast);
}

.smeweb-modal__form {
	display: grid;
	gap: 1rem;
}

.smeweb-modal__label {
	display: grid;
	gap: 0.375rem;
	font-size: var(--wp--preset--font-size--small);
	color: #6E6E85;
}

.smeweb-modal__label input {
	width: 100%;
	padding: 0.75rem 0.875rem;
	font-family: inherit;
	font-size: 1rem;
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 10px;
}

.smeweb-modal__label input:focus {
	outline: 0;
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.16);
}

/* A file input cannot be restyled past its own button, so it is only given room. */
.smeweb-modal__label input[type="file"] {
	padding: 0.625rem;
	font-size: var(--wp--preset--font-size--x-small);
	background-color: #f9f9ff;
}

.smeweb-modal__hint {
	margin: -0.375rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.6;
	color: #6E6E85;
}

.smeweb-modal__actions {
	display: flex;
	justify-content: flex-end;
	gap: 0.75rem;
	margin-top: 0.5rem;
}

/*
 * The confirming button is a submit, so it already carries the dashboard's blue pill from the
 * button rules further up this file — including their padding, which is why cancel is given the
 * same numbers here rather than its own.
 */
.smeweb-modal__btn {
	min-height: 40px;
	padding: 0.6rem 1.4rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	background-color: transparent;
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 999px;
	cursor: pointer;
}

.smeweb-modal__btn:hover,
.smeweb-modal__btn:focus-visible {
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary);
}

.smeweb-modal__aside {
	margin: 1.25rem 0 0;
	padding-top: 1.25rem;
	font-size: var(--wp--preset--font-size--x-small);
	border-top: 1px solid var(--wp--preset--color--outline);
}

/*
 * Three classes deep on purpose.
 *
 * .smeweb-account-body button[type="submit"] forces a filled blue pill with !important on four
 * properties, and it outranks two classes — so the remove-picture control, which is a submit and
 * has to read as a quiet link, needs a longer selector to win rather than a later one.
 */
.smeweb-account-body .smeweb-modal__aside .smeweb-modal__link {
	min-height: 0 !important;
	padding: 0 !important;
	font-family: inherit !important;
	font-size: inherit !important;
	font-weight: 400 !important;
	color: #6E6E85 !important;
	background-color: transparent !important;
	border: 0 !important;
	border-radius: 0 !important;
	text-decoration: underline;
	cursor: pointer;
}

.smeweb-account-body .smeweb-modal__aside .smeweb-modal__link--danger {
	color: #C4241A !important;
}

.smeweb-account-body .smeweb-modal__aside .smeweb-modal__link:hover {
	text-decoration: none;
}

/*
 * ------------------------------------------------------------------ *
 * ประวัติการสั่งซื้อ — Dashboard-6-v2
 * ------------------------------------------------------------------ *
 *
 * Six columns in the same card the domain table uses, so the two tabs share their rules and
 * only the widths differ. The frame drew a seventh, แบบภาษี ณ ที่จ่าย; the team has dropped it.
 *
 * The domain table's widths are reset rather than reused: three columns can be given fractions
 * of the card, six cannot. Measured off the frame the columns come to 227, 166, 243, 83, 110 and
 * 152 of a 1138 content width — and the 83 the frame gives รวม is a header's width, not a
 * total's; the mock has no rows in it. So the table sizes itself to its content, the numbers and
 * dates are held on one line, and a floor keeps the six from crushing.
 *
 * The scroll is on a wrapper rather than the table, because overflow on a table element is not
 * something browsers agree about.
 */
.smeweb-ord__scroll {
	overflow-x: auto;
}

.smeweb-ord {
	/*
	 * 40rem, down from 46. The floor is there so six columns of Thai labels do not crush into
	 * each other before the wrapper starts scrolling; one column fewer needs less of it.
	 */
	min-width: 40rem;
	table-layout: auto;
}

.smeweb-ord th,
.smeweb-ord td {
	width: auto;
	padding-right: 1.25rem;
}

.smeweb-ord__total,
.smeweb-ord td:nth-child(5),
.smeweb-ord td:nth-child(6) {
	white-space: nowrap;
}

/* The frame centres its empty state rather than setting it against the left edge. */
.smeweb-mysite__empty--center {
	margin-bottom: 0;
	text-align: center;
}

/*
 * The three tabs still being designed hold two lines on the same card as the rest, and a card
 * with no columns in it should not carry the two-column grid the site block declares.
 */
.smeweb-mysite__card--soon {
	display: block;
}

.smeweb-mysite__card--soon .smeweb-mysite__lede {
	margin: 0 0 0.75rem;
}

@container mysite (min-width: 601px) {
	.smeweb-mysite__shot {
		max-width: 355px;
	}
}

/*
 * 389 x 238 in the frame, which is 1.634 — the ratio every screenshot in the template library
 * already has, so a shot taken the same way crops to nothing here.
 */
.smeweb-mysite__shot-img {
	display: block;
	width: 100%;
	aspect-ratio: 389 / 238;
	object-fit: cover;
	border-radius: 8px;
	margin-bottom: 0.3125rem;
}

.smeweb-mysite__shot-none {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 389 / 238;
	margin-bottom: 0.3125rem;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
	background-color: var(--wp--preset--color--surface);
	border-radius: 8px;
}

/* The capsule the frame puts under the shot: white, a light hairline, a full-width pill. */
/*
 * Two lines is possible at the narrowest the card gets, so the label is centred and its lines
 * are tightened rather than left at the paragraph leading a wrapped button inherits.
 */
.smeweb-mysite__wp {
	text-align: center;
	line-height: 1.3;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.625rem;
	padding: 0.5rem 1.25rem;
	font-size: 1rem;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	background-color: var(--wp--preset--color--base);
	border: 1px solid #dedede;
	border-radius: 999px;
	transition: border-color 0.18s ease;
}

.smeweb-mysite__wp:hover,
.smeweb-mysite__wp:focus-visible {
	border-color: var(--wp--preset--color--primary);
}

.smeweb-mysite__wp img {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
}

/*
 * 16px on a 44px line rather than 14px on 23.
 *
 * At 14 it was the smallest thing on the page and under the size at which this font stops
 * stacking Thai marks cleanly, and 23px of height is half of what a finger needs. The height
 * comes from min-height rather than padding so it does not move the link off the button above.
 */
.smeweb-mysite__docs {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	font-size: 1rem;
	color: var(--wp--preset--color--primary);
	text-align: center;
	text-decoration: none;
}

.smeweb-mysite__docs:hover,
.smeweb-mysite__docs:focus-visible {
	text-decoration: underline;
}

/* Right column: the address, then the list. */
.smeweb-mysite__url {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin: 0 0 1.75rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	font-weight: 700;
	overflow-wrap: anywhere;
}

.smeweb-mysite__url a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.smeweb-mysite__url a:hover,
.smeweb-mysite__url a:focus-visible {
	text-decoration: underline;
}

.smeweb-mysite__share {
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
}

/*
 * A definition list because that is what it is, laid out as rows rather than with the browser's
 * indent. Grid, not flex, so every label column is the width of the frame's 139px instead of
 * each row finding its own.
 */
.smeweb-mysite__rows {
	display: grid;
	gap: 0.375rem;
	margin: 0;
}

.smeweb-mysite__row {
	display: grid;
	grid-template-columns: 139px minmax(0, 1fr);
	gap: 1.25rem;
	align-items: center;
	min-height: 31px;
	font-size: 1rem;
}

/*
 * #6E6E85 rather than the #848484 this started with, which measured 3.74:1 on white against
 * the 4.5 a 16px label needs. This is the grey the sidebar already uses for its inactive rows,
 * so it is one value fewer in the palette as well as a legible one.
 */
.smeweb-mysite__row dt {
	font-weight: 500;
	color: #6E6E85;
}

/*
 * anywhere, because these values are addresses. havenflora.co.th has nothing a browser will
 * break on, so in a narrow column it ran straight through the card's edge.
 */
.smeweb-mysite__row dd {
	margin: 0;
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	overflow-wrap: anywhere;
}

/* The package, and the build stage, on the frame's capsule. */
.smeweb-mysite__pill {
	display: inline-block;
	white-space: nowrap;
	padding: 0.25rem 0.75rem;
	font-size: 1rem;
	font-weight: 500;
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
	border-radius: 46px;
}

/*
 * The status, in green, once the site is up.
 *
 * The frame's own green is #61ba11, read off a full-resolution export of node 5519:5883. That
 * value measures 2.46:1 on white — a lime that reads as a highlight rather than as text, and
 * this is text. #3F7D0A is the same hue carried down until it clears 4.5, measured 5.06:1, so
 * the row still reads green rather than turning into the conventional dark green a palette
 * would have offered.
 */
.smeweb-mysite__ok {
	color: #3F7D0A !important;
	font-weight: 600;
}

/*
 * The expiry warning takes the logout button's red rather than the theme's accent, which is
 * #FF0000 and measured 3.9:1 on a pale ground. #C4241A is the value that fixed that label and
 * clears 4.5 here.
 */
.smeweb-mysite__near {
	color: #C4241A !important;
}

.smeweb-mysite__warn {
	font-weight: 600;
}

.smeweb-mysite__empty {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.7;
	color: var(--wp--preset--color--muted);
}

.smeweb-mysite__card--help,
.smeweb-mysite__card--empty {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.25rem;
	flex-wrap: wrap;
	padding: 1.25rem 1.5rem;
	background-color: var(--wp--preset--color--surface);
	border-color: transparent;
}

.smeweb-mysite__card--help p {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
}

.smeweb-mysite__btn {
	flex: 0 0 auto;
	padding: 0.55rem 1.3rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	color: var(--wp--preset--color--primary);
	text-decoration: none;
	background-color: var(--wp--preset--color--base);
	border-radius: 999px;
	box-shadow: inset 0 0 0 2px var(--wp--preset--color--primary);
	transition: color 0.18s ease, background-color 0.18s ease;
}

.smeweb-mysite__btn--primary {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
}

.smeweb-mysite__btn:hover,
.smeweb-mysite__btn:focus-visible {
	color: var(--wp--preset--color--base);
	background-color: var(--wp--preset--color--primary);
}

/*
 * The two columns stack when the panel itself is under 680, whatever the window is doing.
 *
 * 600, rebased. The number was 860 while the card was 1230 wide; the card is 780 now, so that
 * threshold sat above the card at every desktop width and the two columns never drew — measured
 * at 1920, the screenshot filled 730 of a 732 content width and pushed the facts a screen down.
 *
 * At 780 the two columns give the screenshot 218 and the facts 444, which is the frame's own
 * proportion at this measure. Under 600 there is not enough for both and it stacks.
 */
@container mysite (max-width: 600px) {
	.smeweb-mysite__card--site {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.75rem;
		/* The padding is set after the flat rule below, where nothing can override it again. */
	}

	.smeweb-mysite__url {
		font-size: 1.125rem;
	}
}

/*
 * Label above value once they cannot sit side by side: 139 of label and 20 of gap leave 181
 * for the value, and the longest of them needs more than that. Under this the dates were
 * breaking onto three lines and the status capsule into a three-line blue block.
 */
@container mysite (max-width: 340px) {
	.smeweb-mysite__row {
		grid-template-columns: minmax(0, 1fr);
		gap: 0.15rem;
		align-items: start;
	}

	.smeweb-mysite__card--help,
	.smeweb-mysite__card--empty {
		align-items: flex-start;
		flex-direction: column;
	}
}

/*
 * ------------------------------------------------------------------ *
 * The plugin's own tabs, in the เว็บไซต์ของฉัน vocabulary
 * ------------------------------------------------------------------ *
 *
 * แดชบอร์ด, ประวัติการซื้อ and โปรไฟล์ cannot be taken over the way เว็บไซต์ของฉัน was — their
 * slugs are in the plugin's reserved list and addCustomerDashboardEndpoint() throws on them. So
 * they keep the plugin's markup and get the card language put over the top of it, which is the
 * next best thing and means one set of numbers for all four tabs.
 *
 * The numbers are the ones .smeweb-mysite already uses: a 1px outline hairline at 12px radius,
 * 1.25rem by 1.5rem of padding, the display font at 1rem/600 for the panel heading. Grouped
 * with the mysite selectors wherever the treatment is identical, so the four tabs cannot drift
 * apart by someone editing one of them.
 */

/*
 * One panel heading across all four tabs. The plugin sets h4 16/600 on two of them and h3 15/600
 * on the profile, which read as two different levels of the same thing.
 *
 * !important on the size only, and for the same reason the bridge rules above carry it: the
 * plugin's own selector beats two classes, and measured without it the headings stayed at 16 and
 * 15. The other declarations land without it because the bridge already forces the family, the
 * weight and the colour on every heading in here.
 */
.smeweb-account-body .fct-customer-dashboard-title,
.smeweb-account-body .fct-customer-dashboard-user-profile .form-heading {
	margin: 0 0 1.25rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem !important;
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--wp--preset--color--contrast);
}

/*
 * The profile's heading is h3.form-heading, not .fct-customer-dashboard-title — an unprefixed
 * class inside a .form-left wrapper, which is why the selector above needed a second half. It
 * is scoped to the profile container rather than left as a bare .form-heading, because a class
 * that generic could belong to anything a future add-on drops into this page.
 */

/*
 * The blocks that should read as cards: the orders table, the empty state and the profile form.
 *
 * The table already had the border and radius from the section above; it is repeated here so
 * the three are one rule and one place to change.
 */
.smeweb-account-body .fct-customer-dashboard-table,
.smeweb-account-body .fct-customer-dashboard-empty-state,
.smeweb-account-body .fct-form-container {
	box-sizing: border-box;
	padding: 1.25rem 1.5rem;
	border: 1px solid var(--wp--preset--color--outline);
	border-radius: 12px;
}

/*
 * The empty state keeps its own generous padding — it centres an icon, a heading and a button in
 * the middle of the panel, and 1.25rem would crowd all three.
 */
.smeweb-account-body .fct-customer-dashboard-empty-state {
	padding: 2.5rem 1.5rem;
}

/*
 * Element Plus rounds the table's bottom corners to 8px inside a 12px wrapper, which shows as a
 * double curve along the foot. Matching it to the wrapper less its 1px border is the only number
 * that lines up.
 *
 * The two bottom corners need naming separately: the shorthand set all four and the computed
 * value came back 11px 11px 8px 8px, so the plugin sets those two with a longhand of its own
 * that a shorthand cannot outrank.
 */
.smeweb-account-body .fct-customer-dashboard-table .el-table {
	border-radius: 11px;
	border-bottom-right-radius: 11px !important;
	border-bottom-left-radius: 11px !important;
}

/*
 * The profile form stops being a right-hand column.
 *
 * Measured, .fct-form-container is 888 wide and .fct-compact-form 488, and the plugin puts the
 * heading and its description in the space to the left — so the fields sat against the right
 * edge with about 600px of white between them and the words that introduce them. Stacked, they
 * read in the order they are meant to be read in, and the form takes a measure rather than the
 * whole panel because a name field 888px wide is not a name field.
 */
.smeweb-account-body .fct-customer-dashboard-user-profile .fct-form-container {
	display: block;
}

.smeweb-account-body .fct-compact-form {
	width: 100%;
	max-width: 34rem;
	margin-inline: 0;
}

/*
 * ------------------------------------------------------------------ *
 * The sidebar and the panel as two cards, Dashboard-1
 * ------------------------------------------------------------------ *
 *
 * The frame gives each of them a white fill, a 20px radius and a 1px stroke that is a gradient
 * running blue at the top to red at the bottom. Sampled down the sidebar's left edge in the
 * frame render: #A39CE2 near the top, #8351AB, #B94A7B, then #F0414C near the foot — blue
 * through violet and magenta into red, vertically. Those readings are the 1px stroke blended
 * with the white behind it, so the stops themselves are the theme's own blue-red preset; only
 * the angle differs from the pill and the buy button, which run it at 115deg.
 *
 * The gradient is painted as two backgrounds rather than with border-image: white clipped to the
 * padding box over the gradient clipped to the border box. border-image cannot do a radius, and
 * these corners are 20px.
 *
 * The container between them is stripped back to a row with a gap, and its own border came off
 * in an earlier round for the same nested-frame reason.
 */
.smeweb-account-body .fct-customer-root-container .fct-customer-dashboard-app-container {
	display: flex;
	gap: 29px;
	align-items: stretch;
	background: none;
}

/*
 * Above 1200 the two cards are within a couple of pixels of each other — 527 and 525 at a 1440
 * window — and stretching them to a shared height is what the frame draws. Below it the panel
 * goes to one column and grows: at 1024 it is 879 tall against a sidebar holding 390 of rows,
 * and stretch turned the rest into 450px of empty card with the logout stranded at the foot of
 * it. Off the cross axis the sidebar is only as tall as what is in it.
 */
@media (max-width: 1199px) {
	.smeweb-account-body .fct-customer-root-container .fct-customer-dashboard-app-container {
		align-items: flex-start;
	}
}

/*
 * Neither of these is a card any more.
 *
 * Dashboard-1 gave the sidebar and the panel a 1px blue-to-red stroke at a 20px radius each.
 * In v2 the sidebar is a tinted band with no border at all and the panel is not drawn — the one
 * card left on the screen is the block inside the panel, and it takes that stroke instead.
 */

/*
 * The sidebar, and the reason its width cannot be one number.
 *
 * Under 807px the plugin turns .fct-customer-dashboard-app-container into a column and swaps
 * the six rows for a hamburger and an absolutely positioned dropdown. In a column, flex-basis
 * is the height — so the 381 that was the frame's width became 381px of empty card with a
 * 36px button in the corner of it. Measured: with the basis at auto the same box is 54 tall,
 * which is the bar's real height. So the number belongs inside a min-width query, and the
 * default here is what the collapsed bar wants.
 */
.smeweb-account-body .fct-customer-dashboard-navs-wrap {
	flex: 0 0 auto;
	max-width: none;
	border-right-width: 1px !important;
	border-right-color: transparent !important;
	padding: 0.5rem 0;
}

/*
 * The sidebar above 807, and why it is positioned rather than laid out.
 *
 * In every v2 frame it starts immediately under the header and runs to the footer — 57px above
 * the heading block, which in this markup is a sibling printed before the plugin's app. Nothing
 * in flow inside that app can reach above it, so the sidebar is taken out and pinned to the
 * section, which the page group already establishes as a containing block.
 *
 * .fct-customer-root-container sits between the two and the plugin gives it position: relative,
 * which would catch the inset first; it goes static for that reason. The drawer the plugin opens
 * below 807 is absolute inside the bar rather than inside this, so nothing it positions depends
 * on it.
 *
 * 807 is measured rather than round: the plugin's own flip sits between 806, where its container
 * is a column, and 808, where it is a row.
 *
 * The width and height it had before are both gone — flex sizing does nothing to a positioned
 * box, and the max-width: 381px that came with it would have capped the frame's 390.
 *
 * #f9f9ff is sampled down the frame at ten heights and flat all the way. Not the theme's surface,
 * which is #f7f4fd and reads lilac, and not base white, which would leave the sidebar no edge at
 * all now the page behind it is white too.
 */
@media (min-width: 807px) {
	/*
	 * !important because the plugin's own stylesheet is printed after this one and sets
	 * position: relative here. Measured without it: the container stayed relative and caught
	 * the sidebar's inset, which put the sidebar at the container's left edge and gave it the
	 * height of the content rather than of the band.
	 */
	.smeweb-account-body .fct-customer-root-container {
		position: static !important;
	}

	/*
	 * The sidebar stays put while the column beside it scrolls.
	 *
	 * fixed rather than sticky, and the reason is where the two boxes sit. The sidebar is the
	 * plugin's, inside .smeweb-account-body; the page heading is ours, in a block above that. A
	 * sticky sidebar has to be in normal flow, which would drop it below the heading and turn a
	 * full-height left column into a panel starting halfway down. fixed keeps the composition
	 * exactly as it is and gives the same behaviour, because with the footer off this page the
	 * band is the last thing on it — there is nothing below for a sticky box to stop against.
	 *
	 * Top is the header's own height: the header is sticky at 0 with z-index 100, so it stays
	 * above this and the sidebar starts where the header ends.
	 */
	.smeweb-account-body .fct-customer-dashboard-navs-wrap {
		position: fixed;
		top: var(--smeweb-account-rail-top);
		left: 0;
		z-index: 1;
		display: flex;
		flex-direction: column;
		width: var(--smeweb-rail);
		max-width: none;
		height: calc(100vh - var(--smeweb-account-rail-top));
		overflow-y: auto;
		/*
		 * 40 above and below, down from the frame's 71.
		 *
		 * 71 was measured off node 5519:5517, where the sidebar began at the top of the page. It
		 * begins under a 72px header now that it is pinned, so that inset was being paid twice —
		 * the avatar sat 142 below the top of the window with nothing in between. 30 either side
		 * is the frame's and stays.
		 */
		padding: 40px 30px;
		background: #f9f9ff;
		border: 0 !important;
		border-radius: 0;
	}

	/*
	 * The plugin insets its menu 20px from the sidebar's own padding, which left the rows 220
	 * wide inside a 320 sidebar — 69% of the column they navigate. Zeroing that inset gives them
	 * the sidebar's full 260 without touching the ground behind them, which stays 320.
	 */
	/*
	 * The plugin's own inset, which was being paid on top of ours in both directions.
	 *
	 * 20 all round: sideways it left the rows 220 wide inside a 320 sidebar — 69% of the column
	 * they navigate — and vertically it added to the 48 below the name block and the 40 under the
	 * logout, so the measured gaps were 68 and 90 while the stylesheet said 48 and 40. Zeroing it
	 * gives the rows the sidebar's full 260 and leaves the spacing to the rules that name it.
	 */
	.smeweb-account-body #fct-customer-menu-container {
		padding: 0;
	}

	/*
	 * The logout sits at the foot of the band, and it has to get there by layout.
	 *
	 * The frame puts it at y718 of a 767 inner column, which is 215 below the last menu row. The
	 * plugin pushes it down by a fixed distance instead, and measured that came to 332 — so the
	 * sidebar's content ran 1024 inside a band of 908 and the row was cut in half by the bottom
	 * edge. A distance cannot be right at more than one height; margin-top: auto is right at
	 * every one, and it keeps the 70 of padding under it.
	 *
	 * The two boxes are the plugin's and neither carries a class, so they are addressed by
	 * position: the wrap's last child holds the menu and the logout, and that box's last child
	 * is the logout.
	 */
	.smeweb-account-body .fct-customer-dashboard-navs-wrap > div:last-child {
		display: flex;
		flex-direction: column;
		flex: 1 1 auto;
		min-height: 0;
		height: auto;
	}

	.smeweb-account-body .fct-customer-dashboard-navs-wrap > div:last-child > div:last-child {
		margin-top: auto;
	}

	/*
	 * The column clears the sidebar: 390 + 150 puts its left edge at the frame's 540, and 1920
	 * less 150 puts the right at 1770. The panel's own half of this is set further down, after
	 * the flat rule that would otherwise override it.
	 */
	.smeweb-account-head,
	.smeweb-account-body .smeweb-mysite {
		max-width: calc(var(--smeweb-account-measure) + var(--smeweb-account-inset) * 2);
		margin-inline: auto;
		padding-inline: var(--smeweb-account-inset);
	}
}

/* Below 807 the plugin stacks its own column, and the sidebar is a bar with its own ground. */
@media (max-width: 806px) {
	.smeweb-account-body .fct-customer-dashboard-navs-wrap {
		padding: 0.25rem;
		background: #f9f9ff;
		border: 0 !important;
		border-radius: 12px;
	}
}

/*
 * The panel carries the column's inset and nothing else.
 *
 * Written here rather than in the min-width block further up, and this is the whole reason: a
 * media query carries no specificity, so the flat rule that used to sit at this point in the
 * file was overriding it. Measured before the move — the panel kept the old 42px inset and the
 * column never reached the frame's 540.
 */
.smeweb-account-body .fct-customer-dashboard-main-content {
	flex: 1 1 auto;
	min-width: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
}

@media (min-width: 807px) {
	/*
	 * The sidebar is positioned, so it takes no width in the row and everything in the column
	 * would start at the window's edge. One padding on the wrapper clears it, and then the
	 * heading block and the card each centre their own measure inside what is left — which is
	 * how the reference does it, and it keeps the two on the same centre line at every width.
	 */
	.smeweb-account-card {
		padding-left: var(--smeweb-rail);
	}
}

/*
 * Below the flip the sidebar is a bar above the content and there is no column to clear, so the
 * inset goes back to --smeweb-shell-inset: the number the footer and every other band on the
 * site use, which on a 430 screen is 37 rather than the 150 this column wants at 1920.
 */
@media (max-width: 806px) {
	.smeweb-account-body .fct-customer-dashboard-main-content,
	.smeweb-account-head {
		padding-inline: var(--smeweb-shell-inset);
	}
}

/*
 * The card, which is the only one on the screen now.
 *
 * The stroke is .smeweb-gradient-border's, shared with the blog's Trending card: a 2px ring at
 * 115deg from accent to primary, drawn as a masked pseudo-element on a 22px corner. What is left
 * here is undoing the base card's own edge — .smeweb-mysite__card sets a 1px grey border and a
 * 12px radius further up, and both are written after the shared rule, so both have to be said
 * again to lose.
 *
 * The frame drew this at 12px with a 1px 180deg stroke of its own. Matching Trending was the
 * later instruction and it wins; the two cards are the same object at two sizes.
 *
 * The columns are the frame's 355 and 422 with 70 between them, as a proportion so both give
 * way together when the card narrows; the screenshot keeps 355 as a ceiling. The frame leaves
 * 291 of slack at the card's right edge and that is not reproduced — a label-and-value list
 * left-aligned in a wider track looks the same, and the slack read as an unfinished edge.
 */
.smeweb-mysite__card--site {
	border: 0;
	border-radius: 22px;
}

/*
 * The two columns, and the screenshot's ceiling, only while the card is wide enough for them.
 *
 * Stated as a min-width container query rather than as a flat rule, and this is the third time
 * the same trap has been walked into here: a container query carries no specificity of its own,
 * so a flat rule written after it wins on file order. Measured with the columns flat — the card
 * was 584 wide at a 1024 window, the max-width: 860 query below was matching, and the tracks
 * stayed at 33 and 67 anyway, which drew the screenshot 153 wide.
 */
@container mysite (min-width: 601px) {
	.smeweb-mysite__card--site {
		/*
		 * 38 against 62, not the frames' 33 against 67.
		 *
		 * The button under the screenshot carries จัดการเว็บไซต์ด้วยตนเอง, which at 16px beside
		 * its 24px mark needs about 254 including its own padding. 33% of a 780 card is 222 and
		 * the label broke onto two lines; 38% is 260 and it holds. The facts keep 400, and the
		 * widest pair in them — a 139 label, 20 of gap and a date at about 150 — needs 309.
		 */
		grid-template-columns: minmax(0, 38fr) minmax(0, 62fr);
		gap: clamp(1.25rem, 5.7%, 70px);
	}
}

/*
 * The card's inset, both sizes stated together and placed after every rule that touches it.
 *
 * 32 all round on a card at its measure, in a variable because the rows inside reach back out
 * to the card's edge with it. The frame's 46 and 42 were drawn for a 1230 card; on a 780 one
 * they are a twelfth of the width, and the reference insets its rows about 32 from a 770 card.
 *
 * Written as two container queries rather than a flat rule and an override, for the fourth time
 * in this stylesheet and for the same reason each time: a container query carries no specificity
 * of its own, so a flat rule after it wins on file order. Measured with the flat rule in place —
 * a 356px card on a phone kept the full 32 and the query below it did nothing.
 */
@container mysite (min-width: 601px) {
	.smeweb-mysite__card--site {
		--smeweb-card-pad: 2rem;
		padding: var(--smeweb-card-pad);
	}
}

@container mysite (max-width: 600px) {
	.smeweb-mysite__card--site {
		--smeweb-card-pad: 1.5rem;
		padding: 1.75rem var(--smeweb-card-pad);
	}
}

/*
 * ------------------------------------------------------------------ *
 * The sidebar rows, Dashboard-1
 * ------------------------------------------------------------------ *
 *
 * Off the frame: rows 310 wide at 14 by 10 of padding with 16 between icon and label, icons 28,
 * labels 18px, and the row you are on filled solid brand blue with white text rather than tinted.
 * The avatar block above shows the display name at 18 with the address under it, and the logout
 * at the foot is red text beside a 28px glyph with no fill behind it.
 *
 * These override the mapping set through the plugin's --fct-customer-dashboard-* variables. Those
 * were the right tool while the sidebar was a tinted column inside a white card; the frame wants
 * a filled pill, and no variable in that set paints one.
 */
/*
 * The label is the navigation's own size, asked for by name.
 *
 * Measured on the live header: the menu links are 17.6px at a 1920 window and 16.5 at a 900
 * one, which is the small preset — 1.1rem with a fluid floor of 0.9375rem. The rows were a
 * flat 1.125rem, so they read 0.4px larger at the top of the range and stayed put as the
 * navigation shrank. Using the token rather than 1.1rem keeps the two in step if the preset
 * ever moves.
 *
 * One thing this gives up: at the bottom of the fluid range the label is 15px, and this font
 * stacks ั over ่ into a single blob under about 19px — ประวัติการสั่งซื้อ has that pair. It
 * was already inside that range at 1.125rem, so nothing new breaks, but matching the
 * navigation and clearing the marks are two different numbers and this row picks the first.
 */
.smeweb-account-body .fct-customer-nav-link {
	gap: 1rem;
	/* 11 and 14, off the frame: the icon sits at y11 x14 inside a 49-tall row. */
	padding: 0.6875rem 0.875rem;
	font-size: var(--wp--preset--font-size--small);
	border-radius: 8px;

	/* 49, which is the frame: 28 of icon inside 11 and 11 of padding, plus the border box. */
	min-height: 49px;
}

/* Sizing lives in the svg rule further down, which carries the !important it needs. */

/*
 * The filled row.
 *
 * Set through the plugin's variables rather than by a selector of ours, because the variables are
 * the published way in and they reach the row's text as well as its fill.
 *
 * An earlier note here said the plugin marks the row with a background rather than a class and
 * that no selector could find it. That was wrong: the parent li carries active_customer_menu, and
 * each item carries fct-customer-nav-item-<slug>. The icon rule above uses the first of those.
 */
.smeweb-account-body .fct-customer-root-container {
	--fct-customer-dashboard-nav-active-bg-color: var(--wp--preset--color--primary);
	--fct-customer-dashboard-nav-active-text-color: var(--wp--preset--color--base);
	--fct-customer-dashboard-nav-active-bar-color: transparent;
}

/* The active marker bar goes: the frame fills the row instead of ruling beside it. */
.smeweb-account-body .fct-customer-nav-link-active-bar,
.smeweb-account-body .fct-customer-dashboard-navs-wrap [class*="active-bar"] {
	display: none !important;
}

/*
 * Logout: red on nothing.
 *
 * The plugin gives it #F04438 on a #FCEBE6 pill. The frame has plain red text on the card, so the
 * fill comes off — and with the fill gone the contrast question the pink raised goes with it:
 * measured, #C4241A on white is 6.4:1 against the 3.25:1 it had on that pink.
 */
.smeweb-account-body .fct-customer-logout-btn {
	gap: 1rem;
	justify-content: flex-start;
	padding: 0.625rem 0.875rem;
	/* The same token as the six rows above it, which is the navigation's. */
	font-size: var(--wp--preset--font-size--small);
	color: #C4241A;
	background-color: transparent !important;
	/*
	 * 8px, the same corner as the six rows above it.
	 *
	 * The 10px that was here never applied, and an earlier note blamed the plugin for that.
	 * Read off the cascade instead, the 999px was ours: the dashboard pill rule above reaches
	 * this row through a[class*="btn"], which outranks a two-class selector. It is excluded
	 * there now, so this is the only radius on the row.
	 */
	border-radius: 8px !important;
}

.smeweb-account-body .fct-customer-logout-btn:hover,
.smeweb-account-body .fct-customer-logout-btn:focus-visible {
	background-color: #FCEBE6 !important;
}

/*
 * The logout glyph, drawn rather than exported.
 *
 * The plugin ships its own inline SVG for this row — a solid box with a notch cut for the
 * arrow — and the frame has the outline the other six rows use: a bracket open on its right
 * with the arrow leaving through the opening. This is that shape at the same 1.8 stroke.
 *
 * It arrives as a mask rather than as markup, because the row is the plugin's and there is no
 * filter for its icon. A mask takes its colour from background-color, so currentColor keeps
 * the glyph on the row's own colour the way the other six manage through fill.
 */
.smeweb-account-body .fct-customer-logout-btn svg,
.smeweb-account-body .fct-customer-logout-btn img {
	display: none;
}

.smeweb-account-body .fct-customer-logout-btn::before {
	content: "";
	flex: 0 0 auto;
	/*
	 * A 28 box holding a 24 glyph, which is what the six rows above do — their span is 28 and
	 * their svg is 24. The box is what sets the gap to the label, so it stays 28 and only the
	 * mask comes down.
	 */
	width: 28px;
	height: 28px;
	background-color: currentColor;
	-webkit-mask: url("assets/img/icon-nav-logout.svg") center / 24px 24px no-repeat;
	mask: url("assets/img/icon-nav-logout.svg") center / 24px 24px no-repeat;
}

/*
 * The head of the sidebar, off node 5519:4093: a 330x129 block with a 72px avatar centred over
 * the name and the address, all three centred, and no rule under it.
 *
 * Dashboard-1 had a 40px avatar beside the two lines with a hairline below; v2 stacks and
 * centres them. display is set explicitly because the plugin lays this out as a row and
 * flex-direction alone would do nothing to a block.
 *
 * The 48 below is the frame's gap to the first menu row — 177 less the block's own 129.
 */
/*
 * Above 807 only. Below it the plugin hides this block and shows a hamburger instead, and a
 * display of ours here would override that display: none — measured, the collapsed bar came out
 * 232 tall on a 430 screen with the avatar and both lines back inside it.
 */
@media (min-width: 807px) {
	.smeweb-account-body .fct-customer-dashboard-customer-info {
		display: flex;
		flex-direction: column;
		align-items: center;
		/* 12 under the avatar rather than 8: the two lines below it are larger now. */
		gap: 12px;
		/*
		 * 36 to the first menu row, where the rule used to say 48.
		 *
		 * It measured 68, because the plugin's menu container added 20 of its own on top. With
		 * that zeroed above, this number is the gap — and 36 is what the block needs now that it
		 * is taller.
		 */
		margin-bottom: 36px;
		padding-top: 0;
		padding-bottom: 0;
		text-align: center;
		border-bottom: 0 !important;
	}

	/*
	 * The name and the address, which the plugin stacks with no gap at all.
	 *
	 * Measured, both lines sat in 16px line boxes touching each other — a 18px name in a 16px
	 * box. A flex column carries the gap so neither line-height has to fight the plugin's, which
	 * is set with enough weight to win against a plain rule here.
	 */
	.smeweb-account-body .fct-customer-dashboard-customer-info-content {
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 6px;
		max-width: 100%;
	}

	.smeweb-account-body .fct-customer-dashboard-customer-info img {
		width: 72px !important;
		height: 72px !important;
		max-width: none !important;
		border-radius: 999px;
		object-fit: cover;
	}
}

/*
 * h3 stays in the selector alongside our own class: the tag is rewritten in PHP on the way out of
 * the plugin's template, and if a plugin update changes that markup the rewrite finds nothing and
 * the h3 comes back. Matching both means the row keeps its size either way.
 */
.smeweb-account-body .fct-customer-dashboard-customer-info h3,
.smeweb-account-body .fct-customer-dashboard-customer-info .smeweb-account-whoami,
.smeweb-account-body .fct-customer-dashboard-customer-info [class*="heading"] {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	/* 20, up from 18. */
	font-size: 1.25rem !important;
	/*
	 * !important on the line-height as well as the size.
	 *
	 * The plugin sets 16px here — under the font size, so the box was shorter than its own text.
	 * The size carried an !important already and the line-height did not, and measured, the
	 * plugin's 16 was still winning.
	 */
	line-height: 1.35 !important;
	/*
	 * The page's darkest ink rather than pure black, which is the colour every other heading on
	 * the site uses. It was #6e6e85, the muted grey the address below it wears — so the name and
	 * the address read as the same rank, and the name is the one you look for.
	 */
	color: var(--wp--preset--color--contrast) !important;
}

/*
 * The address under the name.
 *
 * last-child rather than a class, because it has none — and it is the last line whether the name
 * above it is our <p> or the plugin's <h3> that the PHP rewrite did not reach.
 */
.smeweb-account-body .fct-customer-dashboard-customer-info-content > p:last-child {
	margin: 0;
	/* 15.2, up from 14. */
	font-size: 0.95rem !important;
	line-height: 1.45 !important;
	color: #6E6E85 !important;
	/* A long address wraps inside the sidebar rather than running out of it. */
	max-width: 100%;
	overflow-wrap: anywhere;
}

/*
 * The icons are inline SVG and every path is fill="currentColor", so each glyph is already the
 * colour of the row it sits in — white on the filled row, near-black on the rest — with no filter
 * and no second copy of the file.
 *
 * The size still needs all four properties and !important. width and height alone were winning
 * the cascade while these were <img> and the glyph still measured 20px: something upstream caps
 * the box rather than sets it, and a capped height drags the width down through the intrinsic
 * ratio. An inline svg meets the same cap.
 *
 * 24 in a 28px slot, not 28.
 *
 * The slot is the frame's 28 and the span below still holds it, so the label and the gap to it do
 * not move. The glyph inside is 24, which is the size these icons drew at for months — while
 * their viewBox was being stripped and each one rendered its raw 24 units anchored top-left. The
 * stripping is fixed and the centring came with it; the size was a separate dial and 28 was too
 * heavy beside a 17.6px label. This is the old size, centred.
 */
.smeweb-account-body .fct-customer-nav-link svg {
	width: 24px !important;
	height: 24px !important;
	max-width: none !important;
	max-height: none !important;
	flex: 0 0 auto;
}

/*
 * Nothing holds the glyph's colour, and that is the point.
 *
 * Every path in these files is fill="currentColor", so the icon is whatever colour the row is:
 * Ink beside the label, white when the row fills — and the row fills on hover as well as on
 * the page you are on, which is where the white comes from without a rule of its own.
 *
 * A rule did stand here setting the svg to the muted grey so the glyph stayed lighter than
 * its label. It also survived the hover, leaving a grey icon on solid brand blue.
 */

/*
 * The rows sit 6px apart, which is the frame's gap.
 *
 * This is what read as ชืด. Each row is 48 tall — 28 of icon inside 10 and 10 of padding — so six
 * of them and their gaps come to 318, and the plugin was spreading the same six down most of a
 * 598px card, leaving every row floating in its own empty band. The items are targeted rather
 * than their list, because the list's own class is not one the plugin documents.
 */
/*
 * The icon's own box, which was four pixels short of its icon.
 *
 * The plugin wraps each glyph in a 20x20 span and the rule below forces the svg to 28 — so the
 * svg hung 4px out of the bottom of its span. Both spans are centred against each other by the
 * row's align-items, which means the row was centring a 20px box while a 28px icon was drawn
 * from that box's top edge: measured, the icon's centre sat 4px below the label's. Giving the
 * span the icon's size puts the two centres on the same line, and centring inside it keeps them
 * there if the svg size ever changes.
 */
.smeweb-account-body .fct-customer-nav-link-icon {
	display: flex;
	flex: 0 0 28px;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
}

/* The label is the rest of the row, and it stays on one line. */
.smeweb-account-body .fct-customer-nav-link-text {
	display: flex;
	align-items: center;
	min-width: 0;
}

/* 8 between rows, up from 6: at 49 tall and 260 wide, 6 read as a stack rather than a list. */
.smeweb-account-body .fct-customer-nav-item + .fct-customer-nav-item {
	margin-top: 8px;
}

.smeweb-account-body .fct-customer-nav-item {
	margin-bottom: 0;
}

/*
 * ------------------------------------------------------------------ *
 * The two things the plugin puts in the card that the frame does not
 * ------------------------------------------------------------------ *
 *
 * What stood here was 90 lines for .smeweb-account-support, the section that came out of
 * page-account.php, and none of it was reaching the page: a comment opener sat unclosed above
 * the first rule and ran on to the end of the block, taking @media (max-width: 880px) with
 * it. Nothing was lost along with the section, but that media query also held the account
 * card's own padding, so that had been dead for as long as the comment was.
 */

/*
 * The collapse toggle goes.
 *
 * It is the plugin's, it renders as a bare |← floating on the seam between the two cards, and
 * what it collapses is a sidebar the frame draws at a fixed width. Below 807 the plugin
 * already hides this one and puts its own button in the bar instead, so this is safe to take
 * out at every width.
 */
.smeweb-account-body .fct-nav-compact-toggle-wrap {
	display: none !important;
}

/*
 * The collapsed bar, under 807.
 *
 * The plugin leaves a 36px hamburger alone in the card with nothing beside it, which on a
 * phone reads as a panel that failed to load rather than as a menu. The label is set here
 * because the markup is the plugin's; it is written in escapes rather than as Thai text
 * because this stylesheet declares no charset and nothing else in it depends on one.
 *
 * The bar is the wrap's last child and the dropdown is the only div inside it — neither
 * carries a class. If a plugin update renames them this quietly stops applying, which is the
 * right way for it to fail.
 */
@media (max-width: 806px) {
	.smeweb-account-body .fct-customer-dashboard-navs-wrap > div:last-child {
		display: flex;
		align-items: center;
		gap: 0.75rem;
		padding: 0.25rem;
	}

	/* The plugin draws it 36 square, which is under the 44 a finger needs. */
	.smeweb-account-body .fct-customer-dashboard-navs-wrap > div:last-child > button {
		min-width: 44px;
		min-height: 44px;
	}

	/* เมนูบัญชี */
	.smeweb-account-body .fct-customer-dashboard-navs-wrap > div:last-child::after {
		content: "\000E40\000E21\000E19\000E39\000E1A\000E31\000E0D\000E0A\000E35";
		font-size: 1.125rem;
		font-weight: 500;
		color: var(--wp--preset--color--contrast);
	}

	/*
	 * The dropdown opens 210 wide, which is narrower than these labels: measured, the six rows
	 * came out 48, 60, 60, 48, 60, 48 tall because three of them wrapped onto a second line.
	 * 320 holds the longest on one line, and the calc keeps it on the screen at 360.
	 */
	.smeweb-account-body .fct-customer-dashboard-navs-wrap > div:last-child > div {
		min-width: min(320px, calc(100vw - 5rem));
	}
}

/*
 * Breadcrumbs over an article.
 *
 * They sit under the title band rather than inside it, above the picture and against the left
 * edge of the column — a path is a line you read from its start, and centring it made it read
 * as a caption for the headline instead. Asked for that way, with the house.
 *
 * The gap between crumbs is 10px, not the 4px it started at. The separator carries spaces of
 * its own inside " › ", so 4px of flex gap on top of them still read as one run of text —
 * measured 4px between every pair of boxes. 10px is where the chevrons start to separate the
 * steps rather than sit inside them, and the row still fits on one line at 1440.
 *
 * Rank Math prints nav.rank-math-breadcrumb wrapping a single <p>, with .separator between
 * the links and .last on the current page. Its own module was off; turning it on is what also
 * gives the page a BreadcrumbList in the schema graph, which it did not have.
 *
 * The trail is หน้าแรก › บล็อก › category › title, and the title alone is 69 characters —
 * 101 for the row, which is two lines in a 720px hero. So the last crumb is capped and
 * ellipsised rather than allowed to wrap: a breadcrumb that wraps stops reading as one path.
 * The h1 directly below says the whole title anyway, so nothing is lost by trimming it here.
 *
 * min-width: 0 on the flex item because an ellipsis cannot happen inside a flex child that is
 * still allowed to grow to its content — the usual reason text-overflow looks ignored.
 */
.smeweb-crumbs {
	margin-bottom: var(--wp--preset--spacing--30);
}

.smeweb-crumbs .rank-math-breadcrumb p {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: flex-start;
	gap: 0.625rem;
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
}

.smeweb-crumbs .rank-math-breadcrumb a {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	white-space: nowrap;
}

/*
 * A house before the first crumb.
 *
 * Drawn with a mask rather than as a background image, so the shape takes currentColor and
 * turns with the link on hover and on focus without a second copy of the file. An <img> could
 * not do that, and an inline SVG would mean filtering the plugin's output.
 *
 * Sized in em so it tracks the crumb text, which is x-small on desktop and smaller again on a
 * phone. The -0.12em nudge sits it on the text baseline; without it the roof rides high.
 */
.smeweb-crumbs .rank-math-breadcrumb a:first-child::before {
	content: "";
	display: inline-block;
	width: 1.05em;
	height: 1.05em;
	margin-right: 0.35em;
	vertical-align: -0.12em;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3.2 2.4 11.6h2.7V20h5.1v-5.6h3.6V20h5.1v-8.4h2.7L12 3.2z' fill='%23000'/%3E%3C/svg%3E") no-repeat center / contain;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3.2 2.4 11.6h2.7V20h5.1v-5.6h3.6V20h5.1v-8.4h2.7L12 3.2z' fill='%23000'/%3E%3C/svg%3E") no-repeat center / contain;
}

.smeweb-crumbs .rank-math-breadcrumb a:hover,
.smeweb-crumbs .rank-math-breadcrumb a:focus-visible {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
}

.smeweb-crumbs .rank-math-breadcrumb .separator {
	color: var(--wp--preset--color--outline);
	flex: none;
}

.smeweb-crumbs .rank-math-breadcrumb .last {
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	color: var(--wp--preset--color--contrast);
}

/*
 * On a phone the path matters more than where it ends, so the title drops out entirely.
 *
 * The separator before it has to go with it, and :last-of-type does not find it — .last is a
 * span too, so it is the last span, and .separator:last-of-type matched nothing at all. Left
 * that way the row ended on a dangling ›, which is how it was caught. :has(+ .last) names the
 * one that sits against the title, whatever the trail length turns out to be.
 */
@media (max-width: 600px) {
	.smeweb-crumbs .rank-math-breadcrumb .last,
	.smeweb-crumbs .rank-math-breadcrumb .separator:has(+ .last) {
		display: none;
	}
}

/*
 * สีของ Fluent Cart ทั้งหน้าร้าน
 *
 * Fluent Cart publishes base variables for its storefront and derives the rest from them, each
 * with the value it falls back to spelled out. So this is a mapping onto the theme palette, not
 * a fight with its stylesheet.
 *
 * They go on :root because that is where the plugin computes the derived set —
 * :root{--fct-checkout-border-color: var(--fct-border-color, #D6DAE1); …}. Declared on
 * .fct-checkout instead, as this was at first, the base name is not in scope at :root and every
 * derived value quietly takes its fallback: the inputs stayed #d6dae1 and the order button
 * stayed slate, with nothing in the CSS looking wrong.
 *
 * --fct-primary-bg-color is the one that shows: default #253241, and it drives the order button
 * and the selected payment radio. A dark slate button on a checkout is the plugin introducing
 * itself; brand blue is the site asking for the sale.
 *
 * Left alone: the summary card, the address modal and the payment panels, which the plugin
 * hard-codes to #ffffff. White is already right and restating it gains nothing.
 */
:root {
	--fct-primary-bg-color: var(--wp--preset--color--primary);
	--fct-primary-text-color: var(--wp--preset--color--contrast);
	--fct-btn-bg-color: var(--wp--preset--color--primary);
	--fct-btn-text-color: var(--wp--preset--color--base);
	--fct-btn-border-color: var(--wp--preset--color--primary);
	--fct-border-color: var(--wp--preset--color--outline);
	--fct-active-border-color: var(--wp--preset--color--primary);
	--fct-input-text-color: var(--wp--preset--color--contrast);
	--fct-input-placeholder-text-color: var(--wp--preset--color--muted);
	--fct-secondary-bg-color: var(--wp--preset--color--surface);
	--fct-secondary-text-color: var(--wp--preset--color--muted);
}

.fct-checkout {
	font-family: var(--wp--preset--font-family--body);
}

/*
 * คู่มือการใช้งาน
 *
 * The index is one card per docs category with its articles listed inside. It borrows the
 * blog card's shell through smeweb-blog-grid — the band width, the column steps, the 6px
 * corners and the soft shadow — so a card here is the same object as a card on the blog, and
 * only what is different about it is written below.
 *
 * Two columns rather than four: a category card holds a list, not a headline, so it needs the
 * width. The grid steps to one column below 782, where two lists side by side stop being
 * scannable.
 */
.smeweb-docs-grid {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 782px) {
	.smeweb-docs-grid {
		grid-template-columns: 1fr;
	}
}

.smeweb-docs-card {
	padding: var(--wp--preset--spacing--40);
	border-radius: 6px;
	box-shadow: 0 2px 12px rgba(20, 20, 43, 0.07);
	transition: box-shadow 0.2s ease;
}

.smeweb-docs-card:hover {
	box-shadow: 0 12px 28px rgba(20, 20, 43, 0.12);
}

/* The count sits on the title line, pushed to the far edge. */
.smeweb-docs-card__title {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--20);
	margin: 0 0 var(--wp--preset--spacing--30);
	padding-bottom: var(--wp--preset--spacing--20);
	border-bottom: 1px solid var(--wp--preset--color--outline);
}

.smeweb-docs-card__title a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.smeweb-docs-card__title a:hover,
.smeweb-docs-card__title a:focus-visible {
	color: var(--wp--preset--color--primary);
}

.smeweb-docs-card__count {
	flex: none;
	min-width: 1.75rem;
	padding: 0.1rem 0.45rem;
	border-radius: 999px;
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	text-align: center;
}

/*
 * The article list carries no bullets: every line is a link, and a bullet beside a link reads
 * as decoration rather than as structure. The left border does the job a bullet would.
 */
.smeweb-docs-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.smeweb-docs-list li + li {
	margin-top: 0.15rem;
}

.smeweb-docs-list a {
	display: block;
	padding: 0.4rem 0 0.4rem 0.85rem;
	border-left: 2px solid var(--wp--preset--color--outline);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	transition: border-color 0.15s ease, color 0.15s ease;
}

.smeweb-docs-list a:hover,
.smeweb-docs-list a:focus-visible {
	border-left-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary);
}

/* A term page shows one card holding the whole list, so it takes the band rather than half of it. */
.smeweb-docs-card--single {
	max-width: 720px;
	margin-inline: auto;
}

.smeweb-docs-back a {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

.smeweb-docs-back a:hover,
.smeweb-docs-back a:focus-visible {
	text-decoration: underline;
}

/* The category line over a doc title, in the same red the blog uses over an article title. */
.smeweb-docs-index + .smeweb-blog-grid,
.wp-block-post-terms a[href*="doc_category"] {
	color: inherit;
}

/* ---------------------------------------------------------------------------
 * The demo-subdomain field at checkout.
 *
 * Drawn to the reference the client supplied: one rounded box holding a globe, the input, and a
 * fixed .smeweb.site suffix sitting behind a divider on the right. The suffix is a sibling of the
 * input rather than text inside it, so it cannot be edited, selected with the value, or wiped by
 * the plugin's Javascript when it repaints the field.
 *
 * Colours come from the theme presets, not the reference's hexes, so the field matches the rest
 * of the checkout rather than importing a second blue.
 * ------------------------------------------------------------------------ */
.smeweb-sub {
	margin-block: 28px 4px;
}

.smeweb-sub__label {
	margin: 0 0 10px;
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

.smeweb-sub__star {
	color: #d63638;
}

/* The box. Grid rather than flex so the suffix keeps its width and the input takes the rest. */
.smeweb-sub__wrap {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 10px;
	padding: 0 0 0 16px;
	border: 1px solid #d8d8e3;
	border-radius: 12px;
	background: #fff;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.smeweb-sub__wrap:focus-within {
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px rgba(31, 42, 205, 0.12);
}

.smeweb-sub__wrap.is-ok {
	border-color: #1a7f37;
}

.smeweb-sub__wrap.is-bad {
	border-color: #d63638;
}

.smeweb-sub__icon {
	display: flex;
	width: 22px;
	height: 22px;
	color: var(--wp--preset--color--primary);
}

.smeweb-sub__icon svg {
	width: 100%;
	height: 100%;
}

/* !important throughout: the plugin's stylesheet prints after this one and styles its own
   .fct_input_wrapper input with a border, padding and a background of its own. */
.smeweb-sub__input {
	width: 100%;
	min-width: 0;
	padding: 14px 0 !important;
	border: 0 !important;
	border-radius: 0 !important;
	background: transparent !important;
	box-shadow: none !important;
	font-size: 1rem;
	color: var(--wp--preset--color--contrast);
}

.smeweb-sub__input:focus {
	outline: 0;
	box-shadow: none !important;
}

.smeweb-sub__suffix {
	align-self: stretch;
	display: flex;
	align-items: center;
	padding: 0 20px;
	border-left: 1px solid #e6e6ef;
	font-size: 1rem;
	font-weight: 600;
	color: var(--wp--preset--color--primary);
	white-space: nowrap;
	user-select: none;
}

.smeweb-sub__hint,
.smeweb-sub__msg,
.smeweb-sub__note {
	margin: 8px 0 0;
	font-size: 0.85rem;
	line-height: 1.5;
}

.smeweb-sub__hint {
	color: #6e6e85;
}

.smeweb-sub__hint b {
	color: var(--wp--preset--color--primary);
	font-weight: 600;
}

/* The verdict line. Empty until there is something to say, and it keeps no height when empty so
   nothing shifts as the customer types. */
.smeweb-sub__msg:empty {
	display: none;
}

.smeweb-sub__wrap.is-ok ~ .smeweb-sub__msg {
	color: #1a7f37;
}

.smeweb-sub__wrap.is-bad ~ .smeweb-sub__msg {
	color: #d63638;
}

.smeweb-sub__wrap.is-busy ~ .smeweb-sub__msg {
	color: #6e6e85;
}

.smeweb-sub__note {
	color: #6e6e85;
}

/* On a phone the suffix would leave the input a few characters wide, so it moves under it. */
@media (max-width: 480px) {
	.smeweb-sub__wrap {
		grid-template-columns: auto 1fr;
		padding: 0 14px;
	}

	.smeweb-sub__suffix {
		grid-column: 1 / -1;
		padding: 0 0 12px;
		border-left: 0;
		font-size: 0.9rem;
	}
}

/* ---------------------------------------------------------------------------
 * การสมัครใช้บริการ — FluentCart's own subscriptions list, dressed as Dashboard-2-v2.
 *
 * The content is the plugin's and stays the plugin's; nothing here adds or removes a fact. What
 * changes is the shape. FluentCart renders the same subscriptions twice — an Element Plus table
 * for wide screens and a list of per-subscription cards for narrow ones — and the frame draws
 * rows, not a table: a brand box, a two-line block, and the amount off to the right. So the card
 * list is shown at every width and the table is put away, which is a swap of two display values
 * rather than an attempt to bend a table framework into a row layout it does not have.
 *
 * !important on the swap because the plugin's stylesheet prints after this one and sets both
 * values in a flat rule, then again inside @media (max-width: 575px). Media queries carry no
 * specificity, so nothing but !important wins from here.
 * ------------------------------------------------------------------------ */
.smeweb-account-body .subscription-only-desktop {
	display: none !important;
}

.smeweb-account-body .subscription-only-mobile {
	display: block !important;
}

/* The card. Radius, padding and the gradient ring come from the shared rule above; the 1px
   outline the panel gives every .fct-customer-dashboard-table has to go, or it draws a second
   line just inside the gradient. */
.smeweb-account-body .fct-customer-dashboard-subscriptions-inner {
	padding: 30px 32px;
	overflow: visible;
}

/* The table wrapper stops being a card of its own: the card is the panel around it now. */
.smeweb-account-body .fct-customer-dashboard-subscriptions .fct-customer-dashboard-table {
	padding: 0;
	border: 0;
	border-radius: 0;
	overflow: visible;
}

/*
 * The section heading, which the frame sets as a bold line with a grey explanation under it.
 *
 * The plugin's own <h4> is restyled rather than hidden and replaced. Hiding it would leave the
 * list with no heading of its own, and generated content is not a heading — a screen reader
 * reading this page should still find "แผนการสมัครสมาชิก" as a real element under the page title.
 */
.smeweb-account-body .fct-customer-dashboard-subscriptions .fct-customer-dashboard-header {
	display: block;
	margin-bottom: 22px;
}

.smeweb-account-body .fct-customer-dashboard-subscriptions .fct-customer-dashboard-title {
	margin: 0;
	font-size: 1.25rem !important;
	font-weight: 700 !important;
	line-height: 1.4 !important;
	color: var(--wp--preset--color--contrast) !important;
}

.smeweb-account-body .fct-customer-dashboard-subscriptions .fct-customer-dashboard-header::after {
	content: "แพ็กเกจที่คุณใช้งานอยู่ และรอบการต่ออายุ";
	display: block;
	margin-top: 4px;
	font-size: 0.9rem;
	line-height: 1.5;
	color: #6e6e85;
}

/*
 * A row per subscription.
 *
 * The plugin stacks three blocks — header (card and renewal date), body (the plan name), footer
 * (status and amount) — in that order, which is a phone layout. Named grid areas put the plan
 * name above its own details on the left and lift the amount to the right, without needing the
 * markup to change: only .item-body, .item-header and .item-footer are placed, and each is a
 * direct child, so nothing has to reach into a grandchild.
 */
.smeweb-account-body .subscription-only-mobile-item {
	display: grid !important;
	grid-template-columns: 1fr auto;
	grid-template-areas:
		"body   footer"
		"header footer";
	align-items: center;
	column-gap: 24px;
	row-gap: 4px;
	padding: 20px 0;
	border-bottom: 1px solid #e9e9f2;
}

.smeweb-account-body .subscription-only-mobile-item:first-child {
	padding-top: 0;
}

.smeweb-account-body .subscription-only-mobile-item:last-child {
	padding-bottom: 0;
	border-bottom: 0;
}

.smeweb-account-body .subscription-only-mobile-item .item-body {
	grid-area: body;
	min-width: 0;
}

.smeweb-account-body .subscription-only-mobile-item .item-header {
	grid-area: header;
	display: flex;
	flex-wrap: wrap;
	align-items: center;

	/*
	 * flex-start, said out loud. The plugin lays this header out as space-between so the card
	 * sits at one end of a phone-width card and the renewal date at the other; in a row that is
	 * now over a thousand pixels wide that threw the date across to the far right, where it read
	 * as part of the amount. Measured before the fix: the date ended at x=1221 with the amount
	 * starting at 1245.
	 */
	justify-content: flex-start;
	gap: 6px 14px;
	min-width: 0;
}

.smeweb-account-body .subscription-only-mobile-item .item-footer {
	grid-area: footer;
	display: flex;
	align-items: center;
	justify-content: flex-end;
}

/* The plan name is the row's title, so it carries the weight the frame gives it. */
.smeweb-account-body .subscription-only-mobile-item .fct-customer-orders-items-title {
	font-size: 1.05rem !important;
	font-weight: 600 !important;
	line-height: 1.45 !important;
	color: var(--wp--preset--color--contrast) !important;
}

/* The card and the renewal date read as one quiet line under the name. */
.smeweb-account-body .subscription-only-mobile-item .item-header .text,
.smeweb-account-body .subscription-only-mobile-item .item-header .fct-card-info .text {
	font-size: 0.875rem !important;
	line-height: 1.5 !important;
	color: #6e6e85 !important;
}

/* The brand mark sits in a bordered well, as it does in the frame. */
.smeweb-account-body .subscription-only-mobile-item .fct-card-info {
	display: flex;
	align-items: center;
	gap: 8px;
}

.smeweb-account-body .subscription-only-mobile-item .fct-card-info img {
	box-sizing: content-box;
	width: 26px;
	height: 18px;
	padding: 5px 7px;
	border: 1px solid #e2e2ec;
	border-radius: 6px;
	background: #fff;
	object-fit: contain;
}

/* Amount and status, stacked and right-aligned against the row's right edge. */
.smeweb-account-body .subscription-only-mobile-item .item-footer-content {
	display: flex !important;
	flex-direction: column;
	align-items: flex-end;
	gap: 8px;
}

.smeweb-account-body .subscription-only-mobile-item .fct-customer-payment-info {
	font-size: 0.95rem !important;
	font-weight: 600 !important;
	line-height: 1.4 !important;
	color: var(--wp--preset--color--contrast) !important;
	text-align: right;
	white-space: nowrap;
}

/* The status pill takes the capsule shape the rest of the account area uses. */
.smeweb-account-body .subscription-only-mobile-item .fct-badge {
	border-radius: 999px;
	padding: 3px 12px;
	font-size: 0.8rem;
	font-weight: 600;
}

/* The pager is a footnote to the list, not a second block: no card of its own. */
.smeweb-account-body .fct-customer-dashboard-subscriptions .pagination-wrap {
	margin-top: 0;
	padding-top: 18px;
	border-top: 1px solid #e9e9f2;
}

.smeweb-account-body .fct-customer-dashboard-subscriptions .pagination-wrap .text {
	font-size: 0.85rem;
	color: #6e6e85;
}

/*
 * On a phone the amount cannot share a line with the name — 17,013.00฿ ต่อ ปี จนกว่าจะยกเลิก is
 * wider than the column it would be left with — so the row goes back to being stacked, which is
 * the layout the plugin wrote these cards for in the first place.
 */
@media (max-width: 640px) {
	.smeweb-account-body .subscription-only-mobile-item {
		grid-template-columns: 1fr;
		grid-template-areas:
			"body"
			"header"
			"footer";
		align-items: start;
		row-gap: 8px;
	}

	.smeweb-account-body .subscription-only-mobile-item .item-footer {
		justify-content: flex-start;
	}

	.smeweb-account-body .subscription-only-mobile-item .item-footer-content {
		flex-direction: row;
		align-items: center;
		gap: 12px;
	}

	.smeweb-account-body .subscription-only-mobile-item .fct-customer-payment-info {
		white-space: normal;
		text-align: left;
	}

	.smeweb-account-body .fct-customer-dashboard-subscriptions-inner {
		padding: 22px 18px;
	}
}
