/*
 * Duck Mark chrome extras.
 *
 * The utility bar, the edge rail, the phone tab bar and the newsletter. These sit
 * outside the header, the footer and the page composition, so they get their own
 * stylesheet and it is loaded only when at least one of them is switched on.
 *
 * Colours come from the shared tokens, so every pack recolours them without a
 * line of pack specific CSS.
 */

.dm-ic {
	width: 1.15em;
	height: 1.15em;
	flex: 0 0 auto;
}

/* ---------------------------------------------------------------- utility bar */

.dm-ubar {
	background: var(--dm-accent-2, #7b5cff);
	color: #fff;
	font-size: clamp(11px, 1.05vw, 13px);
}

.dm-ubar .dm-ubar__list {
	list-style: none;
	margin: 0 auto;
	padding: .55em var(--dm-shell-gutter, 20px);
	width: min(100%, var(--dm-shell-container, 1120px));
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: .4em 1.6em;
}

.dm-ubar .dm-ubar__item {
	margin: 0;
	padding: 0;
	display: flex;
	align-items: center;
	gap: .5em;
	font-weight: 800;
	letter-spacing: .08em;
	text-transform: uppercase;
	white-space: nowrap;
}

/* A divider between statements, never before the first one. */
.dm-ubar .dm-ubar__item + .dm-ubar__item::before {
	content: "";
	width: 1px;
	height: 1.1em;
	margin-right: 1.1em;
	background: currentColor;
	opacity: .4;
}

.dm-ubar__link {
	display: flex;
	align-items: center;
	gap: .5em;
	color: inherit;
	text-decoration: none;
}

.dm-ubar__link:hover { text-decoration: underline; text-underline-offset: 3px; }

/* --- the plain pattern drops the icons and the dividers --- */
.dm-ubar--plain .dm-ic { display: none; }
.dm-ubar--plain .dm-ubar__item + .dm-ubar__item::before { display: none; }

/* --- the ticker keeps everything on one line and slides it --- */
.dm-ubar--ticker .dm-ubar__list {
	flex-wrap: nowrap;
	overflow: hidden;
	justify-content: flex-start;
}

.dm-ubar--ticker .dm-ubar__item { animation: dm-ubar-slide 26s linear infinite; }

@keyframes dm-ubar-slide {
	from { transform: translateX(0); }
	to { transform: translateX(-100%); }
}

/* ---------------------------------------------------------------- edge rail */

/*
 * Decoration down the side of the screen. It carries no information that is not
 * elsewhere on the page, which is why the markup marks it as decorative, and it
 * disappears whenever the screen is too narrow to spare the room.
 */
.dm-rail {
	position: fixed;
	top: 50%;
	z-index: 40;
	display: flex;
	flex-direction: column;
	gap: 1.6em;
	transform: translateY(-50%);
	pointer-events: none;
}

.dm-rail--left { left: max(8px, calc((100% - var(--dm-shell-container, 1120px)) / 2 - 64px)); }
.dm-rail--right { right: max(8px, calc((100% - var(--dm-shell-container, 1120px)) / 2 - 64px)); }

.dm-rail__badge {
	display: grid;
	justify-items: center;
	gap: .3em;
	max-width: 4.5em;
	color: var(--dm-text, #16160f);
	font-size: 10px;
	font-weight: 800;
	letter-spacing: .1em;
	line-height: 1.2;
	text-align: center;
	text-transform: uppercase;
	opacity: .72;
}

.dm-rail__badge .dm-ic { width: 1.7em; height: 1.7em; }

@media (max-width: 1400px) {
	.dm-rail { display: none; }
}

/* ---------------------------------------------------------------- tab bar */

.dm-tabbar { display: none; }

@media (max-width: 782px) {
	.dm-tabbar {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 60;
		display: grid;
		grid-auto-flow: column;
		grid-auto-columns: 1fr;
		background: var(--dm-bg, #16160f);
		border-top: 2px solid var(--dm-border, rgba(0, 0, 0, .2));
		/* Clear of the home indicator on a phone that has one. */
		padding-bottom: env(safe-area-inset-bottom, 0);
	}

	.dm-tabbar__tab {
		display: grid;
		justify-items: center;
		align-content: center;
		gap: .25em;
		min-height: 56px;
		padding: .4em .2em;
		/* Derived from the contracted pair rather than from a second token, so a
		   pack that never declared `--dm-muted` cannot fall through to a default
		   grey meant for a white ground: on the two dark packs that is 4.10:1 and
		   4.18:1, which would have traded one contrast fault for another. Mixing
		   the pack's own ink toward the pack's own ground is 5.77:1 at worst
		   across all nine. The plain declaration above it is what a browser
		   without `color-mix` keeps. */
		color: var(--dm-text, #f4f1e8);
		color: color-mix(in srgb, var(--dm-text, #f4f1e8) 68%, var(--dm-bg, #16160f));
		font-size: 10px;
		font-weight: 800;
		letter-spacing: .06em;
		text-transform: uppercase;
		text-decoration: none;
	}

	.dm-tabbar__tab .dm-ic { width: 1.5em; height: 1.5em; }

	/* The label is 10px/800 uppercase, which is not large text, so it owes 4.5:1.
	   `--dm-accent` cannot pay that on a light pack: on the active one it is the
	   pack's pink on the pack's white ground at 2.15:1, and the current tab —
	   the one the shopper is looking for — was the only unreadable one.

	   It was never one pack's bug. Measured across all nine: `--dm-accent` as a
	   label fails on four of them — kitsch 1.36:1, fruity 2.15:1, neutral 2.84:1,
	   luxe-modern 3.06:1 — and only passes on the packs whose accent happens to be
	   near-black or near-white. A colour chosen to be loud is the wrong place to
	   put a contrast obligation.

	   So the accent keeps the job it can do at any contrast — a 2px indicator that
	   is never the only cue — and both labels are carried by the pair every pack
	   contrast-checks against the ground it sits on. Current is that ink at full
	   strength (16.66:1 on the active pack, 16.19:1 at worst across the nine); the
	   weight step and the indicator carry the current/not-current distinction. */
	.dm-tabbar__tab.is-current {
		color: var(--dm-text, #f4f1e8);
		font-weight: 900;
		box-shadow: inset 0 2px 0 0 var(--dm-accent, #8ee63f);
	}

	/* Same reason the label moved: a focus ring owes 3:1 against what it sits on,
	   and the accent was under it at 2.15:1. */
	.dm-tabbar__tab:focus-visible {
		outline: 2px solid var(--dm-text, #f4f1e8);
		outline-offset: -2px;
	}

	/* Room at the bottom so the bar never sits on top of the last thing. The bar
	   is its `min-height` plus the home-indicator inset, so the room owes both —
	   reserving the 56px alone left the inset's worth of the last element under
	   the bar on any phone that has one. */
	body.dm-has-tabbar { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); }
}

/* The product page can pin its own purchase bar to the bottom from 760px down, at
   a z-index three orders above this one — the tab bar would be painted and then
   covered whole, on the one screen where a shopper needs the buy button and the
   way out of the page at the same time. The purchase bar keeps the bottom edge,
   because the CTA must not move relative to the thumb; the tab bar is what
   yields, and the page reserves room for the pair.

   **Both rules key off the bar itself, not off the setting that asks for one.**
   `dm-spc-sticky-purchase` on `body` only means the setting is on. Measured on
   this site: the setting is on, the class is present, and `.dm-spc-sticky` is
   emitted **zero** times — its renderer runs on `wp_footer` and gives up when it
   cannot resolve a product there. Keying the reserved room off the class alone
   held 64px of empty space under every product page for a bar that never
   arrived. `:has()` asks the only question that matters — is the bar here — so
   the room appears if the renderer is ever fixed and costs nothing until then.

   Scoped to 760px to match the breakpoint that reveals the purchase bar: between
   761 and 782 the tab bar is alone. */
@media (max-width: 760px) {
	body.dm-has-tabbar .dm-spc-sticky {
		bottom: calc(56px + env(safe-area-inset-bottom, 0px));
	}

	body.dm-has-tabbar:has(.dm-spc-sticky) {
		padding-bottom: calc(56px + 64px + env(safe-area-inset-bottom, 0px));
	}
}

/* ---------------------------------------------------------------- newsletter */

.dm-news {
	background: var(--dm-surface, #ece5d8);
	color: var(--dm-text, #16160f);
}

.dm-news__inner {
	width: min(100% - (var(--dm-shell-gutter, 20px) * 2), var(--dm-shell-container, 1120px));
	margin-inline: auto;
	padding-block: clamp(24px, 3.5vw, 48px);
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 1.2em 2em;
}

.dm-news--stacked .dm-news__inner {
	flex-direction: column;
	align-items: flex-start;
}

.dm-news__title {
	margin: 0;
	font-family: var(--dm-font-display, inherit);
	font-weight: var(--dm-display-weight, 900);
	font-size: clamp(19px, 2.2vw, 30px);
	letter-spacing: .02em;
	text-transform: uppercase;
	color: inherit;
}

.dm-news__text {
	margin: .35em 0 0;
	font-size: clamp(12px, 1.2vw, 14px);
	opacity: .78;
}

.dm-news__form {
	display: flex;
	flex: 1 1 320px;
	max-width: 460px;
	gap: 0;
}

.dm-news__field {
	flex: 1;
	min-width: 0;
	padding: .8em 1em;
	background: #fff;
	color: var(--dm-text, #16160f);
	border: 2px solid currentColor;
	border-radius: var(--dm-radius-sm, 0);
	font-size: 14px;
}

.dm-news__button {
	flex: 0 0 auto;
	padding: .8em 1.4em;
	background: var(--dm-primary, #16160f);
	color: var(--dm-on-primary, #ece5d8);
	border: 2px solid var(--dm-primary, #16160f);
	border-radius: var(--dm-btn-radius, 0);
	font-weight: 900;
	letter-spacing: .08em;
	text-transform: uppercase;
	cursor: pointer;
}

.dm-news__button:hover,
.dm-news__button:focus-visible {
	background: var(--dm-accent, #8ee63f);
	border-color: var(--dm-accent, #8ee63f);
	color: var(--dm-text, #16160f);
}

@media (max-width: 782px) {
	.dm-news__inner { flex-direction: column; align-items: stretch; }
	.dm-news__form { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
	.dm-ubar--ticker .dm-ubar__item { animation: none; }
}
