/*
 * SMYN — the service menu.
 *
 * Not a design system. The site already has one, and every value below comes
 * from it: the treatment pages' price list (.smyn-b30-prices), their FAQ
 * accordion (.smyn-b30-acc), the treatments hub's category selector
 * (.smyn-b37-tab). Where a number here looks arbitrary it is quoted from one of
 * those, and the comment says which.
 *
 * Two faces, as everywhere else on the site: Glacial Indifference for the
 * things a visitor reads — names, prices, headings — and Jost for the things
 * they scan: labels, durations, controls. Setting the tracked uppercase labels
 * in Glacial was the single biggest reason the old version read as a plugin.
 */

.smyn-catalogue {
	--cat-ink: var(--smyn-ink, #1A1714);
	--cat-cream: var(--smyn-cream, #FDFAF7);
	--cat-accent: var(--smyn-terracotta, #822E27);
	--cat-accent-hover: var(--smyn-terracotta-hover, #93382F);
	--cat-muted: var(--smyn-muted, #74615A);
	--cat-mocha: var(--smyn-mocha, #7A6358);
	--cat-line: var(--smyn-line, #D5C9B8);
	--cat-champagne: var(--smyn-champagne, #D8CCB8);
	--cat-wash: var(--smyn-hover-surface, #F1E9DC);

	/* The site's serif-less pairing. Both faces are self-hosted by the theme. */
	/* The theme's Brand Book tokens, with a literal behind each so the
	   catalogue still sets type correctly if the plugin is ever used under a
	   different theme. Glacial Indifference has no pound sign, so Jost stays
	   directly behind it in the display stack — that is what renders the £. */
	--cat-display: var(--smyn-font-display, "Glacial Indifference", Jost, sans-serif);
	--cat-label: var(--smyn-font-label, "Glacial Indifference", Jost, sans-serif);

	/* .smyn-b30-acc-head uses this curve and .3s; so does .smyn-b37-tab. */
	--cat-ease: cubic-bezier(.22, .61, .36, 1);

	/* Wide enough to sit flush with the sections above and below at every size
	   the site is used at; a ceiling only so a 2560px monitor does not stretch
	   one row of type across a metre of glass. */
	max-width: 1560px;
	margin-inline: auto;
	color: var(--cat-ink);
	font-family: var(--cat-display);
	container-type: inline-size;
}

.smyn-catalogue *,
.smyn-catalogue *::before,
.smyn-catalogue *::after {
	box-sizing: border-box;
}

/* Defined here rather than assumed: the module must not depend on the theme
   having its own .screen-reader-text. */
.smyn-catalogue .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.smyn-catalogue :focus-visible {
	/* .smyn-b30-acc-head:focus-visible, verbatim. */
	outline: 2px solid var(--cat-accent);
	outline-offset: 3px;
}

/* ── category navigation ─────────────────────────────────────────────────
   .smyn-b37-tab is the treatments hub's selector: square, tracked uppercase
   Jost, terracotta fill when active. Kept, with the inactive border dropped so
   five categories read as a line of type rather than a row of boxes, and 10px
   raised to 11px because these are controls. */

.smyn-catalogue__nav {
	margin: 0 0 clamp(2.75rem, 5cqi, 4.5rem);
	border-bottom: 1px solid var(--cat-line);
}

.smyn-catalogue__tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 0 clamp(0.25rem, 1.5cqi, 0.75rem);
	margin-bottom: -1px;
}

.smyn-catalogue__tab {
	appearance: none;
	background: none;
	border: 0;
	border-radius: 0;
	padding: 13px 18px;
	font: 700 13px/1 var(--cat-label);
	letter-spacing: 1.8px;
	text-transform: uppercase;
	color: var(--cat-mocha);
	cursor: pointer;
	white-space: nowrap;
}

.smyn-catalogue__tab:hover {
	color: var(--cat-accent);
}

.smyn-catalogue__tab[aria-selected="true"] {
	background: var(--cat-accent);
	color: var(--cat-cream);
}

/* ── the category itself ─────────────────────────────────────────────────
   The eyebrow-above-title composition of "04 · PRICES / Prices." on every
   treatment page. The count lives in the eyebrow slot, where the site puts
   secondary labels, instead of competing with the title from the far right. */

.smyn-catalogue__world + .smyn-catalogue__world {
	margin-top: clamp(4rem, 8cqi, 7rem);
}

.smyn-catalogue__world:focus-visible {
	outline: none; /* Programmatic focus target; the tab shows the state. */
}

.smyn-catalogue__world-head {
	margin-bottom: clamp(2rem, 4cqi, 3.25rem);
}

.smyn-catalogue__eyebrow {
	margin: 0 0 clamp(0.75rem, 1.5cqi, 1.125rem);
	font: 700 13px/1.2 var(--cat-label);
	letter-spacing: 2.4px;
	text-transform: uppercase;
	color: var(--cat-accent);
	font-variant-numeric: tabular-nums;
}

.smyn-catalogue__world-title {
	margin: 0;
	font-family: var(--cat-display);
	font-size: clamp(2.75rem, 8cqi, 5.5rem);
	font-weight:400;
	line-height: 0.92;
	letter-spacing: -0.02em;
	text-wrap: balance;
}

/* The site sets its editorial headings with a full stop — "Prices.",
   "Questions, answered." Punctuation, not data: the term name is untouched. */
.smyn-catalogue__world-title::after {
	content: ".";
}

/* ── chapters ────────────────────────────────────────────────────────────
   Numbered like the treatment pages' "01 Aftercare." rows, so a subgroup reads
   as a chapter rather than a label floating above a list. */

.smyn-catalogue__group + .smyn-catalogue__group {
	margin-top: clamp(2.75rem, 5cqi, 4.25rem);
}

.smyn-catalogue__group-title {
	display: flex;
	align-items: baseline;
	gap: 12px;
	/* No rule of its own: the first row's top hairline is the chapter's rule.
	   Both drew two lines 12px apart, which is the one thing a hairline list
	   must never do. */
	margin: 0 0 0.875rem;
	font: 700 13px/1.2 var(--cat-label);
	letter-spacing: 2.4px;
	text-transform: uppercase;
	color: var(--cat-accent);
}

.smyn-catalogue__group-n {
	font-weight: 700;
	letter-spacing: 1.4px;
	/* Champagne is the site's number colour on INK. On cream it is a ghost —
	   about 1.9:1 — so the mocha is used instead and the number reads as a
	   quiet anchor rather than a smudge. */
	color: var(--cat-mocha);
	font-variant-numeric: tabular-nums;
}

.smyn-catalogue__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

/* ── one treatment ───────────────────────────────────────────────────────
   .smyn-b30-prices .pt-row is "34px minmax(0,1fr) 110px 96px 26px" at
   "padding:16px 0" with a hairline top rule. This is that, with one more cell
   because a catalogue row needs a booking link as well as a price. */

.smyn-service {
	display: grid;
	grid-template-columns: 34px minmax(0, 1fr) 168px 104px auto;
	grid-template-areas: "n name meta price actions";
	align-items: center;
	gap: 0 14px;
	padding: 15px 0;
	border-top: 1px solid var(--cat-line);
}

.smyn-catalogue__list > .smyn-service:last-child {
	border-bottom: 1px solid var(--cat-line);
}

.smyn-service__n {
	grid-area: n;
	align-self: center;
	font: 700 11px/1 var(--cat-label);
	letter-spacing: 0.5px;
	/* See the note on __group-n: champagne on cream is not a colour, it is an
	   absence. Muted, mixed back toward the ground, keeps the number quiet
	   while still landing on 3:1.
	   Expressed as a mix rather than opacity so the computed colour IS the
	   contrast: an opacity on top makes every ratio you measure a lie. The
	   plain declaration below it is the fallback, and it errs darker. */
	color: var(--cat-muted);
	color: color-mix(in srgb, var(--cat-muted) 70%, var(--cat-cream));
	font-variant-numeric: tabular-nums;
}

.smyn-service__name {
	grid-area: name;
	margin: 0;
	font-family: var(--cat-display);
	font-size: clamp(1.0625rem, 1.5cqi, 1.3125rem);
	font-weight:400;
	line-height: 1.3;
	letter-spacing: 0;
	color: var(--cat-ink);
}

.smyn-service__meta {
	grid-area: meta;
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 4px 10px;
	margin: 0;
	font: 400 13px/1.4 var(--cat-label);
	color: var(--cat-muted);
	/* The longest duration in the catalogue is "2 hours 45 mins - 3 hours".
	   Wrapping it made that row taller than its neighbours and broke the
	   baseline the eye tracks down. */
	white-space: nowrap;
}

.smyn-service__badge {
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--cat-accent);
}

.smyn-service__price {
	grid-area: price;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 2px;
	margin: 0;
	text-align: right;
	white-space: nowrap;
}

/* "from" is a label, so it is set like one — and quietly, so the number reads
   first. .smyn-b30-prices .p i does the same at 9px; 11px here because the
   brief rules out functional text that small. */
.smyn-service__from {
	font: 700 13px/1 var(--cat-label);
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--cat-muted);
}

.smyn-service__amount {
	font-family: var(--cat-display);
	font-size: clamp(1.125rem, 1.7cqi, 1.375rem);
	font-style: italic;
	font-weight:400;
	line-height: 1;
	color: var(--cat-accent);
	font-variant-numeric: tabular-nums;
}

/* ── the two actions ─────────────────────────────────────────────────────
   Book carries words, colour and a rule beneath it. Details is one glyph. That
   is the entire hierarchy, and it needs no boxes to say which is primary. */

.smyn-service__actions {
	grid-area: actions;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 4px;
}

.smyn-service__book {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	/* .smyn-b30-related a: tracked uppercase Jost, 1px underline at 4px. */
	font: 700 13px/1.4 var(--cat-label);
	letter-spacing: 0.9px;
	text-transform: uppercase;
	color: var(--cat-accent);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 4px;
	white-space: nowrap;
	padding: 10px 2px;
}

.smyn-service__book:hover,
.smyn-service__book:focus {
	color: var(--cat-accent-hover);
}

.smyn-service__book-mark {
	font-size: 12px;
	line-height: 1;
}

/* .smyn-b30-acc-head .ic, including the 45deg turn that makes a "+" a "×". */
.smyn-service__toggle {
	appearance: none;
	background: none;
	border: 0;
	border-radius: 0;
	cursor: pointer;
	width: 34px;
	height: 34px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	/* A control, so its glyph is held to the 3:1 non-text contrast minimum.
	   Champagne on cream is about 1.9:1 — decorative at best, and this is not
	   decoration. Muted on cream is 5.6:1 and still reads as the quieter of
	   the two actions. */
	color: var(--cat-muted);
}

.smyn-service__toggle-mark {
	display: block;
	font: 400 19px/1 var(--cat-label);
}

.smyn-service__toggle:hover {
	color: var(--cat-accent);
}

.smyn-service__toggle[aria-expanded="true"] {
	color: var(--cat-accent);
}

.smyn-service__toggle[aria-expanded="true"] .smyn-service__toggle-mark {
	transform: rotate(45deg);
}

/* ── what a treatment includes ───────────────────────────────────────────
   A warm wash rather than a box: the site has no rounded cards and no shadow
   anywhere, so a panel here is a change of ground and a rule, nothing more. */

.smyn-service__detail {
	grid-column: 1 / -1;
	margin: 12px 0 4px 34px;
	padding: 16px 22px;
	border-left: 2px solid var(--cat-accent);
	background: var(--cat-wash);
	max-width: 68ch;
}

.smyn-service__detail p {
	margin: 0 0 0.75em;
	font: 400 15px/1.75 var(--cat-label);
	color: var(--cat-mocha);
}

.smyn-service__detail > :last-child {
	margin-bottom: 0;
}

.smyn-service__note {
	color: var(--cat-ink) !important;
}

.smyn-catalogue--empty p {
	margin: 0;
	font: 400 15px/1.75 var(--cat-label);
	color: var(--cat-muted);
}

/* ── tablet ──────────────────────────────────────────────────────────────
   Between about 640px and 900px there is room for one line but not for the
   full desktop grid. Dropping the row number and tightening the two fixed
   columns buys it: 768px was otherwise falling all the way to the phone
   layout and spending its width on nothing. */

@container (min-width: 38rem) and (max-width: 56rem) {
	.smyn-service {
		grid-template-columns: minmax(0, 1fr) 128px 92px auto;
		grid-template-areas: "name meta price actions";
		gap: 0 12px;
	}

	.smyn-service__n {
		display: none;
	}

	.smyn-service__detail {
		margin-left: 0;
	}
}

/* ── narrow ──────────────────────────────────────────────────────────────
   Designed, not stacked. Name and price share the first line so the two things
   a visitor is comparing stay together; duration and the two controls share the
   second. Roughly 76px a row, so 39 treatments is a scroll and not a journey. */

@container (max-width: 38rem) {
	.smyn-service {
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-areas:
			"name  price"
			"meta  actions";
		align-items: start;
		gap: 6px 12px;
		padding: 14px 0;
	}

	.smyn-service__n {
		display: none; /* Row numbers are a desktop grace note, not information. */
	}

	.smyn-service__name {
		font-size: clamp(1.0625rem, 4.4cqi, 1.25rem);
		align-self: center;
	}

	.smyn-service__price {
		align-self: center;
	}

	.smyn-service__meta {
		align-self: center;
	}

	.smyn-service__actions {
		gap: 2px;
	}

	/* A thumb, not a mouse. 44px square is the target size guidance, and the
	   row absorbs it because the name line above is only ~26px tall. */
	.smyn-service__toggle {
		width: 44px;
		height: 44px;
	}

	.smyn-service__book {
		padding: 13px 2px;
	}

	.smyn-service__detail {
		margin-left: 0;
		padding: 14px 16px;
	}

	.smyn-catalogue__nav {
		/* Elegant swipe rather than five cramped labels. */
		overflow-x: auto;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
		/* The last label fading at the edge says "there is more this way"
		   without adding an arrow, a shadow or a scrollbar to the design. */
		mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
		-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
	}

	/* Once the last category is reached there is nothing left to hint at, and
	   a permanent fade over a fully-scrolled row just looks like a bug. */
	.smyn-catalogue__nav[data-scroll-end="true"] {
		mask-image: none;
		-webkit-mask-image: none;
	}

	.smyn-catalogue__nav::-webkit-scrollbar {
		display: none;
	}

	.smyn-catalogue__tabs {
		flex-wrap: nowrap;
		scroll-snap-type: x proximity;
	}

	.smyn-catalogue__tab {
		scroll-snap-align: start;
		padding: 12px 14px;
		letter-spacing: 1.4px; /* .smyn-b37-tab does the same under 767px. */
	}
}

/* Fallback for browsers without container queries: the same break, by
   viewport. The catalogue sits in a full-width section, so the two agree. */
@supports not (container-type: inline-size) {
	@media (max-width: 38rem) {
		.smyn-service {
			grid-template-columns: minmax(0, 1fr) auto;
			grid-template-areas:
				"name  price"
				"meta  actions";
			align-items: center;
			gap: 6px 12px;
		}

		.smyn-service__n {
			display: none;
		}

		.smyn-service__detail {
			margin-left: 0;
		}

		.smyn-catalogue__tabs {
			flex-wrap: nowrap;
			overflow-x: auto;
		}
	}
}

/* ── motion, only where it is welcome ────────────────────────────────────
   .3s on the same curve as the accordion icon and the hub tabs. */

@media (prefers-reduced-motion: no-preference) {
	.smyn-catalogue__tab,
	.smyn-service__book,
	.smyn-service__toggle {
		transition: color .3s var(--cat-ease), background-color .3s var(--cat-ease);
	}

	.smyn-service__toggle-mark {
		transition: transform .3s var(--cat-ease);
	}

	.smyn-service__detail {
		animation: smyn-catalogue-reveal .28s var(--cat-ease) both;
	}

	@keyframes smyn-catalogue-reveal {
		from {
			opacity: 0;
			transform: translateY(-4px);
		}
		to {
			opacity: 1;
			transform: none;
		}
	}
}

/* ── print ───────────────────────────────────────────────────────────────
   A printed menu is one continuous list: no tabs, no hidden worlds, no
   controls, and every description on the page. */

@media print {
	.smyn-catalogue__nav,
	.smyn-service__actions {
		display: none !important;
	}

	.smyn-catalogue__world[hidden],
	.smyn-service__detail[hidden] {
		display: block !important;
	}

	.smyn-service {
		break-inside: avoid;
	}

	.smyn-service__detail {
		background: none;
		border-left-color: var(--cat-line);
	}
}

/* ==================================================================
   No JavaScript — the whole menu, not one category
   ==================================================================
   The server now ships the catalogue in its final state: the first world open,
   the other six carrying `hidden`, every description collapsed, the tab bar
   and the disclosure buttons live. With JavaScript that is what the browser
   paints first and there is nothing left to shift — the catalogue's 0.0837 CLS
   on a phone came entirely from JS doing this collapse after the first paint.

   Without JavaScript that same markup would strand a visitor on Nails with a
   tab bar that does nothing. So when scripting is off, everything reopens and
   the controls that would not work are taken away. `scripting: none` is a
   Media Queries Level 5 feature (Chrome 120+, Safari 17+, Firefox 113+); on an
   older browser without it, JavaScript is essentially always available and the
   default state above is the correct one.

   This lives in the stylesheet rather than in a <noscript><style> or an inline
   <script> because the catalogue gate asserts, deliberately, that the shortcode
   emits neither.
   ================================================================== */
@media (scripting: none) {
	/* Every category open and reachable — the complete price list. */
	.smyn-catalogue__world[hidden] {
		display: block !important;
	}
	/* Every description open, since nothing can expand one. */
	.smyn-service__detail[hidden] {
		display: block !important;
	}
	/* And no controls that cannot work. */
	.smyn-catalogue__nav,
	.smyn-service__toggle {
		display: none !important;
	}
}
