/*
Theme Name:   Divas Luxe
Theme URI:    https://divas-escort.com/
Description:  Luxury black / gold / teal child theme for Astra. Bespoke design system with animated cards, scroll-reveal sections, gradient gold typography and high-class editorial polish. Built for divas-escort.com.
Author:       Divas Escort
Author URI:   https://divas-escort.com/
Template:     astra
Version:      1.0.0
License:      GNU General Public License v2 or later
License URI:  http://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  divas-luxe
Tags:         luxury, dark, gold, editorial, blog
*/

/* ==========================================================================
   1. DESIGN TOKENS
   ========================================================================== */
:root {
	/* base — layered blacks give depth without looking flat */
	--dl-black:        #08080a;
	--dl-surface:      #0e0e12;
	--dl-surface-2:    #14141a;
	--dl-surface-3:    #1c1c24;

	/* gold — the primary accent */
	--dl-gold:         #c9a84c;
	--dl-gold-lt:      #f0d98c;
	--dl-gold-dp:      #8c6d22;
	--dl-gold-grad:    linear-gradient(135deg, #f0d98c 0%, #c9a84c 45%, #8c6d22 100%);

	/* teal — the secondary accent, used sparingly for contrast + freshness */
	--dl-teal:         #0f9a9a;
	--dl-teal-lt:      #5fd6d6;
	--dl-teal-dp:      #0a6767;
	--dl-teal-grad:    linear-gradient(135deg, #5fd6d6 0%, #0f9a9a 100%);

	/* type */
	--dl-cream:        #f6f1e4;
	--dl-text:         #d8d4cc;
	--dl-muted:        #8f8a80;

	/* lines + glow */
	--dl-line:         rgba(201, 168, 76, .16);
	--dl-line-strong:  rgba(201, 168, 76, .42);
	--dl-glow-gold:    0 10px 40px rgba(201, 168, 76, .18);
	--dl-glow-teal:    0 10px 40px rgba(15, 154, 154, .20);

	/* motion */
	--dl-ease:         cubic-bezier(.22, .61, .36, 1);
	--dl-ease-out:     cubic-bezier(.16, 1, .3, 1);
	--dl-dur:          .5s;

	/* rhythm */
	--dl-radius:       14px;
	--dl-radius-sm:    8px;
	--dl-shell:        1180px;

	/* spacing scale — everything on the site uses these, so vertical rhythm stays
	   even and nothing is arbitrarily wide or tight. Each step fluidly shrinks on
	   small screens rather than snapping at a breakpoint. */
	--sp-1:  6px;
	--sp-2:  10px;
	--sp-3:  clamp(12px, 1.4vw, 16px);
	--sp-4:  clamp(16px, 2vw, 22px);
	--sp-5:  clamp(22px, 2.8vw, 30px);
	--sp-6:  clamp(28px, 3.6vw, 40px);
	--sp-7:  clamp(36px, 5vw, 56px);
	--sp-8:  clamp(48px, 7vw, 84px);
	--sp-9:  clamp(60px, 9vw, 110px);
}

/* ==========================================================================
   2. BASE
   ========================================================================== */
/*
 * The root has to carry the background, not just the body. iOS Safari paints
 * its status bar, its bottom toolbar and the rubber-band overscroll area from
 * the root element — with html transparent it falls back to white, which is why
 * the phone showed white bars top and bottom around a black page.
 * color-scheme makes Safari render its own chrome dark to match.
 */
html {
	background: var(--dl-black);
	color-scheme: dark;
}

/*
 * Undo Astra's mobile root shrink.
 *
 * Astra ships html{font-size:91.2%} below 921px against 100% on desktop, so the
 * root is 14.59px on a phone and 16px on a laptop. Every rem on the site is
 * therefore worth ~9% less on mobile, which is why copy read small everywhere
 * rather than in any one component: the first fixes here were per-component
 * patches for what was a single global cause.
 *
 * !important is load-bearing rather than lazy. Astra prints its dynamic CSS
 * inline in <head> AFTER the child stylesheet, so an equally specific rule
 * (0,0,1 on html) would lose on source order no matter where it sits in here.
 *
 * Both of Astra's breakpoints are covered: it declares 91.2% at max-width 921px
 * and again at 544px, and the narrower one would otherwise win on a phone.
 */
@media (max-width: 921px) {
	html { font-size: 100% !important; }
}

body,
#page {
	background-color: var(--dl-black);
	color: var(--dl-text);
}

/*
 * Faint diagonal line texture. It has to live on #page, the topmost opaque
 * layer — put on html or body it would simply be painted over. .ast-container
 * gives up its own background for the same reason.
 *
 * Deliberately not background-attachment: fixed; a fixed background over a long
 * scrolling page is a known repaint cost on iOS, and at a 7px repeat the
 * difference is invisible anyway.
 */
#page {
	background-image: repeating-linear-gradient(
		45deg,
		rgba(255, 255, 255, .019) 0,
		rgba(255, 255, 255, .019) 1px,
		transparent 1px,
		transparent 7px
	);
}
.ast-container { background: transparent; }

body {
	font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	line-height: 1.75;
}

/* subtle luxury texture — a fixed radial wash so the black never reads as dead flat */
body::before {
	content: "";
	position: fixed;
	inset: 0;
	pointer-events: none;
	z-index: 0;
	background:
		radial-gradient(1000px 600px at 12% -8%,  rgba(201, 168, 76, .07), transparent 60%),
		radial-gradient(900px  520px at 88% 108%, rgba(15, 154, 154, .07), transparent 60%);
}
#page { position: relative; z-index: 1; }

h1, h2, h3, h4, h5, h6,
.entry-title,
.site-title {
	font-family: "Cormorant Garamond", Georgia, "Times New Roman", serif;
	font-weight: 600;
	letter-spacing: -.01em;
	line-height: 1.2;
}

/*
 * Headings are gold site-wide. Astra colours headings that carry an id (our
 * contents anchors) with its link colour, which rendered them dark blue — these
 * selectors are specific enough to win without needing !important everywhere.
 */
h1, h2, h3, h4, h5, h6,
#content h1, #content h2, #content h3, #content h4, #content h5, #content h6,
.entry-content h1, .entry-content h2, .entry-content h3,
.entry-content h4, .entry-content h5, .entry-content h6,
.dl-article h1, .dl-article h2, .dl-article h3,
.dl-article h4, .dl-article h5, .dl-article h6,
h1[id], h2[id], h3[id], h4[id], h5[id], h6[id],
h1:target, h2:target, h3:target, h4:target, h5:target, h6:target {
	color: var(--dl-gold-lt);
}
/* the page's own H1 stays cream so it leads; everything below it is gold */
h1.dl-hero__title, h1.entry-title, h1.dl-profile__name { color: var(--dl-cream); }
/* headings must never inherit a link colour */
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { color: inherit; }

h1 { font-size: clamp(2.1rem, 5vw, 3.6rem); }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); }
h3 { font-size: clamp(1.3rem, 2.4vw, 1.7rem); }

p  { margin: 0 0 1.35em; }

a {
	color: var(--dl-gold-lt);
	text-decoration: none;
	transition: color .25s var(--dl-ease);
}
a:hover, a:focus { color: var(--dl-teal-lt); }

/* keyboard focus stays visible — accessibility */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
	outline: 2px solid var(--dl-gold);
	outline-offset: 3px;
}

/* No blue anywhere. Astra paints buttons and the scroll-to-top in its accent, and
   mobile browsers add their own blue tap highlight — both look wrong on black. */
* { -webkit-tap-highlight-color: transparent; }

button:focus,
.dl-faq__q:focus,
.dl-faq__q:active,
.dl-faq__q:hover {
	background: transparent;
	box-shadow: none;
}
/* mouse/touch focus shouldn't paint a block; keyboard focus keeps the gold ring above */
button:focus:not(:focus-visible) { outline: none; }

/* Astra's scroll-to-top */
#ast-scroll-top,
.ast-scroll-to-top-right,
.ast-scroll-top-icon {
	/* transparent: the arrow and its outline, nothing filled behind them. No
	   backdrop blur either — blurring the page through a control that is meant
	   to read as transparent puts the fill back in all but name. */
	background: transparent !important;
	color: var(--dl-gold-lt) !important;
	border: 1px solid var(--dl-line-strong) !important;
	border-radius: var(--dl-radius-sm) !important;
}
#ast-scroll-top:hover { background: rgba(24, 20, 8, .55) !important; border-color: var(--dl-gold) !important; }

/*
 * Only at the foot of the page.
 *
 * Astra reveals this after any downward scroll, which parks a control over the
 * page for the whole of a long listing. It is only worth anything once you have
 * run out of page, so JS sets .dl-at-foot on <html> from the scroll position.
 *
 * `display` is forced here rather than left to Astra, which sets it inline.
 * Measured why: with Astra holding display:none, the fade never ran, because a
 * transition does not tick on an element that is not being rendered. Computed
 * opacity and visibility stayed frozen on their old values while pointer-events,
 * which is not transitioned, updated normally. Keeping the element rendered at
 * all times and driving only opacity/visibility makes the fade work and puts
 * one rule in charge instead of two fighting.
 *
 * Specificity check, because this leans on !important: the review-form lock
 * `body.dl-locked #ast-scroll-top` is (1,1,1) and still beats this (1,0,0), so
 * the button stays hidden behind the form exactly as before.
 */
#ast-scroll-top {
	display: block !important;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity .3s var(--dl-ease), visibility .3s var(--dl-ease);
}
.dl-at-foot #ast-scroll-top {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

::selection { background: rgba(201, 168, 76, .3); color: #fff; }

/* gold gradient text — for hero words + section eyebrows */
.dl-gold-text {
	background: var(--dl-gold-grad);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
}

/* ==========================================================================
   3. LAYOUT SHELL
   ========================================================================== */
.dl-shell {
	max-width: var(--dl-shell);
	margin-inline: auto;
	padding-inline: clamp(18px, 4vw, 34px);
}

/*
 * Astra pads .ast-container differently per template — 20px on pages, 8px on
 * archives — which stacked on top of the shell's own gutter and left the guide
 * 24px narrower than a location page on a phone. Zero it on our templates so
 * .dl-shell is the only thing setting the edge.
 *
 * Its 1240px max-width is deliberately left alone: that keeps the hero inside
 * the container on desktop rather than running edge to edge.
 * Scoped rather than global: Astra's own pages still need their padding.
 */
#content > .ast-container:has(> .dl-guide),
#content > .ast-container:has(> .dl-tax),
#content > .ast-container:has(> .dl-profile),
#content > .ast-container:has(> .dl-home),
#content > .ast-container:has(> .dl-archive) {
	padding-left: 0;
	padding-right: 0;
}

/*
 * Astra also spaces #primary away from the header — 4em of padding below 993px,
 * 4em of margin above it — which dropped every hero 58px down the page and left
 * a dead black band under the header. Our templates open with a full-bleed hero
 * that should meet the header, so take the top off both. The bottom stays: it's
 * what separates the last section from the footer.
 */
/* .dl-profile is deliberately not in this list: it opens with the breadcrumb row
   rather than a full-bleed hero, so zeroing its top padding pushed the trail and
   the prev/next buttons hard up against the header line. */
#primary.dl-home,
#primary.dl-tax,
#primary.dl-guide,
#primary.dl-archive {
	padding-top: 0;
	margin-top: 0;
}
/* explicit rather than inherited, so the breadcrumb row and its prev/next buttons
   always clear the header bar at every width */
#primary.dl-profile { margin-top: 0; padding-top: clamp(14px, 2.4vw, 30px); }

/* one section rhythm, three densities */
.dl-section        { padding: var(--sp-8) 0; position: relative; }
.dl-section--tight { padding: var(--sp-6) 0; }
.dl-section--loose { padding: var(--sp-9) 0; }

/* hairline divider with a gold centre fade */
.dl-rule {
	height: 1px;
	border: 0;
	background: linear-gradient(90deg, transparent, var(--dl-line-strong), transparent);
	margin: 0;
}

.dl-eyebrow {
	display: block;
	font-family: "Inter", sans-serif;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .32em;
	text-transform: uppercase;
	color: var(--dl-gold);
	margin-bottom: var(--sp-2);
}
/*
 * An eyebrow is always followed by its heading, so keying off that pairing gives
 * every section the same rhythm no matter how deeply the block is nested. The
 * positional rule this replaces only reached direct children of .dl-shell.
 */
.dl-eyebrow + h1,
.dl-eyebrow + h2,
.dl-eyebrow + h3 { margin-top: 0; margin-bottom: var(--sp-4); }

/* a lede between the heading and the content carries the gap instead */
.dl-eyebrow + h2 + .dl-lede,
h2 + .dl-lede { margin-top: calc(var(--sp-4) * -1 + var(--sp-2)); margin-bottom: var(--sp-4); }

/* section headings without an eyebrow */
.dl-section > .dl-shell > h2 { margin: 0 0 var(--sp-4); }

.dl-lede {
	font-size: clamp(1.02rem, 1.7vw, 1.2rem);
	color: var(--dl-muted);
	margin: 0 0 var(--sp-4);
}
/*
 * Section ledes run the full shell width so they line up with the grid beneath
 * them — capped at 62ch they stopped a third of the way across and read as a
 * layout fault. The centred display blocks keep the measure: a centred line
 * running 110 characters is genuinely hard to track back from.
 */
.dl-hero .dl-lede,
.dl-guide-promo .dl-lede { max-width: 62ch; margin-inline: auto; }
.dl-lede:last-child { margin-bottom: 0; }

/* ==========================================================================
   4. HERO
   ========================================================================== */
.dl-hero {
	position: relative;
	min-height: clamp(430px, 68vh, 660px);
	display: grid;
	place-items: center;
	text-align: center;
	overflow: hidden;
	border-bottom: 1px solid var(--dl-line);
	/* Once the copy outgrows min-height the hero is exactly content height, which
	   left the gold flourish sitting 2px off the bottom edge. This keeps air below
	   it at every size. */
	padding-block: clamp(32px, 6vw, 64px);
}

/* slow drifting sheen behind the hero copy */
.dl-hero::after {
	content: "";
	position: absolute;
	inset: -40%;
	background: conic-gradient(from 0deg,
		transparent 0deg,
		rgba(201, 168, 76, .10) 60deg,
		transparent 130deg,
		rgba(15, 154, 154, .09) 220deg,
		transparent 300deg);
	animation: dl-drift 26s linear infinite;
	pointer-events: none;
}
@keyframes dl-drift { to { transform: rotate(360deg); } }

.dl-hero__inner { position: relative; z-index: 2; }

.dl-hero__title { margin: 0 0 18px; }

/* thin gold rule under the hero title that draws itself in */
.dl-hero__flourish {
	width: 0;
	height: 1px;
	margin: 26px auto 0;
	background: var(--dl-gold-grad);
	animation: dl-draw 1.5s var(--dl-ease-out) .5s forwards;
}
@keyframes dl-draw { to { width: 190px; } }

/* ==========================================================================
   5. CARDS — the signature component
   ========================================================================== */
/*
 * Intrinsically responsive: the track minimum itself scales with the viewport,
 * so this gives 2 columns on a phone and 4 on desktop from ONE rule. No media
 * queries to be defeated by a cached stylesheet or a stray viewport.
 *   390px phone  -> min 150px -> 2 columns
 *   768px tablet -> min ~169px -> 3-4 columns
 *   1180px desk  -> min 250px -> 4 columns
 */
.dl-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(clamp(140px, 22vw, 250px), 1fr));
	gap: var(--sp-3);
}
@media (min-width: 783px) { .dl-grid { gap: var(--sp-4); } }

.dl-card {
	position: relative;
	display: flex;
	flex-direction: column;
	/* same near-black + faint gold wash as the luxury cards, so every card on the
	   site reads as one family */
	background:
		radial-gradient(120% 80% at 50% 100%, rgba(201,168,76,.05), transparent 60%),
		linear-gradient(180deg, #0c0c10, #08080a);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	overflow: hidden;
	isolation: isolate;
	transition:
		transform    .55s var(--dl-ease-out),
		border-color .35s var(--dl-ease),
		box-shadow   .55s var(--dl-ease-out);
}

/* animated gold border-sweep on hover (masked gradient ring — no layout shift) */
.dl-card::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	padding: 1px;
	background: linear-gradient(135deg, var(--dl-gold-lt), transparent 35%, transparent 65%, var(--dl-teal));
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	opacity: 0;
	transition: opacity .45s var(--dl-ease);
	pointer-events: none;
	z-index: 3;
}

@media (hover: hover) and (pointer: fine) {
	/* translate3d rather than translateY, so the lift is composited rather than
	   going back through layout. Deliberately NOT paired with a standing
	   will-change: that would hold every card on the GPU for the life of the
	   page, and a promoted layer per card is what a phone cannot afford. */
	.dl-card:hover {
		transform: translate3d(0, -8px, 0);
		border-color: transparent;
		box-shadow: var(--dl-glow-gold);
	}
	.dl-card:hover::before { opacity: 1; }
	.dl-card:hover .dl-card__img img { transform: scale(1.07); }
	.dl-card:hover .dl-card__more { gap: 14px; color: var(--dl-gold-lt); }
}
.dl-card:active { transform: translateY(-3px); }

/* ==========================================================================
   THE GOLD-TO-TEAL EDGE, SHARED
   --------------------------------------------------------------------------
   The same ring the listing cards carry, on everything else that is tappable:
   service chips, area chips, the area cover cards and the duo tiles. One
   effect across the site rather than a different accent per component.

   It is a 1px gradient painted into the border box and punched out with a mask,
   so it sits exactly where the border is and replaces it — the label underneath
   keeps its own colour, which is the point. border-radius: inherit means each
   component keeps its own shape, from the 5px chips to the 999px pills.
   ========================================================================== */
.dl-likes li.is-link,
.dl-arealinks li a,
.dl-nearby li a,
.dl-guide__morecard,
.dl-duo__item { position: relative; }

/* the same gradient as .dl-card, deliberately not a variant of it */
.dl-likes li.is-link::before,
.dl-arealinks li a::before,
.dl-nearby li a::before,
.dl-guide__morecard::before,
.dl-duo__item::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	padding: 1px;
	background: linear-gradient(135deg, var(--dl-gold-lt), transparent 35%, transparent 65%, var(--dl-teal));
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	opacity: 0;
	transition: opacity .3s var(--dl-ease);
	pointer-events: none;
	z-index: 3;
}

/* The ring and the border share the same 1px, so the border stands down for it —
   without this the resting gold sits underneath and the edge reads doubled. */
@media (hover: hover) {
	.dl-likes li.is-link:hover::before,
	.dl-arealinks li a:hover::before,
	.dl-nearby li a:hover::before,
	.dl-guide__morecard:hover::before,
	.dl-duo__item:hover::before { opacity: 1; }

	.dl-likes li.is-link:hover,
	.dl-arealinks li a:hover,
	.dl-nearby li a:hover,
	.dl-guide__morecard:hover { border-color: transparent; }
}

.dl-card__img {
	position: relative;
	aspect-ratio: 3 / 2;
	overflow: hidden;
	/*
	 * Near-black rather than the grey surface token.
	 *
	 * This shows in the band where the photo does not quite reach the bottom of
	 * its box, and the token is rgb(28,28,36) — light enough to read as a line
	 * against a #09090c body. Measured on the rail cards: excess brightness at
	 * the seam went 3 -> 0 from this alone.
	 */
	background: #0b0b0e;
	/*
	 * An opaque row on the seam.
	 *
	 * Measured: nothing overhangs, the image fills its box exactly — but the
	 * boundary lands on a fractional pixel (.578 on a 1x screen) and the body
	 * below it has no background of its own, so the renderer blends the photo's
	 * bright bottom row into the card behind it. That is the pale hairline, and
	 * it shifts as the card lifts 8px on hover, which is what reads as a flash.
	 *
	 * box-sizing is border-box here, so this takes a pixel from the image rather
	 * than adding one to the box: nothing moves, and the blend has something
	 * solid to happen against.
	 */
	border-bottom: 1px solid #09090c;
}
.dl-card__img img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 1.1s var(--dl-ease-out);
}
/*
 * Gradient scrim, so overlaid text stays readable on any photo — and so the
 * photo actually reaches the card's colour before the body starts.
 *
 * It used to stop at 85% opacity, which left 15% of the photo showing at the
 * very bottom edge. Measured against a bright lower edge that put rgb(37,34,34)
 * directly above the body's rgb(9,9,12): a 28-point step, not an antialiasing
 * artefact. Static and subtle at rest, but the card lifts 8px and the photo
 * zooms on hover, so that edge is redrawn every frame — which is the flicker.
 *
 * Carrying the last stop to full opacity on the body's own colour removes the
 * step rather than hiding it. Two earlier attempts here fixed the wrong layer:
 * compositing hints, then a 1px cap that merely moved the step up a pixel.
 */
/*
 * The readability scrim, and why it runs past the bottom edge.
 *
 * Ending the gradient at 100% put its only fully-opaque row exactly on the
 * img/body join. Two things then conspired:
 *
 *   1. .dl-card__body carries margin-top:-1px to guarantee no sub-pixel gap.
 *      That hides the last row, so the row actually on show sits at ~99.6%,
 *      where the scrim is still slightly translucent and a bright photo comes
 *      through it.
 *   2. The image box ends on a fractional device pixel (226.66px on an
 *      iPhone 13). The photo's antialiased final row has more coverage than
 *      the scrim's, so it wins even where the scrim is nominally opaque.
 *
 * Bisected on device: moving the opaque stop earlier fixed every row except
 * that fractional one, and it only moved when the border width changed. Both
 * are needed. Extending 3px below the box puts the join deep inside the solid
 * region, and .dl-card's overflow:hidden keeps the overhang inside the card
 * while .dl-card__body (z-index:1) paints over it.
 *
 * Verified 0 excess brightness at the seam on iPhone SE / 13 / 13 Pro Max and
 * desktop, on both the grid cards and the recently-viewed rail, with desktop
 * hover unregressed. Costs no compositor layer, so it cannot bring back the
 * pinch-zoom crash that promoting these elements caused.
 */
.dl-card__img::after {
	content: "";
	position: absolute;
	inset: 0 0 -3px 0;
	background: linear-gradient(180deg,
		transparent 35%,
		rgba(8, 8, 10, .85) 86%,
		#09090c 96%);
}

.dl-card__tag {
	position: absolute;
	top: 14px;
	left: 14px;
	z-index: 2;
	padding: 5px 12px;
	border-radius: 999px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--dl-black);
	background: var(--dl-gold-grad);
}
.dl-card__tag--teal { background: var(--dl-teal-grad); color: #04211f; }

/*
 * Opaque, and overlapping the photo by a pixel.
 *
 * This was transparent, so the colour below the seam was whatever the card's
 * background gradient happened to be at that height — which changes from card
 * to card. Matching the scrim to it could only ever be right for one card size.
 * A flat base makes both sides of the join a known constant, and the -1px pulls
 * them together so there is no boundary left to rasterise between.
 *
 * #09090c is the card gradient's value through this region (it runs #0c0c10 to
 * #08080a), so nothing looks different — it is simply no longer variable.
 */
.dl-card__body {
	position: relative;
	z-index: 1;
	margin-top: -1px;
	background: #09090c;
	padding: var(--sp-4);
	display: flex;
	flex-direction: column;
	flex: 1;
	gap: var(--sp-1);
}
.dl-card__title { margin: 0; font-size: 1.2rem; line-height: 1.25; }
.dl-card__title a { color: var(--dl-cream); }
.dl-card__excerpt { font-size: .9rem; color: var(--dl-muted); margin: 0; flex: 1; }
.dl-card__body > .dl-card__more { margin-top: var(--sp-2); }

/* The whole listing card is the click target now that the "View profile" link is
   gone. The title's link is stretched over the card, so anywhere on it works. */
.dl-listing .dl-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}
.dl-listing .dl-card__title { position: static; }
.dl-listing { cursor: pointer; }

/* Journal cards, the same way. The title was the only click target, so the
   date and the excerpt beside it did nothing, which is not what a card that
   looks like a card leads you to expect.

   inset:0 resolves against .dl-card__body, not .dl-card, because the body is
   the nearest positioned ancestor. That is the whole card here: these carry no
   thumbnail, and .dl-card__body is flex:1, so it fills the card on its own.
   Where a journal card does have an image, that image is already its own <a>,
   so the pair still covers everything. */
.dl-post .dl-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}
.dl-post .dl-card__title { position: static; }
.dl-post { cursor: pointer; }

.dl-card__more {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--dl-gold);
	transition: gap .35s var(--dl-ease), color .35s var(--dl-ease);
}
.dl-card__more::after {
	content: "";
	width: 22px;
	height: 1px;
	background: currentColor;
}

/* --- directory listings + taxonomy archives --- */
.dl-hero--tax { min-height: clamp(260px, 34vh, 360px); }

/* ==========================================================================
   JOURNAL HERO STAT CARDS — frosted glass
   --------------------------------------------------------------------------
   Four figures, each on its own surface, in place of one line of text.

   The frost is a real backdrop-filter rather than a flat translucent panel,
   which is only worth the cost when there is something behind it worth
   sampling. There is: the hero carries a gradient wash and the diagonal
   texture, so each card picks up a different part of both and they do not
   read as four identical rectangles.

   Every colour comes from the existing tokens. The numbers use --dl-gold-grad
   clipped to the text, the same treatment the hero titles already use, so the
   cards belong to the page rather than sitting on top of it.

   On the compositor cost, deliberately: backdrop-filter promotes each card to
   its own layer. Four static elements on one page is a rounding error against
   the 68 permanently-promoted layers that caused the iOS pinch-zoom crash
   earlier in this build, and none of these animate. That is also why the
   treatment is scoped to this one block rather than offered site-wide.
   ========================================================================== */
.dl-jstats {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--sp-2);
	/*
	 * Sized off the viewport, not the parent. .dl-hero uses place-items:center,
	 * so .dl-hero__inner shrink-wraps its content and a percentage width here
	 * resolves against a box that is itself sized by this element. Measured:
	 * width:min(100%,660px) produced 105px cards on both a phone and a 1440
	 * desktop. Viewport units break that circularity.
	 */
	width: min(92vw, 660px);
	margin: var(--sp-4) auto 0;
}

.dl-jstat {
	position: relative;
	padding: var(--sp-4) var(--sp-2);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	/* a cream tint rather than plain white: white frost reads blue-grey against
	   this palette and pulls the whole hero cold */
	background: linear-gradient(180deg, rgba(246, 241, 228, .06), rgba(246, 241, 228, .015));
	-webkit-backdrop-filter: blur(16px) saturate(150%);
	backdrop-filter: blur(16px) saturate(150%);
	/* the top inner highlight is what actually sells glass; without it the card
	   reads as a flat translucent box */
	box-shadow: inset 0 1px 0 rgba(246, 241, 228, .08);
	overflow: hidden;
}

/* one hairline of the house gold-to-teal along the top edge, so a row of four
   reads as a set rather than four unrelated boxes */
.dl-jstat::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--dl-gold), var(--dl-teal), transparent);
	opacity: .55;
	pointer-events: none;
}

.dl-jstat__n {
	display: block;
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: clamp(1.55rem, 5.2vw, 2.05rem);
	/*
	 * 1.25, not 1, because of the two things that combine here.
	 *
	 * Cormorant Garamond sets old-style figures, so 3 4 5 7 9 descend below the
	 * baseline exactly as a lowercase g does, and so does the J in Jan/Jun/Jul.
	 * With line-height:1 the box ends at the baseline, and background-clip:text
	 * paints the gradient only within that box, so the descender falls outside
	 * the paint area and simply is not drawn. It reads as the glyph being
	 * sliced off rather than as a layout overflow.
	 *
	 * Measured on device at 32px: worst case is "3", "5", "9", "Sep" and "May"
	 * at 6.7px below the box, which is 0.209em. 1.25 clears that with margin.
	 * Only "Jul" happened to be on screen when this was spotted, which is why
	 * it looked like a problem with one letter.
	 */
	line-height: 1.25;
	background: var(--dl-gold-grad);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}
/* the month sits alongside three numerals, so it comes down to match their weight */
.dl-jstat__n--sm { font-size: clamp(1.25rem, 4.2vw, 1.6rem); }

.dl-jstat__l {
	display: block;
	margin-top: 7px;
	font-size: .64rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--dl-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

@media (max-width: 600px) {
	.dl-jstats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.dl-jstat { padding: var(--sp-3) var(--sp-2); }
}

/* Firefox without backdrop-filter, and anything else that lacks it: an opaque
   surface, because a 6%-alpha panel over a dark hero is invisible on its own. */
@supports not ((-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px))) {
	.dl-jstat { background: rgba(20, 20, 26, .82); }
}

.dl-hero__count {
	margin: var(--sp-3) 0 0;
	font-size: .95rem;
	letter-spacing: .04em;
	color: var(--dl-muted);
}
.dl-hero__count strong {
	font-size: 1.5rem;
	font-family: "Cormorant Garamond", Georgia, serif;
	background: var(--dl-gold-grad);
	-webkit-background-clip: text; background-clip: text;
	-webkit-text-fill-color: transparent;
	margin-right: 4px;
}

.dl-listing .dl-card__img { aspect-ratio: 3 / 4; display: block; }
.dl-listing__meta  { font-size: .82rem; color: var(--dl-muted); margin: 0; }
.dl-listing__price { font-size: .92rem; font-weight: 600; color: var(--dl-gold-lt); margin: 0; }

/*
 * The rate, on the photo rather than under it.
 *
 * It sits bottom left, where .dl-card__img::after has already darkened the
 * photo to near-black, so it needs no plate of its own to stay legible. Two
 * details keep it honest: a text-shadow for the rare photo that is bright
 * right into the corner, and pointer-events:none so it never intercepts a tap
 * meant for the card, whose whole surface is the click target.
 */
.dl-card__rate {
	position: absolute;
	left: var(--sp-3);
	bottom: 10px;
	z-index: 2;
	font-size: .92rem;
	font-weight: 600;
	line-height: 1;
	color: var(--dl-gold-lt);
	text-shadow: 0 1px 6px rgba(0, 0, 0, .85);
	pointer-events: none;
}
.dl-card--mini .dl-card__rate { left: var(--sp-2); bottom: 8px; font-size: .8rem; }
@media (max-width: 600px) {
	.dl-card__rate { left: var(--sp-2); bottom: 8px; }
}

.dl-empty { text-align: center; color: var(--dl-muted); padding: 40px 0; }

/* empty-area state — leads with what IS available rather than what isn't */
.dl-nearby-intro {
	text-align: center;
	max-width: 62ch;
	margin: 0 auto var(--sp-6);
	padding-bottom: var(--sp-5);
	border-bottom: 1px solid var(--dl-line);
}
.dl-nearby-intro__title {
	font-size: clamp(1.4rem, 2.6vw, 1.9rem);
	margin: 0 0 var(--sp-2);
}
.dl-nearby-intro__text {
	color: var(--dl-muted);
	font-size: .98rem;
	margin: 0;
}

/* nearby-areas link cloud — the internal-link net across the borough cluster */
.dl-nearby ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
}
.dl-eyebrow + .dl-nearby ul,
.dl-nearby .dl-eyebrow + ul { margin-top: var(--sp-2); }
.dl-nearby li a {
	display: inline-block;
	padding: 8px 16px;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	font-size: .86rem;
	color: var(--dl-text);
	transition: border-color .3s var(--dl-ease), color .3s var(--dl-ease), background .3s var(--dl-ease);
}
/*
 * Guarded, and teal.
 *
 * This was an unguarded :hover, so on a phone iOS left it latched on to
 * whichever card was tapped last — you would come back from an area page and
 * find one card still lit for no reason. Inside (hover: hover) it cannot apply
 * to touch at all, and :active below gives the press its own feedback.
 */
@media (hover: hover) {
	.dl-nearby li a:hover { border-color: transparent; }      /* the ring takes over */
}

/* --- clouds that carry a cover photo ---
 * A uniform card grid rather than a wrapping row of pills. With 44 areas the
 * pills wrapped into a ragged one-and-two-per-row column on a phone that was
 * hard to scan; equal tiles read as a set and halve the height.
 */
.dl-nearby--covers ul {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(165px, 1fr));
	gap: 8px;
}
.dl-nearby--covers li a {
	display: flex;
	align-items: center;
	gap: 10px;
	min-width: 0;
	height: 100%;                  /* equal heights across a row */
	padding: 6px 12px 6px 6px;
	border: 1px solid var(--dl-line);
	border-radius: 12px;
	background: linear-gradient(180deg, rgba(255,255,255,.025), transparent);
	background-clip: padding-box;
}
.dl-cloud__pic {
	position: relative;
	flex: 0 0 auto;
	width: 40px; height: 40px;
	border-radius: 9px;            /* rounded square: reads as a card, not an avatar */
	overflow: hidden;
	background: var(--dl-surface-3);
	/* thin gold ring, the same detail the cards use */
	box-shadow: 0 0 0 1px rgba(201,168,76,.25);
}
.dl-cloud__pic img {
	width: 100%; height: 100%;
	object-fit: cover;
	object-position: 50% 14%;      /* faces sit near the top of a 3:4 crop */
	display: block;
	transition: transform .6s var(--dl-ease-out);
}
.dl-cloud__txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dl-cloud__name {
	font-size: .82rem;
	line-height: 1.2;
	color: var(--dl-text);
	overflow-wrap: anywhere;       /* "High St. Kensington" must not blow the tile out */
	transition: color .25s var(--dl-ease);
}
.dl-nearby--covers .dl-cloud__n { font-size: .68rem; color: var(--dl-muted); margin: 0; }
/* These cards are .dl-nearby li a, so the shared ring already covers the edge.
   Only the thumbnail outline and the zoom are added on top; the area name and
   the count keep their resting colours. */
@media (hover: hover) {
	.dl-nearby--covers li a:hover { border-color: transparent; }
	.dl-nearby--covers li a:hover .dl-cloud__pic { box-shadow: 0 0 0 1px var(--dl-teal); }
	.dl-nearby--covers li a:hover .dl-cloud__pic img { transform: scale(1.08); }
}
.dl-nearby--covers li a.is-pressed .dl-cloud__pic { box-shadow: 0 0 0 1px var(--dl-teal); }
@media (max-width: 600px) {
	/* pinned to two, so a long name can't drop a tile to its own row */
	.dl-nearby--covers ul { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; }
	.dl-nearby--covers li a { padding: 5px 9px 5px 5px; gap: 8px; border-radius: 10px; }
	.dl-cloud__pic { width: 36px; height: 36px; border-radius: 8px; }
	.dl-cloud__name { font-size: .76rem; }
	.dl-nearby--covers .dl-cloud__n { font-size: .64rem; }
}

/* --- badges on listing cards — same language as the profile, scaled down --- */
.dl-badges {
	position: absolute;
	top: 9px; left: 9px;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
	pointer-events: none;
}
.dl-badge {
	padding: 4px 9px;
	border-radius: 3px;
	font-family: "Inter", sans-serif;
	font-size: 8.5px;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--dl-gold-lt);
	background: rgba(10, 9, 7, .6);
	-webkit-backdrop-filter: blur(8px) saturate(140%);
	backdrop-filter: blur(8px) saturate(140%);
	border: 1px solid rgba(201, 168, 76, .45);
	white-space: nowrap;
}
.dl-badge--recommended { color: #14100a; background: linear-gradient(135deg, #ffed8c, var(--dl-gold)); border-color: transparent; }
.dl-badge--new { color: var(--dl-teal-lt); border-color: rgba(15,154,154,.5); }

/* --- single listing / escort profile --- */
.dl-profile { padding: var(--sp-5) 0 0; }
/* the profile grid needs air before the divider, or the last stat row sits on it */
.dl-profile > .dl-shell { padding-bottom: var(--sp-7); }

.dl-crumbs-wrap { padding-top: 18px; }
/* pages + posts: the trail sits under the title, so it needs a little air above
   and a hairline to separate it from the heading rather than the content */
.dl-crumbs-wrap--under { margin: 0 0 var(--sp-5); padding: var(--sp-3) 0 0; border-top: 1px solid var(--dl-line); }
.dl-crumbs-wrap--under .dl-crumbs { margin-bottom: 0; }
.dl-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: .82rem; color: var(--dl-muted); margin-bottom: 22px; }
.dl-crumbs a { color: var(--dl-muted); }
.dl-crumbs a:hover { color: var(--dl-gold-lt); }
.dl-crumbs__here { color: var(--dl-cream); }
/* Yoast prints a plain string rather than markup, so style its separator too */
.dl-crumbs .breadcrumb_last { color: var(--dl-cream); }

/* profile: the trail keeps the left, prev/next escort sits at the right end of
   the same line. The trail can wrap internally; the arrows never shrink. */
.dl-crumbnav { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); margin-bottom: 22px; }
.dl-crumbnav .dl-crumbs { margin-bottom: 0; flex: 1 1 auto; min-width: 0; }

.dl-pnav { display: flex; align-items: center; flex: 0 0 auto; }
.dl-pnav__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px; height: 36px;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	color: var(--dl-text);
	background-clip: padding-box;
	transition: border-color .3s var(--dl-ease), color .3s var(--dl-ease), background .3s var(--dl-ease);
}
@media (hover: hover) {
	.dl-pnav__btn:hover { border-color: var(--dl-gold); color: var(--dl-gold-lt); background: rgba(201,168,76,.06); }
}
.dl-pnav__btn:active { border-color: var(--dl-gold); color: var(--dl-gold-lt); }
.dl-pnav__sep { width: 1px; height: 15px; background: var(--dl-line); margin: 0 9px; }
@media (max-width: 600px) {
	.dl-crumbnav { gap: var(--sp-3); margin-bottom: 16px; }
	.dl-pnav__btn { width: 38px; height: 38px; }        /* still a comfortable thumb target */
	.dl-pnav__sep { margin: 0 5px; }
}

.dl-chip--badge { color: var(--dl-black); background: linear-gradient(135deg, #ffed8c, var(--dl-gold)); border-color: transparent; }

.dl-profile__grid {
	display: grid;
	grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
	gap: clamp(20px, 3vw, 40px);
	align-items: start;
}
@media (max-width: 900px) { .dl-profile__grid { grid-template-columns: 1fr; } }

.dl-profile__left { position: sticky; top: 92px; display: grid; gap: var(--sp-3); }
@media (max-width: 900px) { .dl-profile__left { position: static; } }

.dl-profile__photo {
	position: relative;
	margin: 0;
	border-radius: var(--dl-radius);
	overflow: hidden;
	border: 1px solid var(--dl-line);
	background: var(--dl-surface-2);
}
.dl-profile__photo img { width: 100%; height: auto; display: block; }

/* ==========================================================================
   PHOTO LOADING — a slow gold sheen where a photo has not arrived yet
   Sits on ::before because the card and duo tiles already spend ::after on
   their scrims. z-index 1 puts it over the photo but under the rate, which
   is on 2, so a price never disappears behind the shimmer.

   Present but transparent at rest rather than only existing while loading:
   a pseudo-element cannot transition into being, and fading out is the whole
   point. Nothing animates until the class goes on.
   ========================================================================== */
.dl-profile__photo::before,
.dl-card__img::before,
.dl-duo__img::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	opacity: 0;
	pointer-events: none;
	transition: opacity .45s var(--dl-ease);
	background-color: #0e0e12;
	background-image: linear-gradient(100deg,
		transparent 22%,
		rgba(201, 168, 76, .20) 41%,
		rgba(246, 241, 228, .16) 50%,
		rgba(201, 168, 76, .20) 59%,
		transparent 78%);
	background-size: 220% 100%;
	background-repeat: no-repeat;
}
.dl-profile__photo.is-loading::before,
.dl-card__img.is-loading::before,
.dl-duo__img.is-loading::before {
	opacity: 1;
	animation: dl-sheen 1.9s ease-in-out infinite;
}
@keyframes dl-sheen {
	from { background-position: 140% 0; }
	to   { background-position: -40% 0; }
}
/* the panel still covers the gap, it just stops moving */
@media (prefers-reduced-motion: reduce) {
	.dl-profile__photo.is-loading::before,
	.dl-card__img.is-loading::before,
	.dl-duo__img.is-loading::before { animation: none; }
}

/* ── badges, drawn in the theme's own language ──
   A vertical stack top-left of the photo. Glass fill, gold hairline, small caps.
   Reads as jewellery on the image rather than stickers stuck over it. */
.dl-photobadges {
	position: absolute;
	top: 12px; left: 12px;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
	z-index: 2;
}
.dl-photobadge {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 12px 6px 11px;
	border-radius: 3px;
	font-family: "Inter", sans-serif;
	font-size: 9px;
	font-weight: 600;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--dl-gold-lt);
	background: rgba(10, 9, 7, .62);
	-webkit-backdrop-filter: blur(10px) saturate(140%);
	backdrop-filter: blur(10px) saturate(140%);
	border: 1px solid rgba(201, 168, 76, .5);
	box-shadow: 0 2px 12px rgba(0,0,0,.35);
	white-space: nowrap;
}
/* a small gold diamond as the marker */
.dl-photobadge::before {
	content: "";
	width: 4px; height: 4px;
	background: var(--dl-gold);
	transform: rotate(45deg);
	flex: none;
}
/* Recommended is the one worth shouting about — solid gold */
.dl-photobadge--recommended {
	color: #14100a;
	background: linear-gradient(135deg, #ffed8c, var(--dl-gold));
	border-color: transparent;
}
.dl-photobadge--recommended::before { background: rgba(20,16,10,.55); }
/* New gets the teal accent so it reads as different, not just another gold pill */
.dl-photobadge--new {
	color: var(--dl-teal-lt);
	border-color: rgba(15, 154, 154, .55);
}
.dl-photobadge--new::before { background: var(--dl-teal); }

@media (max-width: 600px) {
	.dl-photobadges { top: 8px; left: 8px; gap: 5px; }
	.dl-photobadge { font-size: 8px; padding: 5px 9px; letter-spacing: .14em; }
}

.dl-profile__head { margin-bottom: var(--sp-5); }
.dl-profile__name { margin: 0 0 var(--sp-3); }
.dl-profile__chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.dl-profile__intro { color: var(--dl-text); font-size: 1.02rem; }
.dl-profile__intro p:last-child { margin-bottom: 0; }

/* ── the compact luxury cards ── */
.dl-profile__cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
	gap: var(--sp-3);
	align-items: start;
}
.dl-card-lux {
	padding: var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	/* near-black, with a faint gold wash in the top corner so it has depth
	   without lifting away from the page */
	background:
		radial-gradient(120% 80% at 50% 0%, rgba(201,168,76,.05), transparent 60%),
		linear-gradient(180deg, #0c0c10, #08080a);
	position: relative;
	overflow: hidden;
}
/* faded gold hairline along the top edge — the detail that makes it read as designed */
.dl-card-lux::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--dl-gold), transparent);
	opacity: .5;
}
.dl-card-lux--wide { grid-column: 1 / -1; }
/* two cards sharing one column: areas + services run down the space beside the
   stats card, which is always the tallest of the three */
.dl-profile__stack { display: grid; gap: var(--sp-3); align-content: start; }
.dl-card-lux__title {
	font-size: 12px;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--dl-gold);
	font-family: "Inter", sans-serif;
	font-weight: 600;
	margin: 0 0 var(--sp-3);
	display: flex;
	align-items: center;
	gap: var(--sp-2);
}
.dl-card-lux__count {
	font-size: 10px;
	padding: 2px 8px;
	border-radius: 999px;
	background: rgba(201,168,76,.14);
	border: 1px solid rgba(201,168,76,.35);
	letter-spacing: .05em;
}
.dl-card-lux__note { font-size: .8rem; color: var(--dl-muted); margin: 12px 0 0; }
.dl-chip {
	display: inline-block; padding: 5px 13px; border-radius: 999px; font-size: 11px;
	letter-spacing: .1em; text-transform: uppercase; font-weight: 600;
	color: var(--dl-gold-lt); border: 1px solid rgba(201,168,76,.45); background: rgba(201,168,76,.07);
}
.dl-chip--teal { color: var(--dl-teal-lt); border-color: rgba(15,154,154,.5); background: rgba(15,154,154,.08); }

/* a chip that jumps to a section: small chevron so it reads as tappable */
.dl-chip--jump { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; }
.dl-chip--jump::after {
	content: "";
	width: 5px; height: 5px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg) translateY(-1px);
}
@media (hover: hover) {
	.dl-chip--jump:hover { background: rgba(15,154,154,.18); border-color: var(--dl-teal); }
}
.dl-chip--jump:active { background: rgba(15,154,154,.18); }

/* the duo card must clear the sticky header when jumped to */
#duo { scroll-margin-top: 100px; }
/* highlight briefly so it's obvious where you landed */
#duo:target { border-color: rgba(15,154,154,.6); animation: dl-flash 1.6s var(--dl-ease) 1; }
@keyframes dl-flash {
	0%   { box-shadow: 0 0 0 0 rgba(15,154,154,.35); }
	40%  { box-shadow: 0 0 0 5px rgba(15,154,154,.16); }
	100% { box-shadow: 0 0 0 0 rgba(15,154,154,0); }
}

/* ── rates table — the page's centrepiece, so it gets the full treatment ── */
.dl-rates {
	display: table;              /* never let a utility rule turn this into a block */
	width: 100%;
	border: 0;
	border-collapse: separate;
	border-spacing: 0;
	font-size: .92rem;
	table-layout: fixed;
	background: transparent;
}
/* Astra draws a full 1px border on every cell, which reads as white gridlines
   on a dark card. Strip them and keep only our own horizontal hairline. */
.dl-rates th,
.dl-rates td {
	padding: 13px 16px;
	text-align: right;
	background: transparent;
	border: 0 !important;
	border-bottom: 1px solid rgba(201,168,76,.1) !important;
}
.dl-rates tr { background: transparent !important; }
.dl-rates th:first-child,
.dl-rates td:first-child { text-align: left; width: 44%; }

.dl-rates thead th {
	font-family: "Inter", sans-serif;
	font-size: 9.5px;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--dl-gold);
	font-weight: 600;
	padding-top: 0;
	padding-bottom: 11px;
	border-bottom: 1px solid var(--dl-line-strong) !important;
}
.dl-rates tbody tr:last-child td { border-bottom: 0 !important; }

.dl-rates tbody td {
	color: var(--dl-cream);
	/* Cormorant sets figures old-style, so 3, 4, 5, 7 and 9 drop below the
	   baseline and a column of prices came out ragged — "£1050" worst of all.
	   Inter matches the extras card and keeps every digit on the line. Slightly
	   smaller than the serif was, because a sans at the same size reads heavier. */
	font-family: "Inter", sans-serif;
	font-size: .88rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0;
}
.dl-rates tbody tr:last-child td { border-bottom: 0; padding-bottom: 0; }
.dl-rates tbody tr { transition: background .2s var(--dl-ease); }
@media (hover: hover) { .dl-rates tbody tr:hover td { background: rgba(201,168,76,.045); } }

/* the duration label stays quiet so the numbers carry the row */
.dl-rates__dur {
	color: var(--dl-muted) !important;
	font-family: "Inter", sans-serif !important;
	font-size: .85rem !important;
	letter-spacing: .01em;
	white-space: nowrap;          /* "Dinner date (3hrs)" stays on one line */
}
/* the bracketed duration is secondary detail — smaller and dimmer */
.dl-rates__hrs {
	font-size: .78em;
	opacity: .72;
	letter-spacing: 0;
}
@media (max-width: 600px) {
	.dl-rates th, .dl-rates td { padding: 11px 8px; }
	.dl-rates th:first-child, .dl-rates td:first-child { width: 46%; }
	.dl-rates__dur { font-size: .78rem !important; }
	.dl-rates__hrs { font-size: .74em; }
	/* matches .dl-extras li at this breakpoint, so the two cards read as a pair */
	.dl-rates tbody td { font-size: .84rem; }
}

/* the headline hour, subtly lifted */
.dl-rates tbody tr:nth-child(1) td,
.dl-rates tbody tr:nth-child(2) td { color: var(--dl-gold-lt); }

.dl-na {
	color: rgba(255,255,255,.22);
	font-family: "Inter", sans-serif;
	font-size: .72rem;
	letter-spacing: .06em;
	text-transform: uppercase;
}

/* stats */
.dl-stats { margin: 0; }
.dl-stats__row { display: flex; justify-content: space-between; gap: 14px; padding: 9px 0; border-bottom: 1px solid var(--dl-line); }
.dl-stats__row:last-child { border-bottom: 0; }
.dl-stats dt { color: var(--dl-muted); font-size: .86rem; margin: 0; }
.dl-stats dd { color: var(--dl-cream); font-size: .86rem; margin: 0; text-align: right; }

/* extras — a price list, so it reads in columns with the figure hard right */
.dl-extras {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 0 var(--sp-5);
}
.dl-extras li {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 9px 0;
	border-bottom: 1px solid var(--dl-line);
	font-size: .88rem;
}
.dl-extras__label { color: var(--dl-text); }
/* dotted leader carries the eye across to the price without a heavy rule */
.dl-extras li::after {
	content: "";
	flex: 1 1 auto;
	height: 1px;
	margin-bottom: 3px;
	background-image: linear-gradient(90deg, var(--dl-line) 1px, transparent 1px);
	background-size: 4px 1px;
	background-repeat: repeat-x;
}
.dl-extras__price { order: 3; color: var(--dl-gold-lt); font-weight: 600; white-space: nowrap; }
@media (max-width: 600px) {
	.dl-extras { grid-template-columns: 1fr; }
	.dl-extras li { font-size: .84rem; padding: 8px 0; }
}

/* services — smaller than the area chips: there are three times as many of them,
   and they now sit in a half-width column */
.dl-likes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 5px; }
.dl-likes li {
	font-size: .68rem; border-radius: 5px;
	color: var(--dl-text); background: rgba(255,255,255,.03); border: 1px solid var(--dl-line);
	transition: border-color .25s var(--dl-ease), color .25s var(--dl-ease), background .25s var(--dl-ease);
}
/* padding lives on the link so the whole chip is the tap target */
.dl-likes li     { padding: 0; }
.dl-likes li a,
.dl-likes li     { display: inline-block; }
.dl-likes li a   { padding: 3px 8px; color: inherit; }
.dl-likes li:not(.is-link) { padding: 3px 8px; }
/* linked services read as interactive; unlinked ones stay quiet */
.dl-likes li.is-link { border-color: rgba(201,168,76,.28); }
/* hover/press is the shared ring above; the label keeps its resting colour */

/* reviews */
.dl-stars { display: inline-flex; gap: 2px; line-height: 1; }
.dl-star { color: rgba(255,255,255,.16); font-size: .95rem; }
.dl-star.is-on { color: var(--dl-gold); }
/* ==========================================================================
   WITHHELD PHOTO  — stands in wherever a listing's image would have gone
   Sized from the container rather than given dimensions of its own, so the
   same element works in a 3:4 card, a 40px area tile and the profile hero
   without a variant for each.
   ========================================================================== */
.dl-noimg {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	min-height: 90px;
	background:
		repeating-linear-gradient(135deg, rgba(255,255,255,.014) 0 8px, transparent 8px 16px),
		linear-gradient(180deg, #101014, #0a0a0d);
	border-bottom: 1px solid var(--dl-line);
}
.dl-noimg__txt {
	font-family: "Inter", sans-serif;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--dl-muted);
}
/* the tiles are 40px square, so the word cannot fit; the texture carries it */
.dl-cloud__pic .dl-noimg { min-height: 0; border-bottom: 0; }
.dl-cloud__pic .dl-noimg__txt { display: none; }

/* ==========================================================================
   JOURNAL FILTER  — search + category chips above the grouped journal
   Deliberately lighter than the listings filter: the journal is a reading
   surface, so this is a search box and a row of chips rather than a panel of
   selects. Same tokens throughout so the two read as the same family.
   ========================================================================== */
.dl-jfilter {
	display: grid;
	gap: var(--sp-3);
	margin: 0 0 var(--sp-5);
	padding: var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	background: linear-gradient(180deg, rgba(255,255,255,.02), rgba(255,255,255,.008));
}
.dl-jfilter__search input {
	width: 100%;
	padding: 12px 15px;
	border-radius: 999px;
}
.dl-jfilter__cats {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.dl-jchip {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 7px 14px;
	border-radius: 999px;
	border: 1px solid var(--dl-line);
	/* A <button> left with a transparent background keeps its native appearance,
	   and WebKit paints its own hover fill over it: the chips flashed system blue
	   on hover. Both halves are needed, the reset and an explicit fill below. */
	-webkit-appearance: none;
	appearance: none;
	background: transparent;
	font-family: "Inter", sans-serif;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--dl-muted);
	cursor: pointer;
	transition: color .25s var(--dl-ease), border-color .25s var(--dl-ease), background-color .25s var(--dl-ease);
}
.dl-jchip span {
	font-size: 10px;
	letter-spacing: .04em;
	opacity: .65;
}
.dl-jchip.is-on {
	color: var(--dl-gold-lt);
	border-color: rgba(201,168,76,.45);
	background: rgba(201,168,76,.09);
}
@media (hover: hover) {
	.dl-jchip:hover {
		color: var(--dl-cream);
		border-color: var(--dl-line-strong);
		background: rgba(201,168,76,.06);
	}
	.dl-jchip.is-on:hover {
		color: var(--dl-gold-lt);
		background: rgba(201,168,76,.14);
	}
}
.dl-jchip:active { border-color: rgba(15,154,154,.55); }
.dl-jfilter__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	min-height: 1px;
}
.dl-jfilter__count {
	margin: 0;
	font-size: .82rem;
	color: var(--dl-muted);
}
.dl-jfilter__clear,
.dl-jfilter__reset {
	padding: 0;
	border: 0;
	/* same native-chrome reset as the chips */
	-webkit-appearance: none;
	appearance: none;
	background: none;
	font-family: "Inter", sans-serif;
	font-size: .82rem;
	color: var(--dl-gold);
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}
@media (hover: hover) {
	.dl-jfilter__clear:hover,
	.dl-jfilter__reset:hover { color: var(--dl-gold-lt); background: none; }
}
/* a hidden group must not leave its grid gap behind */
.dl-journal__group[hidden] { display: none; }
@media (max-width: 600px) {
	.dl-jfilter { padding: var(--sp-3); }
	.dl-jchip   { font-size: 10px; padding: 6px 11px; }
}

/* ==========================================================================
   RECRUITMENT CARD  — closes a grid of escorts
   Inherits .dl-card, so the border, radius, gold hover sweep and pointer glow
   all come free and it reads as part of the grid. Only the surface changes:
   frosted instead of near-black, which is what marks it as not an escort.

   One backdrop-filter per grid. The stats block already documents why that cost
   is acceptable for a handful of static elements; this adds one more, and it
   never animates.
   ========================================================================== */
.dl-work {
	/* spans the row. As a single tile it lands alone at the end of the grid with
	   three empty cells beside it and reads as something that failed to load;
	   full width makes it a deliberate closing panel instead. */
	grid-column: 1 / -1;
	background: linear-gradient(180deg, rgba(246,241,228,.055), rgba(246,241,228,.014));
	-webkit-backdrop-filter: blur(16px) saturate(150%);
	backdrop-filter: blur(16px) saturate(150%);
	box-shadow: inset 0 1px 0 rgba(246,241,228,.08);
}
/* same reasoning as .dl-jstat: a 5%-alpha panel with no frost behind it is invisible */
@supports not ((-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px))) {
	.dl-work { background: rgba(20, 20, 26, .82); }
}
.dl-work__inner {
	display: flex;
	flex: 1;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 9px;
	min-height: 190px;
	padding: var(--sp-5) var(--sp-4);
	text-align: center;
	text-decoration: none;
}
.dl-work__eyebrow {
	font-family: "Inter", sans-serif;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--dl-gold);
}
.dl-work__title {
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: clamp(1.5rem, 2.3vw, 1.95rem);
	/* the descenders on this face clip against a background-clip:text box at 1 */
	line-height: 1.25;
	background: var(--dl-gold-grad);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}
.dl-work__copy {
	margin: 0;
	max-width: 52ch;
	font-size: .85rem;
	line-height: 1.55;
	color: var(--dl-muted);
}
.dl-work__cta {
	margin-top: 4px;
	padding: 7px 16px;
	border-radius: 999px;
	border: 1px solid rgba(201,168,76,.45);
	background: rgba(201,168,76,.07);
	font-family: "Inter", sans-serif;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--dl-gold-lt);
	transition: background-color .3s var(--dl-ease), border-color .3s var(--dl-ease);
}
@media (hover: hover) {
	.dl-work:hover .dl-work__cta { background: rgba(201,168,76,.18); border-color: var(--dl-line-strong); }
}
/* touch, via the same class the cards use */
.dl-work.is-pressed .dl-work__cta { background: rgba(201,168,76,.18); border-color: var(--dl-line-strong); }
@media (max-width: 600px) {
	.dl-work__inner { min-height: 200px; padding: var(--sp-4) var(--sp-3); }
	.dl-work__copy  { font-size: .8rem; }
}

.dl-reviews__avg {
	display: flex; align-items: center; gap: 10px;
	margin: 0 0 var(--sp-3); padding-bottom: var(--sp-3);
	border-bottom: 1px solid var(--dl-line);
}
.dl-reviews__avg strong { color: var(--dl-cream); font-size: 1.05rem; }
.dl-reviews__avg span   { color: var(--dl-muted); font-size: .82rem; }
.dl-reviews { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.dl-review {
	padding: var(--sp-3);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: rgba(255,255,255,.018);
	transition: border-color .3s var(--dl-ease), background-color .3s var(--dl-ease);
}
/* A review is not a link, so this is feedback rather than affordance: the teal
   edge the rest of the site uses, and nothing that implies it can be clicked. */
@media (hover: hover) {
	.dl-review:hover {
		border-color: rgba(15,154,154,.55);
		background: rgba(255,255,255,.045);
	}
}
/* Touch never matches (hover: hover), and a propagated :active does not repaint a
   static <li> reliably on iOS, so the same class the cards use carries it here. */
.dl-review.is-pressed {
	border-color: rgba(15,154,154,.55);
	background: rgba(255,255,255,.045);
}
.dl-review__head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 7px; }
.dl-review__head strong { color: var(--dl-cream); font-size: .9rem; }
.dl-review__head time   { color: var(--dl-muted); font-size: .76rem; margin-left: auto; }
.dl-review p { margin: 0; font-size: .9rem; color: var(--dl-text); }
.dl-reviews__none { color: var(--dl-muted); font-size: .9rem; margin: 0; }
.dl-reviews__cta  { margin: var(--sp-4) 0 0; }

/* ── confirmation after a review is posted ──
   Teal rather than gold: gold is the resting accent all over this card, and a
   confirmation needs to read as something that just happened. */
.dl-reviewsent {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	margin: var(--sp-4) 0 0;
	padding: var(--sp-3) var(--sp-4);
	border: 1px solid var(--dl-teal);
	border-radius: var(--dl-radius);
	background: rgba(15, 154, 154, .10);
}
.dl-reviewsent__tick {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px; height: 26px;
	border-radius: 999px;
	border: 1px solid var(--dl-teal);
	color: var(--dl-teal-lt);
	font-size: .8rem;
	line-height: 1;
}
.dl-reviewsent strong { display: block; color: var(--dl-teal-lt); font-size: .98rem; margin-bottom: 3px; }
.dl-reviewsent p { margin: 0; font-size: .86rem; color: var(--dl-text); line-height: 1.5; }

/* the same panel, for a review that was turned away */
.dl-reviewerr {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	margin: var(--sp-4) 0 0;
	padding: var(--sp-3) var(--sp-4);
	border: 1px solid rgba(214, 96, 77, .55);
	border-radius: var(--dl-radius);
	background: rgba(214, 96, 77, .10);
}
.dl-reviewerr__mark {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px; height: 26px;
	border-radius: 999px;
	border: 1px solid rgba(214, 96, 77, .55);
	color: #e8907c;
	font-size: .82rem;
	font-weight: 600;
	line-height: 1;
}
.dl-reviewerr strong { display: block; color: #e8907c; font-size: .98rem; margin-bottom: 3px; }
.dl-reviewerr p { margin: 0; font-size: .86rem; color: var(--dl-text); line-height: 1.5; }

/* ── recently viewed ── */
/*
 * The rule lives inside this section rather than before it, so it disappears
 * along with the section when there is no history to show — a divider floating
 * on its own would be worse than no section at all. That means the section's own
 * top padding was stacking above the rule, so it is dropped and the spacing is
 * carried underneath instead.
 */
#dl-recent { padding-top: 0; }
#dl-recent > .dl-rule { margin-bottom: var(--sp-6); }

.dl-recent__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sp-3);
	margin-bottom: var(--sp-4);
}
.dl-recent__head h2 { margin: 0; }
.dl-recent__clear {
	flex: none;
	margin-top: 4px;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background: none;
	color: var(--dl-muted);
	font-family: inherit;
	font-size: .74rem;
	letter-spacing: .06em;
	/* Symmetric, and this is the correct value on touch: measured on an iPhone
	   the ink sits 9.60px from the top and 9.60px from the bottom, dead centre.
	   An asymmetric nudge was tried globally once and put it a pixel low here,
	   which is why the correction below is scoped rather than applied to both. */
	padding: 7px 15px;
	cursor: pointer;
	transition: color .25s var(--dl-ease), border-color .25s var(--dl-ease), background-color .25s var(--dl-ease);
}
/*
 * Optical centring, desktop only.
 *
 * The same label renders differently on the two engines. Measured ink position
 * inside the button, both at 27.83px tall with symmetric 7px padding:
 *
 *   iPhone 13      above 9.60px   below  9.60px   dead centre
 *   Desktop 1440   above 8.64px   below 10.56px   1.92px high
 *
 * So the fix is 2px of shift, and it belongs only where the problem is. Gated
 * on the pointer rather than a width, because this follows the rendering path
 * rather than the viewport: a touch tablet at 1024px should keep the value
 * that is already correct for it. This is the same guard the hover styles
 * below use, so the two stay together.
 */
@media (hover: hover) and (pointer: fine) {
	.dl-recent__clear { padding-top: 8px; padding-bottom: 6px; }
}

@media (hover: hover) {
	.dl-recent__clear:hover { color: var(--dl-gold-lt); border-color: var(--dl-gold); background-color: rgba(201,168,76,.07); }
}
.dl-recent__clear:active { color: var(--dl-gold-lt); border-color: var(--dl-gold); background-color: rgba(201,168,76,.1); }

/* ── the review form, inline in the reviews card ──
   Sat in a panel of its own so it still reads as a distinct thing to fill in
   rather than more of the card it opens inside. No fixed positioning anywhere
   in here, which is the entire point of it. */
.dl-reviewform {
	margin-top: var(--sp-4);
	padding: var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	background: rgba(255, 255, 255, .022);
}
.dl-reviewform__title {
	margin: 0 0 6px;
	font-size: 1.15rem;
}
.dl-reviewform__sub {
	margin: 0 0 var(--sp-4);
	color: var(--dl-muted);
	font-size: .85rem;
}
@media (max-width: 782px) {
	.dl-reviewform { padding: var(--sp-3); }
	.dl-reviewform__title { font-size: 1.05rem; }
}

/* ==========================================================================
   REVIEW RAIL (homepage) + REVIEWS PAGE
   ========================================================================== */

/*
 * The rail sits outside .dl-shell so it can bleed to both edges — a row that
 * stops dead at the shell looks truncated rather than scrollable. The track
 * then re-creates the shell gutter as padding, so card one still lines up with
 * the heading above it while card five runs off the edge as a hint there's more.
 */
.dl-rail {
	position: relative;
	margin-top: var(--sp-4);
}

/* --- rail arrows --- */
.dl-rail__nav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 4;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background: rgba(12, 12, 16, .92);
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
	color: var(--dl-gold);
	cursor: pointer;
	transition: border-color .25s var(--dl-ease), background-color .25s var(--dl-ease), opacity .25s var(--dl-ease);
}
.dl-rail__nav svg { width: 20px; height: 20px; }
/* inside the shell gutter, so they sit over the cards rather than the page edge */
.dl-rail__nav--prev { left: max(10px, calc((100% - var(--dl-shell)) / 2 - 4px)); }
.dl-rail__nav--next { right: max(10px, calc((100% - var(--dl-shell)) / 2 - 4px)); }
@media (hover: hover) {
	.dl-rail__nav:hover { border-color: var(--dl-gold); background: rgba(24, 20, 8, .95); }
}
.dl-rail__nav:active { border-color: var(--dl-gold); }
.dl-rail__nav:focus-visible { outline: 2px solid var(--dl-gold); outline-offset: 2px; }
/* at either end there is nothing to scroll to, so it stops being a control */
.dl-rail__nav[disabled] { opacity: 0; pointer-events: none; }
.dl-rail__track {
	list-style: none;
	margin: 0;
	display: flex;
	gap: var(--sp-3);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scroll-padding-inline: clamp(18px, 4vw, 34px);
	padding-block: 4px var(--sp-2);
	padding-inline: max(
		clamp(18px, 4vw, 34px),
		calc((100% - var(--dl-shell)) / 2 + clamp(18px, 4vw, 34px))
	);
}
/* a visible bar under a row of dark cards reads as a broken element */
.dl-rail__track { scrollbar-width: none; -ms-overflow-style: none; }
.dl-rail__track::-webkit-scrollbar { display: none; }
.dl-rail__item {
	flex: 0 0 clamp(268px, 78vw, 330px);
	scroll-snap-align: start;
	display: flex;
}
/*
 * The card fills its slot rather than sizing to its own content.
 *
 * Without this the card is a content-sized flex child, and the only thing with
 * any width inside it is the photo — so its width came from the image's
 * intrinsic size. Before an image decoded there was nothing to measure and the
 * card collapsed to the width of the escort's name, then snapped out to full
 * width as the photo arrived. Measured on the live profile rail: items a
 * uniform 172px, cards 72, 95, 172, 65, 172, 71 depending purely on which
 * photos had decoded.
 *
 * min-width: 0 because a flex child will not shrink below its content
 * otherwise, which is what a long name would do to the row.
 */
.dl-rail__item > .dl-card {
	width: 100%;
	min-width: 0;
}

/* --- recently viewed, rail variant (profile pages) ---
 * Deliberately smaller than a grid listing card. This row sits directly under
 * "more escorts in <area>", which is a full-size four-card grid, and two rows
 * of equally weighted cards read as one long block rather than two separate
 * lists. Shrinking the second one is what tells them apart.
 *
 * ~40vw means two and a half cards fit a phone: the cut-off third is the
 * affordance that says the row scrolls, which a row of exactly two would not.
 */
.dl-rail__item--mini { flex: 0 0 clamp(134px, 40vw, 172px); }

.dl-card--mini .dl-card__body    { padding: var(--sp-3); gap: 2px; }
.dl-card--mini .dl-card__title   { font-size: .95rem; }
.dl-card--mini .dl-listing__meta { font-size: .74rem; }
.dl-card--mini .dl-listing__price{ font-size: .8rem; }

/*
 * Less gold on the small cards.
 *
 * Measured identical to the grid cards on every gold-bearing property: same
 * border rgba(201,168,76,.16), same wash, same ::before at opacity 0, no
 * box-shadow. Nothing extra was ever added here. But the same 1px edge around
 * a 134px card encloses a third of the area, and five of them sit in view at
 * once, so the same values read considerably hotter. Scaling the gold with the
 * card is what keeps the two rows looking like one family.
 */
.dl-card--mini {
	border-color: rgba(201, 168, 76, .09);
	background:
		radial-gradient(120% 80% at 50% 100%, rgba(201, 168, 76, .025), transparent 60%),
		linear-gradient(180deg, #0c0c10, #08080a);
}

/*
 * Headroom for the hover lift.
 *
 * .dl-rail__track scrolls horizontally, and overflow-x:auto makes it a scroll
 * container in BOTH axes, so it clips vertically too. With only 4px of top
 * padding the 8px hover lift pushed the card 4px past the scrollport and it
 * was visibly sliced along its top edge. Measured: card.top 278.34 against a
 * scrollport top of 282.34. 16px leaves 8px clear once lifted.
 */
.dl-recent--rail .dl-rail__track { padding-block: 16px var(--sp-3); }

/* the rule lives inside the section so it cannot show above an empty row */
.dl-recent--rail { padding-top: 0; }
.dl-recent--rail > .dl-rule { margin-bottom: var(--sp-6); }
.dl-recent--rail h2 { margin: 0; }

.dl-rvcard {
	display: flex;
	flex-direction: column;
	gap: 10px;
	width: 100%;
	padding: var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	background:
		radial-gradient(120% 80% at 50% 0%, rgba(201,168,76,.05), transparent 60%),
		linear-gradient(180deg, #0c0c10, #08080a);
	transition: border-color .3s var(--dl-ease), transform .3s var(--dl-ease-out);
}
@media (hover: hover) {
	.dl-rvcard:hover { border-color: var(--dl-gold); transform: translateY(-3px); }
}
/* photo + name on the left, stars pinned right, all on one baseline */
.dl-rvcard__head {
	display: flex;
	align-items: center;
	gap: 10px;
	padding-bottom: 11px;
	border-bottom: 1px solid var(--dl-line);
}
.dl-rvcard__head .dl-stars { flex: none; margin-left: auto; }
.dl-rvcard__head .dl-star { font-size: .82rem; }

.dl-rvcard__who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.dl-rvcard__img {
	flex: none;
	width: 42px; height: 42px;
	border-radius: 999px;
	overflow: hidden;
	border: 1px solid var(--dl-line);
}
/* The crop is square and the source is a 2:3 portrait, so a centred crop lands
   on the body. Biased up to the same 12% the duo tiles and combo faces use. */
.dl-rvcard__img img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%; display: block; }
.dl-rvcard__id { display: grid; gap: 1px; min-width: 0; }
.dl-rvcard__id strong {
	color: var(--dl-cream); font-size: .92rem; line-height: 1.2;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dl-rvcard__id span {
	color: var(--dl-muted); font-size: .72rem;
	letter-spacing: .04em;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/*
 * Every card is the height of the tallest in the row, so the quote takes the
 * slack and the byline stays pinned to the bottom edge. Clamped to four lines
 * so one long review cannot set the height for all of them.
 */
.dl-rvcard__text {
	margin: 0;
	flex: 1 1 auto;
	font-size: .9rem;
	line-height: 1.55;
	color: var(--dl-text);
	display: -webkit-box;
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* the byline closes the card; the head already carries the rule above the quote */
.dl-rvcard__by {
	margin: 0;
	display: flex; align-items: baseline; gap: 8px;
	font-size: .76rem; color: var(--dl-muted);
	padding-top: 10px;
	border-top: 1px solid var(--dl-line);
}
.dl-rvcard__by time { margin-left: auto; font-variant-numeric: tabular-nums; }

/* the last card in the rail: a way through, not a review */
.dl-rvcard--all {
	align-items: flex-start;
	justify-content: flex-start;
	text-align: left;
	border-style: dashed;
}
.dl-rvcard__alltitle {
	color: var(--dl-gold-lt);
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.35rem;
	line-height: 1.15;
}
.dl-rvcard__allsub { color: var(--dl-muted); font-size: .82rem; line-height: 1.5; }

/* the figures: number large, label small underneath, divided rather than boxed */
.dl-rvcard__stats {
	list-style: none;
	margin: var(--sp-2) 0 0;
	padding: var(--sp-3) 0 0;
	border-top: 1px solid var(--dl-line);
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-4);
	width: 100%;
}
.dl-rvcard__stats li { display: grid; gap: 1px; }
.dl-rvcard__stats strong {
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.5rem;
	line-height: 1;
	color: var(--dl-cream);
}
.dl-rvcard__stats span {
	font-size: .68rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--dl-muted);
}
.dl-rvcard__allicon {
	display: inline-flex; align-items: center; justify-content: center;
	width: 40px; height: 40px;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	color: var(--dl-gold);
	transition: transform .3s var(--dl-ease-out), border-color .3s var(--dl-ease);
	/* The arrow is first in the markup so it is announced with the link rather
	   than after the description. Visually it belongs in the corner, so order
	   sends it to the end, margin-top: auto drops it to the bottom of the card
	   and align-self carries it over to the right. */
	order: 2;
	margin-top: auto;
	align-self: flex-end;
	flex: none;
}
@media (hover: hover) {
	.dl-rvcard--all:hover .dl-rvcard__allicon { transform: translateX(4px); border-color: var(--dl-gold); }
}

/* ── sitemap ── */
.dl-sitemap__grid { display: grid; gap: var(--sp-4); }
@media (min-width: 700px)  { .dl-sitemap__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .dl-sitemap__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* the companion list is the long one, so it runs the full width and columns internally */
.dl-sitemap__block--wide { grid-column: 1 / -1; }
.dl-sitemap__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.dl-sitemap__block--wide .dl-sitemap__list {
	grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
	gap: 9px var(--sp-4);
}
.dl-sitemap__list li { display: flex; align-items: baseline; gap: 7px; }
.dl-sitemap__list a {
	font-size: .88rem;
	color: var(--dl-muted);
	transition: color .25s var(--dl-ease);
}
@media (hover: hover) { .dl-sitemap__list a:hover { color: var(--dl-teal-lt); } }
.dl-sitemap__list a:active { color: var(--dl-teal-lt); }
.dl-sitemap__xml { margin: var(--sp-5) 0 0; font-size: .82rem; color: var(--dl-muted); }
.dl-sitemap__xml a { color: var(--dl-gold-lt); }

/* ── link to us ── */
.dl-linkgrid { display: grid; gap: var(--sp-4); }
@media (min-width: 900px) { .dl-linkgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dl-linkcard__note { margin: 0 0 var(--sp-3); font-size: .88rem; color: var(--dl-muted); }
.dl-linkcard__label {
	margin: 0 0 7px;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--dl-gold);
}
.dl-linkcard__preview {
	padding: var(--sp-3);
	margin-bottom: var(--sp-3);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: rgba(255,255,255,.018);
	font-size: .9rem;
	color: var(--dl-text);
}
.dl-linkcard__code {
	width: 100%;
	padding: var(--sp-3);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: rgba(0,0,0,.35);
	color: var(--dl-cream);
	color-scheme: dark;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: .8rem;
	line-height: 1.5;
	resize: vertical;
	/* the whole point is that it is easy to grab */
	cursor: text;
}
.dl-linkcard__code:focus { outline: none; border-color: var(--dl-gold); }
.dl-linknote { margin-top: var(--sp-4); }
.dl-linknote p { margin: 0 0 var(--sp-2); font-size: .9rem; color: var(--dl-text); }
.dl-linknote p:last-child { margin-bottom: 0; }

/* ── reviews page: one card per companion ── */
.dl-rvgroups { display: grid; gap: var(--sp-4); }
.dl-rvgroup {
	padding: var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	background:
		radial-gradient(120% 80% at 50% 0%, rgba(201,168,76,.05), transparent 60%),
		linear-gradient(180deg, #0c0c10, #08080a);
}
.dl-rvgroup__head {
	display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3);
	padding-bottom: var(--sp-3);
	margin-bottom: var(--sp-3);
	border-bottom: 1px solid var(--dl-line);
}
.dl-rvgroup__who { display: flex; align-items: center; gap: 13px; min-width: 0; }
.dl-rvgroup__img {
	flex: none;
	width: 58px; height: 58px;
	border-radius: 999px;
	overflow: hidden;
	border: 1px solid var(--dl-line);
}
.dl-rvgroup__img img {
	width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%; display: block;
	transition: transform .55s var(--dl-ease-out);
}
.dl-rvgroup__id { display: grid; min-width: 0; }
.dl-rvgroup__id strong { color: var(--dl-cream); font-size: 1.08rem; transition: color .25s var(--dl-ease); }
.dl-rvgroup__id span   { color: var(--dl-muted); font-size: .8rem; transition: color .25s var(--dl-ease); }

/*
 * Hover on the reviews page.
 *
 * The photo, the name and the area are all one <a class="dl-rvgroup__who">, so
 * a single rule moves the three of them together rather than lighting up
 * whichever one the pointer happens to be over. That is what makes the header
 * read as one link instead of three neighbouring things.
 *
 * The review below it is NOT a link, so it warms its border and surface rather
 * than turning gold or lifting. Reserving the gold and the movement for things
 * that actually go somewhere keeps the signal honest.
 *
 * Behind (hover: hover) so a tap does not leave a stuck hover state on touch.
 */
@media (hover: hover) {
	.dl-rvgroup__who:hover .dl-rvgroup__id strong { color: var(--dl-gold-lt); }
	.dl-rvgroup__who:hover .dl-rvgroup__id span   { color: var(--dl-text); }
	.dl-rvgroup__who:hover .dl-rvgroup__img       { border-color: var(--dl-gold); }
	.dl-rvgroup__who:hover .dl-rvgroup__img img   { transform: scale(1.07); }

	.dl-rvitem:hover {
		border-color: var(--dl-line-strong);
		background: rgba(255, 255, 255, .032);
	}
}

/*
 * Touch gets the same confirmation, without the state sticking afterwards.
 *
 * .dl-rvitem is an <li> rather than a link, and iOS only applies :active to
 * non-form elements once the document carries a touch listener. initTouchActive()
 * attaches an empty passive one for exactly this reason, so these fire.
 */
.dl-rvgroup__who:active .dl-rvgroup__id strong { color: var(--dl-gold-lt); }
.dl-rvgroup__who:active .dl-rvgroup__img { border-color: var(--dl-gold); }
.dl-rvitem:active {
	border-color: var(--dl-line-strong);
	background: rgba(255, 255, 255, .032);
}
.dl-rvgroup__score {
	margin: 0 0 0 auto;
	display: flex; align-items: center; gap: 9px;
	font-size: .82rem; color: var(--dl-muted);
}
.dl-rvgroup__score strong { color: var(--dl-cream); font-size: 1rem; }
.dl-rvgroup__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.dl-rvitem {
	padding: var(--sp-3);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: rgba(255,255,255,.018);
	transition: border-color .25s var(--dl-ease), background-color .25s var(--dl-ease);
}
.dl-rvitem__head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 7px; }
.dl-rvitem__head strong { color: var(--dl-cream); font-size: .9rem; }
.dl-rvitem__head time   { color: var(--dl-muted); font-size: .76rem; margin-left: auto; }
.dl-rvitem p { margin: 0; font-size: .9rem; line-height: 1.55; color: var(--dl-text); }
.dl-rvgroup__cta { margin: var(--sp-4) 0 0; }
/* the empty state stands alone on the page rather than sitting in a card, so its
   button centres under the message instead of hanging off the left edge */
.dl-empty + .dl-rvgroup__cta { text-align: center; }
@media (max-width: 600px) {
	.dl-rvgroup__score { margin-left: 0; width: 100%; }
}

/* ── modal ── */
/*
 * Locked with overflow alone, not position: fixed.
 *
 * The fixed-body lock is the usual way to hold the page still, but it has to
 * save the scroll offset, re-apply it as a negative top, then scroll back on
 * close — and on iOS every one of those steps is a visible jump. Taking the
 * whole mechanism out is what stopped the form lurching about. The overlay is
 * fixed and covers the page anyway, and it contains its own overscroll, so
 * there is nothing behind it left to scroll.
 */
body.dl-locked { overflow: hidden; }
/* Astra's back-to-top floats above everything and landed on the form, right
   beside Cancel. There is nothing to scroll back to while the page is locked
   behind the modal, so it has no job here. */
body.dl-locked #ast-scroll-top { display: none !important; }
.dl-modal { position: fixed; inset: 0; z-index: 999; display: flex; align-items: center; justify-content: center; padding: var(--sp-4); }
.dl-modal[hidden] { display: none; }
.dl-modal__backdrop {
	position: absolute; inset: 0;
	background: rgba(4,4,6,.82);
	-webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.dl-modal__panel {
	position: relative;
	width: min(520px, 100%);
	max-height: 86vh;
	/* dvh tracks Safari's collapsing toolbars; vh is the LARGE viewport, so a
	   panel sized in vh runs under the toolbar and loses its submit button.
	   Declared separately so browsers without dvh keep the line above. */
	max-height: min(86vh, 86dvh);
	overflow-y: auto;
	overscroll-behavior: contain;      /* stop the page scrolling once it bottoms out */
	-webkit-overflow-scrolling: touch;
	padding: var(--sp-5);
	border: 1px solid var(--dl-line-strong);
	border-radius: var(--dl-radius);
	background:
		radial-gradient(120% 70% at 50% 0%, rgba(201,168,76,.07), transparent 60%),
		linear-gradient(180deg, #0d0d11, #08080a);
	box-shadow: 0 30px 80px rgba(0,0,0,.7);
}
/* circular, in the same hairline-on-near-black language as the pager arrows and
   the count pills, so it reads as part of the set rather than a bare glyph */
.dl-modal__x {
	position: absolute; top: 12px; right: 12px;
	width: 36px; height: 36px;
	display: flex; align-items: center; justify-content: center;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background: rgba(255,255,255,.04);
	background-clip: padding-box;
	cursor: pointer;
	color: var(--dl-muted); font-size: 1.25rem; line-height: 1;
	transition: color .25s var(--dl-ease), border-color .25s var(--dl-ease), background .25s var(--dl-ease);
}
@media (hover: hover) {
	.dl-modal__x:hover { color: var(--dl-gold-lt); border-color: var(--dl-gold); background: rgba(201,168,76,.1); }
}
.dl-modal__x:active { color: var(--dl-gold-lt); border-color: var(--dl-gold); background: rgba(201,168,76,.14); }
.dl-modal__title { margin: 0 0 6px; font-size: clamp(1.3rem, 3.4vw, 1.7rem); }
.dl-modal__sub   { margin: 0 0 var(--sp-4); color: var(--dl-muted); font-size: .85rem; }

/* ── form ── */
.dl-form__row { margin-bottom: var(--sp-3); }
.dl-form__label {
	display: block; margin-bottom: 6px;
	font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
	color: var(--dl-gold); font-weight: 600;
}
.dl-form input[type="text"],
.dl-form input[type="email"],
.dl-form textarea {
	width: 100%;
	padding: 11px 13px;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: rgba(255,255,255,.03);
	color: var(--dl-cream);
	font-family: inherit;
	font-size: 16px;                 /* under 16px and iOS zooms the page on focus */
	transition: border-color .25s var(--dl-ease), background .25s var(--dl-ease);
}
.dl-form textarea { resize: vertical; min-height: 110px; }
.dl-form input:focus,
.dl-form textarea:focus { outline: none; border-color: var(--dl-gold); background: rgba(201,168,76,.05); }
.dl-form__hint { display: block; margin-top: 5px; font-size: .74rem; color: var(--dl-muted); }
/* honeypot: off-screen rather than display:none, which some bots skip */
.dl-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.dl-form__actions { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-4); flex-wrap: wrap; }
/* secondary action: no chrome at rest, a quiet pill on hover. The border is
   transparent rather than absent so nothing shifts when it appears. */
.dl-modal__cancel,
.dl-reviewform__cancel {
	border: 1px solid transparent;
	border-radius: 999px;
	background: none;
	background-clip: padding-box;
	cursor: pointer;
	color: var(--dl-muted);
	font-size: .85rem;
	padding: 10px 20px;
	transition: color .25s var(--dl-ease), border-color .25s var(--dl-ease), background .25s var(--dl-ease);
}
@media (hover: hover) {
	.dl-modal__cancel:hover,
	.dl-reviewform__cancel:hover { color: var(--dl-cream); border-color: var(--dl-line); background: rgba(255,255,255,.05); }
}
.dl-modal__cancel:active,
.dl-reviewform__cancel:active { color: var(--dl-cream); border-color: var(--dl-line-strong); background: rgba(255,255,255,.08); }

/* star picker: 5 to 1 in the markup, reversed here so 1 reads leftmost and
   `:checked ~ label` can fill everything below the star that was picked */
/* Label, stars and the read-back on one line. Stacked, this row took as much
   height as a text field for a control that is five taps wide. */
.dl-form__row--rate {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 4px 12px;
}
/* the label keeps its own line: label + stars + read-back together overflow a
   phone, and letting them wrap put the pieces in a different order at each width */
.dl-form__row--rate .dl-form__label { flex: 1 0 100%; margin-bottom: 2px; }
.dl-rate__value {
	font-size: .78rem;
	color: var(--dl-muted);
	font-variant-numeric: tabular-nums;   /* the readout must not jitter as it changes */
}
.dl-rate__value.is-set { color: var(--dl-gold-lt); }

/* Boxed like every other field in this form. Five bare glyphs floating on the
   panel did not read as something you were meant to fill in. */
.dl-rate {
	display: inline-flex;
	flex-direction: row-reverse;
	justify-content: flex-end;
	gap: 2px;
	position: relative;
	padding: 5px 10px;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: rgba(255,255,255,.03);
}
.dl-rate:focus-within { border-color: var(--dl-gold); }

/*
 * Asking for the rating, on the control itself.
 *
 * This is what replaces Safari's "Select one of these options" bubble, which
 * parked a white speech balloon over the stars — the one thing it was asking
 * you to look at. The box shakes once, turns the warning colour and holds it
 * until a star is picked, so the answer is where the question was asked.
 */
@keyframes dl-rate-nudge {
	0%, 100% { transform: translateX(0); }
	18%      { transform: translateX(-5px); }
	38%      { transform: translateX(5px); }
	58%      { transform: translateX(-3px); }
	78%      { transform: translateX(2px); }
}
.dl-rate.is-missing {
	animation: dl-rate-nudge .42s var(--dl-ease);
	border-color: rgba(214, 96, 77, .85);
	background: rgba(214, 96, 77, .08);
}
.dl-rate.is-missing label { color: rgba(214, 96, 77, .55); }

/* the same treatment for a text field that was left empty */
.dl-form input.is-missing,
.dl-form textarea.is-missing {
	animation: dl-rate-nudge .42s var(--dl-ease);
	border-color: rgba(214, 96, 77, .85) !important;
	background: rgba(214, 96, 77, .08) !important;
}
/* the shake is the flourish, the colour is the message — keep the colour */
@media (prefers-reduced-motion: reduce) {
	.dl-rate.is-missing { animation: none; }
}
/* 1px rather than 0, and anchored to .dl-rate: still invisible, but it stays
   focusable and any native validation message lands on the stars rather than
   somewhere else on the page */
.dl-rate input { position: absolute; opacity: 0; width: 1px; height: 1px; left: 0; bottom: 0; }
/* the asterisk that marks the rating as required */
.dl-form__req { color: var(--dl-gold); margin-left: 2px; }
.dl-rate label {
	cursor: pointer;
	font-size: 1.55rem;
	line-height: 1;
	/* An unlit star at 18% white was all but invisible on this panel. Gold at
	   low alpha stays part of the palette and can actually be seen, so you can
	   tell there are five of them before touching anything. */
	color: rgba(201, 168, 76, .3);
	transition: color .15s var(--dl-ease), transform .15s var(--dl-ease-out);
	padding: 2px 1px;
}
/* the chosen star lifts slightly, so the boundary is readable at a glance
   rather than resting on a colour difference alone */
.dl-rate input:checked + label { transform: scale(1.14); }
.dl-rate input:checked ~ label { color: var(--dl-gold); }
@media (hover: hover) {
	.dl-rate label:hover,
	.dl-rate label:hover ~ label { color: var(--dl-gold-lt); }
}
/* rounded to match the star, rather than a square box cutting across it */
.dl-rate input:focus-visible + label { outline: 1px solid var(--dl-gold); outline-offset: 1px; border-radius: 3px; }

@media (max-width: 600px) {
	/* a sheet that clears the screen edges rather than a full-bleed slab, and
	   sits above the home indicator */
	/*
	 * The overlay scrolls, the panel does not.
	 *
	 * This was a sheet pinned to the bottom with the panel scrolling inside it.
	 * Two problems on a phone: the keyboard covers the bottom of the screen,
	 * which is exactly where the sheet lived, and a scrolling box inside a fixed
	 * box is the combination iOS handles worst. Anchored to the top with the
	 * overlay itself doing the scrolling, the fields you are typing into are in
	 * the upper half where the keyboard never reaches, and there is only one
	 * scroller to get confused.
	 */
	.dl-modal {
		padding: 10px;
		align-items: flex-start;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior: contain;
	}
	.dl-modal__panel {
		width: 100%;
		max-height: none;              /* let it be as tall as it needs; the overlay scrolls */
		overflow: visible;
		margin-bottom: calc(env(safe-area-inset-bottom, 0px) + 40vh);   /* room to scroll past the keyboard */
		border-radius: var(--dl-radius);
		padding: var(--sp-4) 16px;
	}
	.dl-modal__title { font-size: 1.25rem; padding-right: 44px; }   /* clear of the close button */
	.dl-modal__sub { margin-bottom: var(--sp-3); font-size: .8rem; }
	.dl-form__row { margin-bottom: 12px; }
	.dl-form textarea { min-height: 88px; }
}

/* booking card */
.dl-booking { text-align: center; border-color: var(--dl-line-strong); }
.dl-booking__price { margin: 0 0 16px; color: var(--dl-muted); font-size: .8rem; letter-spacing: .1em; text-transform: uppercase; }
.dl-booking__price strong { display: block; font-family: "Cormorant Garamond", Georgia, serif; font-size: 2.4rem; color: var(--dl-gold-lt); letter-spacing: 0; margin: 2px 0; }
.dl-booking .dl-btn { width: 100%; margin-bottom: 9px; }
.dl-booking__facts { list-style: none; margin: 16px 0 0; padding: 16px 0 0; border-top: 1px solid var(--dl-line); }
.dl-booking__facts li { display: flex; justify-content: space-between; padding: 5px 0; font-size: .85rem; }
.dl-booking__facts span { color: var(--dl-muted); }
.dl-booking__facts strong { color: var(--dl-cream); font-weight: 500; }
.dl-booking__guide { margin: 14px 0 0; font-size: .8rem; color: var(--dl-muted); }

/* ── guide pages: carded sections + sticky contents rail ── */
.dl-guide__grid { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: var(--sp-5); align-items: start; }
@media (max-width: 900px) { .dl-guide__grid { grid-template-columns: 1fr; } }

.dl-guide__rail { position: sticky; top: 96px; }
@media (max-width: 900px) { .dl-guide__rail { position: static; } }
.dl-guide__toc { margin: 0; padding-left: 1.1em; }
.dl-guide__toc li { margin-bottom: 8px; font-size: .86rem; line-height: 1.4; }
.dl-guide__toc li::marker { color: var(--dl-gold); font-size: .8em; }
.dl-guide__toc a { color: var(--dl-text); }
.dl-guide__toc a:hover { color: var(--dl-gold-lt); }

.dl-guide__intro { margin-bottom: var(--sp-4); font-size: 1.06rem; }
.dl-guide__body { display: grid; gap: var(--sp-3); }
.dl-guide__card { scroll-margin-top: 100px; }
/* headings are the jump targets, so they need the same clearance */
.dl-guide__card h2[id], .dl-article h2[id], .dl-article h3[id] { scroll-margin-top: 100px; }
/* the card owns its padding, so the first and last children shouldn't add their own */
.dl-guide__card .dl-article > h2:first-child { margin-top: 0; }
.dl-guide__card .dl-article > *:first-child { margin-top: 0; }
.dl-guide__card .dl-article > *:last-child  { margin-bottom: 0; }
/* callouts sit inside a card already, so soften them rather than nesting a second box */
.dl-guide__card .dl-callout { margin: var(--sp-4) 0; background: rgba(201,168,76,.05); border-color: var(--dl-line); }
.dl-guide__card .dl-callout:last-child { margin-bottom: 0; }
/* headings after the first need air above, but not a full article-sized gap */
.dl-guide__card .dl-article h3 { margin-top: var(--sp-5); }

.dl-guide__more { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-3); }
.dl-guide__morecard {
	display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-3);
	text-decoration: none; transition: border-color .25s var(--dl-ease), transform .3s var(--dl-ease-out);
}
.dl-guide__morecard strong { font-family: "Cormorant Garamond", Georgia, serif; font-size: 1.15rem; color: var(--dl-cream); font-weight: 600; line-height: 1.25; }
/* the opening line of the page, in place of the "Read" label these carried:
   a repeated word told a reader nothing about which card to choose */
.dl-guide__moreex {
	font-size: .86rem;
	line-height: 1.55;
	color: var(--dl-muted);
}
@media (hover: hover) { .dl-guide__morecard:hover { transform: translateY(-3px); } }
/* the CTA button hugs its label rather than stretching, and stays centred */
.dl-guide__cta { margin-top: var(--sp-5); text-align: center; }
.dl-guide__cta .dl-btn { display: inline-flex; width: auto; max-width: 100%; }

/* ==========================================================================
   CASTING — the two ways in
   --------------------------------------------------------------------------
   The page has no form, so these two panels carry the whole call to action.
   They get the frosted treatment from the journal stat cards for the same
   reason it works there: the page has a gradient behind it worth sampling,
   and glass reads as considered rather than as another button.

   Two of them, side by side, weighted equally. Neither email nor phone is
   presented as the preferred route, because which one feels safer is entirely
   the reader's business.
   ========================================================================== */
.dl-cast__ways {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sp-3);
	margin: 0 0 var(--sp-6);
}
.dl-cast__ways--foot { margin: var(--sp-6) 0 0; }

.dl-cast__way {
	position: relative;
	display: block;
	padding: var(--sp-5) var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	background: linear-gradient(180deg, rgba(246, 241, 228, .055), rgba(246, 241, 228, .014));
	-webkit-backdrop-filter: blur(16px) saturate(150%);
	backdrop-filter: blur(16px) saturate(150%);
	box-shadow: inset 0 1px 0 rgba(246, 241, 228, .08);
	text-decoration: none;
	/* declared, not inherited: these sit in a left-aligned section, and centring
	   is what makes two panels read as a pair of destinations rather than as two
	   paragraphs that happen to have borders */
	text-align: center;
	overflow: hidden;
	transition: border-color .3s var(--dl-ease), transform .35s var(--dl-ease-out);
}
/* the house gold-to-teal hairline, along the top edge only */
.dl-cast__way::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--dl-gold), var(--dl-teal), transparent);
	opacity: .55;
	pointer-events: none;
}

.dl-cast__waylabel {
	display: block;
	font-size: .64rem;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--dl-muted);
}
.dl-cast__wayval {
	display: block;
	margin-top: 9px;
	font-family: "Cormorant Garamond", Georgia, serif;
	/* 1.25 not 1: this font sets old-style figures and they descend, and the
	   gradient below is clipped to the text, so a short line box would slice
	   the bottom off every 3, 4, 5, 7 and 9 in the phone number */
	line-height: 1.25;
	font-size: clamp(1.15rem, 3.4vw, 1.5rem);
	background: var(--dl-gold-grad);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	overflow-wrap: anywhere;
}
.dl-cast__waynote {
	display: block;
	margin-top: 10px;
	font-size: .82rem;
	line-height: 1.5;
	color: var(--dl-muted);
}

@media (hover: hover) {
	.dl-cast__way:hover { border-color: var(--dl-gold); transform: translateY(-3px); }
}
.dl-cast__way:active { border-color: var(--dl-gold); transform: translateY(-1px); }

@media (max-width: 600px) {
	.dl-cast__ways { grid-template-columns: 1fr; gap: var(--sp-2); }
	.dl-cast__way { padding: var(--sp-4) var(--sp-3); }
}

/* no blur available: an opaque panel, since a 5%-alpha surface is invisible */
@supports not ((-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px))) {
	.dl-cast__way { background: rgba(20, 20, 26, .82); }
}

/* related guides block on taxonomy pages */
.dl-relguides { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--sp-3); }

/* --- journal, grouped by cluster ---
   A rule and a count above each set, so the groups read as separate shelves
   rather than one long grid with headings dropped into it. */
.dl-journal__group + .dl-journal__group { margin-top: var(--sp-7); }
.dl-journal__grouphead {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-3);
	margin: 0 0 var(--sp-4);
	padding-bottom: var(--sp-2);
	border-bottom: 1px solid var(--dl-line);
}
.dl-journal__grouphead h2 { margin: 0; font-size: 1.5rem; }
.dl-journal__grouphead span {
	flex: none;
	font-size: .74rem;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--dl-muted);
}
@media (max-width: 600px) {
	.dl-journal__group + .dl-journal__group { margin-top: var(--sp-6); }
	.dl-journal__grouphead h2 { font-size: 1.3rem; }
}

/* listings archive filters */
.dl-archive__filters { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6); }
@media (max-width: 782px) {
	.dl-archive__filters { grid-template-columns: 1fr; gap: 0; }
	/* closed rows sit tight to each other; the separator carries the rhythm */
	.dl-browse + .dl-browse { border-top: 1px solid var(--dl-line); }
}

/* --- collapsible quick-browse (same mechanics as the footer columns) --- */
.dl-browse > summary {
	list-style: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 14px 0;
	margin-bottom: 0;
}
.dl-browse > summary::-webkit-details-marker { display: none; }
/* chevron: shown only while the group is actually collapsible */
.dl-browse > summary::after {
	content: "";
	width: 7px; height: 7px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg) translateY(-2px);
	transition: transform .3s var(--dl-ease);
	flex: none;
}
.dl-browse[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
.dl-browse > .dl-arealinks { padding-bottom: var(--sp-3); }
@media (min-width: 783px) {
	/* Collapsible here too, unlike the footer columns — the chevron and the
	   pointer stay, only the spacing tightens. Open is still the default; the
	   control is there for anyone who wants the list out of the way. */
	.dl-browse > summary { padding: 0 0 var(--sp-2); }
	.dl-browse > .dl-arealinks { padding-bottom: 0; }
}

/* ── duo partners ── */
.dl-duo__intro { font-size: .86rem; color: var(--dl-muted); margin: 0 0 var(--sp-3); }
.dl-duo {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(clamp(110px, 18vw, 150px), 1fr));
	gap: var(--sp-2);
}
.dl-duo__item {
	display: block;
	position: relative;                /* for the gradient edge below */
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	overflow: hidden;
	background: rgba(255,255,255,.02);
	transition: border-color .25s var(--dl-ease);
}
/*
 * No lift and no zoom on these tiles, deliberately.
 *
 * The edge shimmered in Chrome on hover. Three attempts to keep the animation
 * and stop the shimmer did not hold: matching the scrim to the strip, then
 * overlapping them, then giving the tile its own compositor layer.
 *
 * Measuring showed why none of it worked. The join is rgb(14,14,16) on both
 * sides, on every tile, at rest and hovered, in WebKit and in Chrome alike, so
 * there was never a colour step to fix. It is a compositor artefact: a rounded
 * overflow-hidden box with a transforming child is re-rasterised every frame in
 * Chrome, and its clipped edge crawls. A screenshot forces a full repaint, so it
 * cannot capture that — which is also why it could not be verified from here.
 *
 * Removing the transform removes the cause. Nothing re-rasterises, so there is
 * no edge to crawl. The gradient ring above is the feedback, and it is the same
 * one the area chips, likes and guide cards use, so the tiles now match them
 * rather than being the one place with its own animation.
 *
 * border-color goes transparent so the ring is the only edge; the two together
 * read as a doubled line.
 */
@media (hover: hover) {
	.dl-duo__item:hover { border-color: transparent; }
}
.dl-duo__img { display: block; position: relative; aspect-ratio: 3 / 4; overflow: hidden; background: #0b0b0e; }
/*
 * A scrim, added because the rate now sits on the photo.
 *
 * The listing cards already had one; these tiles never did, so gold text on a
 * pale photo would have been unreadable. Deliberately NOT taken to a solid
 * colour at the bottom edge: the meta strip below sits on the tile background
 * rather than on #09090c, so committing the scrim to an opaque end would
 * manufacture the very seam that took three attempts to remove from the
 * listing cards. Ending translucent darkens the corner without introducing a
 * colour boundary that has to be matched.
 */
.dl-duo__img::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 42%, rgba(6, 6, 9, .55) 72%, rgba(6, 6, 9, .92) 100%);
	pointer-events: none;
}
.dl-duo__img img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%; display: block; transition: transform .8s var(--dl-ease-out); }
.dl-duo__meta { display: block; padding: 9px 10px 11px; }
.dl-duo__meta strong { display: block; font-family: "Cormorant Garamond", Georgia, serif; font-size: 1rem; color: var(--dl-cream); line-height: 1.2; }
.dl-duo__meta span { display: block; font-size: .74rem; color: var(--dl-muted); margin-top: 2px; }
/* now an overlay on the photo rather than a line in the meta strip, so it needs
   its own type rather than inheriting .dl-duo__meta span */
.dl-duo__price {
	position: absolute;
	left: 8px;
	bottom: 7px;
	z-index: 2;
	font-size: .78rem;
	font-weight: 600;
	line-height: 1;
	color: var(--dl-gold-lt);
	text-shadow: 0 1px 6px rgba(0, 0, 0, .85);
	pointer-events: none;
}

/* area links inside a profile card — same compact chip as the services list,
   so the two cards read as a matching pair rather than two different systems */
.dl-arealinks { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 7px; }
.dl-arealinks li a {
	display: inline-block;
	font-size: .8rem;
	padding: 5px 11px;
	border-radius: 6px;
	color: var(--dl-text);
	background: rgba(255,255,255,.03);
	border: 1px solid var(--dl-line);
	transition: border-color .25s var(--dl-ease), color .25s var(--dl-ease), background .25s var(--dl-ease);
}
@media (hover: hover) {
	.dl-arealinks li a:hover { border-color: transparent; }   /* the ring takes over */
}

/* --- homepage --- */
.dl-hero__cta { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center; margin: var(--sp-5) 0 0; }
.dl-cloud__n { font-size: .75em; color: var(--dl-muted); margin-left: 4px; }

.dl-two-col { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6); }
@media (max-width: 782px) { .dl-two-col { grid-template-columns: 1fr; gap: var(--sp-6); } }

/* guide promo — the editorial layer gets its own treatment so it doesn't read as another category block */
.dl-guide-promo {
	position: relative;
	padding: var(--sp-7) var(--sp-5);
	border: 1px solid var(--dl-line-strong);
	border-radius: var(--dl-radius);
	background:
		linear-gradient(135deg, rgba(201,168,76,.07), rgba(15,154,154,.05)),
		linear-gradient(180deg, var(--dl-surface-2), var(--dl-surface));
	text-align: center;
}
.dl-guide-promo h2 { margin: 0 0 var(--sp-3); }
.dl-guide-promo .dl-lede { margin-inline: auto; margin-bottom: 0; }
.dl-guide-promo__links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--sp-2) var(--sp-5);
	margin-top: var(--sp-4);
}
.dl-guide-promo .dl-btn { margin-top: var(--sp-5); }
.dl-guide-promo__links a {
	font-size: .92rem;
	color: var(--dl-gold-lt);
	border-bottom: 1px solid rgba(201,168,76,.3);
	padding-bottom: 2px;
	transition: border-color .25s var(--dl-ease);
}
.dl-guide-promo__links a:hover { border-color: var(--dl-gold); }

/* pagination */
.dl-pagination { margin-top: var(--sp-6); }
.dl-pagination .nav-links { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2); }
.dl-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 40px;
	height: 40px;
	padding: 0 13px;
	margin: 0;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	background: transparent;
	background-clip: padding-box;      /* keeps a gradient off the border edge */
	color: var(--dl-text);
	font-size: .9rem;
	line-height: 1;
	text-decoration: none;
	transition: border-color .3s var(--dl-ease), color .3s var(--dl-ease), background .3s var(--dl-ease);
}
@media (hover: hover) {
	.dl-pagination .page-numbers:hover { border-color: var(--dl-gold); color: var(--dl-gold-lt); background: rgba(201,168,76,.06); }
}
/* current page: border matches the fill, so there's no seam where they meet */
.dl-pagination .page-numbers.current,
.dl-pagination .page-numbers.current:hover {
	background: linear-gradient(180deg, #f0d98c, var(--dl-gold));
	border-color: var(--dl-gold);
	color: #14100a;
	font-weight: 700;
}
.dl-pagination .page-numbers.dots { border-color: transparent; background: none; color: var(--dl-muted); }

/* prev / next as chevrons, sized as a comfortable tap target */
.dl-pagination .page-numbers.prev,
.dl-pagination .page-numbers.next { min-width: 44px; padding: 0; }
.dl-chev {
	display: block;
	width: 9px; height: 9px;
	border-left: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	margin-left: 3px;                       /* optically centre the arrow */
}
.dl-chev--next { transform: rotate(-135deg); margin-left: -3px; }

/* hide the accessible label without hiding it from screen readers */
.dl-pagination .screen-reader-text {
	position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
	overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Astra styles .ast-pagination too — keep ours winning */
.dl-pagination .navigation, .dl-pagination .nav-links { border: 0; }
.dl-pagination .nav-links > * { flex: 0 0 auto; }

@media (max-width: 600px) {
	.dl-pagination .nav-links { gap: 6px; }
	.dl-pagination .page-numbers { min-width: 38px; height: 38px; padding: 0 10px; font-size: .85rem; }
	.dl-pagination .page-numbers.prev,
	.dl-pagination .page-numbers.next { min-width: 44px; height: 44px; }   /* keep the chevrons easy to hit */
}

/* ==========================================================================
   6. BUTTONS
   ========================================================================== */
.dl-btn,
.wp-block-button__link,
.ast-button,
button.dl-btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 14px 34px;
	border: 1px solid var(--dl-gold);
	border-radius: 999px;
	background: transparent;
	color: var(--dl-gold-lt);
	font-family: "Inter", sans-serif;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .22em;
	text-transform: uppercase;
	cursor: pointer;
	overflow: hidden;
	/* The fill below sits at z-index -1. Without a stacking context of its own
	   that puts it BEHIND the section background rather than behind the label,
	   so the fill never appeared and the dark hover text landed on black. */
	isolation: isolate;
	transition: color .4s var(--dl-ease), border-color .4s var(--dl-ease);
}
/* gold fill wipes in from the left */
.dl-btn::before,
.wp-block-button__link::before {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--dl-gold-grad);
	transform: translateX(-101%);
	transition: transform .5s var(--dl-ease-out);
	z-index: -1;
}
/* Fill and text colour must change together. Binding the colour to :hover alone
   left the label unreadable on touch, where the fill lands but hover never fires. */
.dl-btn:hover::before,
.dl-btn:active::before,
.dl-btn:focus::before,
.wp-block-button__link:hover::before,
.wp-block-button__link:active::before { transform: translateX(0); }

.dl-btn:hover,
.dl-btn:active,
.dl-btn:focus,
.wp-block-button__link:hover,
.wp-block-button__link:active { color: #14100a; border-color: var(--dl-gold); }

/*
 * Touch: no lingering hover, just a clear press state.
 *
 * This was written as `:not(:active)` on the resting rules, which measured wrong
 * on a real iPhone — WebKit reported the element as :active while the ::before
 * fill stayed parked off-canvas and the label never changed colour, so a tap
 * produced nothing but a 2% scale. Stating the resting state plainly and letting
 * a higher-specificity :active override it removes the negation entirely, and
 * the press now paints. Faster wipe too: a tap is over in ~100ms, so a 500ms
 * fill never got far enough to be seen.
 */
@media (hover: none) {
	.dl-btn::before { transition: transform .18s var(--dl-ease-out); transform: translateX(-101%); }
	.dl-btn { color: var(--dl-gold-lt); }
	.dl-btn--teal { color: var(--dl-teal-lt); }

	/* iOS latches :hover on to the last thing tapped, and .dl-btn:hover outranks
	   the resting rule above — so a button stayed filled gold after you pressed
	   it. Neutralised here, before the press rules, so :active still wins. */
	.dl-btn:hover::before { transform: translateX(-101%); }
	.dl-btn:hover { color: var(--dl-gold-lt); border-color: var(--dl-line-strong); }
	.dl-btn--teal:hover { color: var(--dl-teal-lt); border-color: rgba(15, 154, 154, .55); }

	.dl-btn:active::before { transform: translateX(0); }
	.dl-btn:active { color: #14100a; border-color: var(--dl-gold); }
	.dl-btn--teal:active { color: #04100f; border-color: var(--dl-teal); }
}

/*
 * Everything else that only had a hover state. On a phone `@media (hover: hover)`
 * correctly skips those rules, and with -webkit-tap-highlight-color set to
 * transparent site-wide that left 30-odd controls with no press feedback at all.
 * One gold wash covers the lot rather than a bespoke :active per component.
 */
@media (hover: none) {
	/* the active-filter pill is deliberately not in this list: it is gold-on-dark
	   inverted, so a gold wash and gold text would put the label on top of its
	   own background. It carries its own press state further down. */
	.dl-filter__picker:active,
	.dl-filter__price select:active,
	.dl-filter__clear:active,
	.dl-pagination .page-numbers:active,
	.dl-guide__toc a:active,
	.dl-guide-promo__links a:active,
	.dl-copygrid a:active,
	.dl-crumbs a:active,
	.dl-rvcard:active,
	.dl-rvcard--all:active,
	.dl-combo:active,
	.dl-combo__face:active,
	.dl-guide__morecard:active,
	.dl-rate label:active,
	.dl-browse > summary:active,
	.dl-foot__col > summary:active {
		border-color: var(--dl-gold);
		background-color: rgba(201, 168, 76, .1);
		color: var(--dl-gold-lt);
	}
	/* cards lift on hover for a mouse; on touch a small settle reads better */
	.dl-rvcard:active,
	.dl-combo:active,
	.dl-guide__morecard:active { transform: scale(.985); }
}

/* Secondary button: teal hairline on near-black, filling to a DEEP teal rather
   than a bright slab — a bright fill fights the black-and-gold palette and the
   dark-on-light text was unreadable the moment the fill landed. */
.dl-btn--teal { border-color: rgba(15, 154, 154, .55); color: var(--dl-teal-lt); }
.dl-btn--teal::before { background: linear-gradient(135deg, #0c2b2b, #071c1c); }
.dl-btn--teal:hover,
.dl-btn--teal:active,
.dl-btn--teal:focus { color: var(--dl-teal-lt); border-color: var(--dl-teal); }

/* ==========================================================================
   7. SCROLL REVEAL  (JS adds .is-in when the element enters the viewport)
   ========================================================================== */
/*
 * Only hidden when JS is actually running. Unconditional opacity:0 meant that a
 * blocked, slow or failed script left the whole page blank — content that
 * depends on JS to become visible is content that can vanish.
 * .dl-js is set on <html> from an inline script in the head.
 */
.dl-js .dl-reveal {
	opacity: 0;
	transform: translateY(26px);
	transition:
		opacity   .6s var(--dl-ease-out),
		transform .6s var(--dl-ease-out);
	will-change: opacity, transform;
}
/*
 * will-change is released the moment the element has arrived.
 *
 * Left standing it holds a compositor layer for every revealed element for the
 * life of the page — forty-odd of them on the homepage, each re-rasterised when
 * the page is zoomed. Pinching in and back out on an iPhone was enough to take
 * the tab down. The hint is only worth anything while the transition is running.
 */
.dl-js .dl-reveal.is-in { opacity: 1; transform: none; will-change: auto; }

/* stagger children — set by JS via --i */
/* 90ms each meant the twelfth card in a grid waited a full second before it
   even started fading in, which looked like a page still loading */
.dl-stagger > * { transition-delay: calc(var(--i, 0) * 40ms); }

/* ==========================================================================
   8. EDITORIAL / ARTICLE BODY  (the guide pages)
   ========================================================================== */
.dl-article {
	max-width: 74ch;
	margin-inline: auto;
	font-size: 1.06rem;
}
.dl-article h2 { margin: 2.2em 0 .7em; }
.dl-article h3 { margin: 1.8em 0 .6em; color: var(--dl-gold-lt); }

.dl-article blockquote {
	margin: 2em 0;
	padding: 4px 0 4px 26px;
	border-left: 2px solid var(--dl-gold);
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.3rem;
	font-style: italic;
	color: var(--dl-cream);
}

.dl-article ul, .dl-article ol { margin: 0 0 1.5em; padding-left: 1.3em; }
.dl-article li { margin-bottom: .55em; }
.dl-article ul li::marker { color: var(--dl-gold); }

/* in-body links get an animated gold underline */
.dl-article p a {
	background-image: linear-gradient(var(--dl-gold), var(--dl-gold));
	background-size: 0% 1px;
	background-repeat: no-repeat;
	background-position: 0 100%;
	transition: background-size .4s var(--dl-ease);
}
.dl-article p a:hover { background-size: 100% 1px; }

/* key-takeaway callout */
.dl-callout {
	margin: 2.2em 0;
	padding: 22px 26px;
	border: 1px solid var(--dl-line-strong);
	border-radius: var(--dl-radius-sm);
	background: linear-gradient(135deg, rgba(201, 168, 76, .07), rgba(15, 154, 154, .04));
}
.dl-callout__label {
	display: block;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: .24em;
	text-transform: uppercase;
	color: var(--dl-gold);
	margin-bottom: 8px;
}
.dl-callout p:last-child { margin-bottom: 0; }

/* ── table of contents: each entry its own faded card ── */
.dl-toc { margin: 0 0 var(--sp-6); padding: 0; border: 0; background: none; }
.dl-toc ol {
	list-style: none;
	counter-reset: dl-toc;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(clamp(160px, 24vw, 250px), 1fr));
	gap: var(--sp-2);
}
.dl-toc li { margin: 0; counter-increment: dl-toc; }
.dl-toc li a {
	position: relative;
	display: flex;
	align-items: center;
	gap: 11px;
	height: 100%;
	padding: 14px 15px;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	/* near-black with a faint gold wash, matching the luxury cards */
	background:
		radial-gradient(120% 90% at 0% 0%, rgba(201,168,76,.06), transparent 65%),
		linear-gradient(180deg, #0c0c10, #08080a);
	color: var(--dl-text);
	font-size: .9rem;
	line-height: 1.3;
	overflow: hidden;
	transition: border-color .3s var(--dl-ease), color .3s var(--dl-ease), transform .3s var(--dl-ease-out);
}
/* the faded gold hairline, same detail as every other card */
.dl-toc li a::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--dl-gold), transparent);
	opacity: .4;
}
/* the number, set in the display serif */
.dl-toc li a::before {
	content: counter(dl-toc, decimal-leading-zero);
	flex: none;
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.15rem;
	color: var(--dl-gold);
	opacity: .75;
	line-height: 1;
}
@media (hover: hover) {
	.dl-toc li a:hover { border-color: var(--dl-line-strong); color: var(--dl-gold-lt); transform: translateY(-2px); }
	.dl-toc li a:hover::after { opacity: .8; }
}
.dl-toc li a:active { border-color: var(--dl-gold); }

/* when the copy carries its own contents, the body uses the full width */
.dl-guide__grid--full { grid-template-columns: 1fr; }

/* Our templates run body copy the full shell width, so it lines up with the
   grids and cards above it. The narrow 74ch measure on top of an already narrow
   shell made these pages look half-empty. Astra's own pages keep the measure. */
.dl-guide .dl-article,
.dl-tax .dl-article,
.dl-archive .dl-article,
.dl-home .dl-article { max-width: none; margin-inline: 0; }

/* FAQ accordion */
/*
 * No rules between the questions.
 *
 * The list previously carried a hairline above it and one under every item,
 * which on a card that already has its own border read as a stack of boxes
 * inside a box. The rows still separate perfectly well on their own: each
 * question has 20px of padding top and bottom, and an open one tints its
 * background, so the structure survives without drawing it.
 */
.dl-faq { border-top: 0; }
.dl-faq__item { border-bottom: 0; }

/*
 * wpautop inserts an empty <p> between each question button and its answer.
 * It computes to 0px so it is doing no visible harm, but it is six stray
 * elements per FAQ and it can pick up margins from any future rule on p.
 */
.dl-faq__item > p:empty { display: none; }
.dl-faq__q {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 18px;
	padding: 20px 4px;
	background: none;
	border: 0;
	text-align: left;
	cursor: pointer;
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.2rem;
	/*
	 * A wrapped question overlapped itself: the computed line-height was 1,
	 * so two lines sat 3.32px closer than the type is tall. It only showed
	 * once the questions were sized up on a phone and started wrapping, but
	 * it was always wrong, so it is fixed here rather than in the media query.
	 */
	line-height: 1.36;
	color: var(--dl-cream);
	transition: color .3s var(--dl-ease);
}
@media (hover: hover) { .dl-faq__q:hover { color: var(--dl-gold-lt); } }
/* open state reads as a subtle dark lift, never a coloured block */
.dl-faq__item.is-open { background: rgba(255,255,255,.018); }
.dl-faq__item.is-open .dl-faq__q { color: var(--dl-gold-lt); }
.dl-faq__q::after {
	content: "";
	flex: none;
	width: 9px; height: 9px;
	border-right: 2px solid var(--dl-gold);
	border-bottom: 2px solid var(--dl-gold);
	transform: rotate(45deg);
	transition: transform .4s var(--dl-ease);
}
.dl-faq__item.is-open .dl-faq__q::after { transform: rotate(-135deg); }
.dl-faq__a {
	max-height: 0;
	overflow: hidden;
	transition: max-height .5s var(--dl-ease-out);
}
.dl-faq__a > div { padding: 0 4px 22px; color: var(--dl-muted); }

/* ==========================================================================
   8b. ASTRA BLOG / ARCHIVE OVERRIDES
   Astra paints its post cards white, which fights the black canvas. Restyle
   its own classes to match .dl-card rather than leaving light blocks floating.
   ========================================================================== */
.ast-article-post,
.ast-article-single,
.ast-separate-container .ast-article-post,
.ast-separate-container .ast-article-single,
.ast-separate-container .ast-comment-list li.depth-1,
.ast-separate-container .comment-respond,
#primary .post,
.ast-article-inner {
	background: linear-gradient(180deg, var(--dl-surface-2), var(--dl-surface)) !important;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	color: var(--dl-text);
	transition: transform .5s var(--dl-ease-out), border-color .35s var(--dl-ease), box-shadow .5s var(--dl-ease-out);
}
.ast-separate-container .ast-article-post { overflow: hidden; }

@media (hover: hover) and (pointer: fine) {
	.ast-article-post:hover {
		transform: translateY(-6px);
		border-color: var(--dl-line-strong);
		box-shadow: var(--dl-glow-gold);
	}
}

/* the whole content wrapper Astra tints */
.ast-separate-container,
.ast-separate-container .site-content,
.ast-plain-container,
#content,
.site-content { background: transparent !important; }

/* titles + excerpts inside Astra cards */
.ast-article-post .entry-title a,
.ast-article-single .entry-title,
#primary .entry-title a { color: var(--dl-cream); }
.ast-article-post .entry-title a:hover { color: var(--dl-gold-lt); }
.ast-excerpt-container,
.ast-article-post .entry-content { color: var(--dl-muted); }

/* meta byline — Astra leaves these browser-blue on a dark background */
.entry-meta,
.entry-meta *,
.ast-blog-meta-container,
.posted-by,
.posted-on,
.post-meta { color: var(--dl-muted) !important; }
.entry-meta a,
.posted-by a,
.ast-taxonomy-container a,
.cat-links a,
.tags-links a {
	color: var(--dl-gold) !important;
	transition: color .25s var(--dl-ease);
}
.entry-meta a:hover,
.posted-by a:hover,
.ast-taxonomy-container a:hover { color: var(--dl-gold-lt) !important; }

/* read-more */
.ast-button, .read-more a { color: var(--dl-gold-lt); }

/* widgets + sidebar */
.widget, .sidebar-main, .secondary { background: transparent; color: var(--dl-text); }
.widget-title, .widget h2 { color: var(--dl-cream); }

/* comments */
.comment-body, .comment-content { color: var(--dl-text); }
.comment-author .fn a { color: var(--dl-gold-lt); }

/* ==========================================================================
   9. HEADER / FOOTER  (Astra overrides)
   ========================================================================== */
.site-header,
.ast-primary-header-bar,
.ast-header-break-point .main-header-bar {
	background: rgba(8, 8, 10, .72) !important;
	backdrop-filter: blur(16px) saturate(150%);
	-webkit-backdrop-filter: blur(16px) saturate(150%);
	border-bottom: 1px solid var(--dl-line);
	transition: background .4s var(--dl-ease), border-color .4s var(--dl-ease);
}
/* once you're past the hero the bar solidifies and picks up a gold hairline */
body.dl-scrolled .site-header,
body.dl-scrolled .ast-primary-header-bar,
body.dl-scrolled.ast-header-break-point .main-header-bar {
	background: rgba(8, 8, 10, .95) !important;
	border-bottom-color: rgba(201, 168, 76, .22);
}

/* ── wordmark: D.E | GUIDE ──
   Drawn from the site-title link rather than an image, so it stays crisp at any
   density and needs no upload. The real title text is still in the DOM for
   screen readers and for the link's accessible name; it's only sized away. */
.site-title { margin: 0; line-height: 1; }
.site-title a {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 0;
	line-height: 1;
	text-decoration: none;
}
.site-title a::before {
	content: "D.E";
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.95rem;
	font-weight: 700;
	letter-spacing: .01em;
	background: var(--dl-gold-grad);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: var(--dl-gold);          /* fallback where background-clip:text is unsupported */
}
.site-title a::after {
	content: "GUIDE";
	font-family: "Inter", sans-serif;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .3em;
	text-indent: .34em;             /* balances the trailing letter-space */
	color: var(--dl-muted);
	padding-left: 10px;
	border-left: 1px solid var(--dl-line);
	transition: color .35s var(--dl-ease), border-color .35s var(--dl-ease);
}
@media (hover: hover) {
	.site-title a:hover::after { color: var(--dl-gold-lt); border-color: rgba(201, 168, 76, .5); }
}
/* Same feedback on touch, where there is no hover to trigger it. */
@media (hover: none) {
	.site-title a:active::after { color: var(--dl-gold-lt); border-color: rgba(201, 168, 76, .5); }
}
@media (max-width: 600px) {
	.site-title a::before { font-size: 1.6rem; }
	.site-title a::after  { font-size: 10px; letter-spacing: .24em; text-indent: .24em; padding-left: 9px; }
}

/* ── nav items ──
   Astra's dynamic CSS targets .ast-builder-menu-1 .menu-item > .menu-link, which
   outranks a plain .main-header-menu a — hence the matching specificity here. */
.ast-builder-menu-1 .menu-item > .menu-link,
.main-header-menu .menu-link {
	position: relative;
	/* !important because Astra's Customizer CSS uses the identical selector from
	   an inline <style> that loads after this file — it wins any tie on order */
	color: var(--dl-text) !important;
	font-family: "Inter", sans-serif;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .14em;             /* eased off as the size went up, or it sprawls */
	text-transform: uppercase;
	border-radius: 999px;
	padding: 9px 14px !important;
	transition: color .35s var(--dl-ease), background .35s var(--dl-ease);
}
/* even spacing between items, so the row reads as a set of buttons */
.ast-builder-menu-1 .main-header-menu { gap: 2px; }

/* Only the top row stays on one line — its labels are short. Submenu labels are
   page titles and must wrap, or they run straight off a 240px panel and off the
   side of a phone. */
.main-header-menu > .menu-item > .menu-link { white-space: nowrap; }
.main-header-menu .sub-menu .menu-link { white-space: normal; }

/* The underline wipes in from the left and retreats to the right, rather than
   growing from the middle — it reads as movement across the label. */
.main-header-menu > .menu-item > .menu-link::after {
	content: "";
	position: absolute;
	left: 13px; right: 13px;
	/* Astra gives header links an 80px line-height to fill the bar, so anything
	   measured from the bottom edge lands 30-odd px under the text. Measured from
	   the centre instead, it sits just below the glyphs at any header height. */
	bottom: calc(50% - .95em);
	height: 1px;
	background: var(--dl-gold-grad);
	transform: scaleX(0);
	transform-origin: right center;
	transition: transform .45s var(--dl-ease-out);
}
.main-header-menu > .menu-item:hover > .menu-link::after,
.main-header-menu > .current-menu-item > .menu-link::after,
.main-header-menu > .current-menu-ancestor > .menu-link::after,
.main-header-menu > .current_page_item > .menu-link::after {
	transform: scaleX(1);
	transform-origin: left center;
}
@media (hover: hover) {
	.ast-builder-menu-1 .menu-item:hover > .menu-link,
	.main-header-menu .menu-item:hover > .menu-link { color: var(--dl-gold-lt) !important; }
}
.main-header-menu > .current-menu-item > .menu-link,
.main-header-menu > .current-menu-ancestor > .menu-link,
.main-header-menu > .current_page_item > .menu-link { color: var(--dl-gold-lt) !important; }

/* dropdown panel */
.main-header-menu .sub-menu {
	background: linear-gradient(180deg, #0d0d11, #08080a) !important;
	border: 1px solid var(--dl-line) !important;
	border-radius: 12px;
	padding: 6px !important;
	box-shadow: 0 24px 60px rgba(0, 0, 0, .6);
}
.main-header-menu .sub-menu .menu-link {
	border-radius: 8px;
	letter-spacing: .14em;
	border: 0 !important;
}
.main-header-menu .sub-menu .menu-item:hover > .menu-link {
	background: rgba(201, 168, 76, .09);
	color: var(--dl-gold-lt);
}
.main-header-menu .sub-menu .menu-item > .menu-link::after { display: none; }

/* ── dropdown chevron ──
   Astra ships it as a fixed-colour SVG; fill: currentColor hands it back to the
   theme so it inherits the same gold the label picks up, and it flips on open. */
.ast-header-navigation-arrow,
.dropdown-menu-toggle {
	color: var(--dl-muted);
	transition: color .3s var(--dl-ease);
}
.ast-header-navigation-arrow .ast-arrow-svg,
.dropdown-menu-toggle .ast-arrow-svg,
.ast-menu-toggle .ast-arrow-svg {
	fill: currentColor;
	width: 9px;
	height: 9px;
	transition: transform .3s var(--dl-ease);
}
.menu-item:hover > .menu-link .ast-header-navigation-arrow,
.menu-item:hover > .menu-link .dropdown-menu-toggle { color: var(--dl-gold-lt); }
/*
 * Scoped to the submenu toggles themselves. Unqualified, this also matched the
 * hamburger — which carries aria-expanded too — so opening the mobile menu
 * flipped every chevron inside it and the open item's arrow pointed the wrong way.
 */
.ast-menu-toggle[aria-expanded="true"] .ast-arrow-svg,
.dropdown-menu-toggle[aria-expanded="true"] .ast-arrow-svg,
.ast-header-navigation-arrow[aria-expanded="true"] .ast-arrow-svg { transform: rotate(180deg); }

/* submenu items get a gold marker rather than a full pill */
.main-header-menu .sub-menu .menu-item > .menu-link {
	position: relative;
	padding-left: 20px !important;
}
.main-header-menu .sub-menu .menu-item > .menu-link::before {
	content: "";
	position: absolute;
	left: 8px;
	top: 50%;
	width: 5px;
	height: 1px;
	background: var(--dl-gold);
	transform: translateY(-50%) scaleX(0);
	transform-origin: left center;
	transition: transform .3s var(--dl-ease-out);
}
.main-header-menu .sub-menu .menu-item:hover > .menu-link::before { transform: translateY(-50%) scaleX(1); }

/* ── "all areas" row at the foot of a dropdown ──
   Set apart by a hairline and a corner arrow, so it reads as the way out of the
   list rather than another item in it. */
/*
 * One gold hairline marks the way out of the list, and nothing else.
 *
 * No margin or padding here: the rows carry their own background while the
 * panel behind them is lighter, so any gap exposed a strip of that panel and
 * read as a grey band above this row. The border alone is the separator.
 */
.main-header-menu .sub-menu .dl-menu-all {
	margin-top: 0;
	padding-top: 0;
	border-top: 1px solid rgba(201, 168, 76, .35) !important;
	border-bottom: 0 !important;
}
.main-header-menu .sub-menu .dl-menu-all > .menu-link {
	display: flex !important;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	color: var(--dl-gold-lt) !important;
	font-size: 9px;
	letter-spacing: .18em;
	padding-left: 14px !important;
}
.main-header-menu .sub-menu .dl-menu-all > .menu-link::before { display: none; }
/* the generic nav underline is absolutely positioned — this one is a real glyph */
.main-header-menu .sub-menu .dl-menu-all > .menu-link::after {
	content: "";
	display: block;
	position: static;
	width: 6px;
	height: 6px;
	background: none;
	border-right: 1.5px solid currentColor;
	border-top: 1.5px solid currentColor;
	transform: rotate(45deg);
	transition: transform .3s var(--dl-ease);
}
@media (hover: hover) {
	.main-header-menu .sub-menu .dl-menu-all > .menu-link:hover::after {
		transform: rotate(45deg) translate(2px, -2px);
	}
}
.ast-header-break-point .main-header-menu .sub-menu .dl-menu-all > .menu-link {
	font-size: .85rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	padding-left: 36px !important;
}
/* the indent hairline stops at this row — the gold rule above it is the divider */
.ast-header-break-point .main-header-menu .sub-menu .dl-menu-all > .menu-link::before { display: none !important; }

/*
 * On touch layouts Astra renders TWO chevrons on a parent item: one inside the
 * link and a separate toggle button beside it. The in-link one is dropped, since
 * the button is the part that actually opens the submenu.
 */
.ast-header-break-point .main-header-menu .menu-link .dropdown-menu-toggle,
.ast-header-break-point .main-header-menu .menu-link .ast-header-navigation-arrow { display: none; }

/* the separate submenu toggle Astra renders on touch layouts */
/*
 * The row becomes a grid so the label and its toggle are siblings on one line
 * and the submenu spans underneath.
 *
 * Astra positions the toggle absolutely. Pinned top-to-bottom it stretched to
 * the whole <li>, which grows to contain the open submenu — so on an open item
 * the button was 372px tall and its chevron sat centred somewhere down inside
 * the submenu instead of on the parent row. Taking it out of absolute
 * positioning removes the problem rather than compensating for it.
 */
.ast-header-break-point .main-header-menu > .menu-item {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: stretch;
}
.ast-header-break-point .main-header-menu > .menu-item > .menu-link { grid-column: 1; }
.ast-header-break-point .main-header-menu > .menu-item > .sub-menu { grid-column: 1 / -1; }

.ast-header-break-point .ast-menu-toggle {
	position: static !important;
	grid-column: 2;
	color: var(--dl-gold-lt) !important;
	background: transparent !important;
	border-left: 1px solid rgba(255, 255, 255, .06) !important;
	width: 56px;
	height: auto !important;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0 !important;
}
.ast-header-break-point .ast-menu-toggle svg { fill: currentColor !important; }

/* ── mobile ── */
.ast-header-break-point .menu-toggle,
.main-header-menu-toggle {
	background: transparent !important;
	border: 1px solid var(--dl-line) !important;
	border-radius: 10px !important;
	width: 44px; height: 44px;            /* a proper tap target */
	color: var(--dl-gold-lt) !important;
	transition: border-color .3s var(--dl-ease), background .3s var(--dl-ease);
}
/* Astra hardcodes a blue fill on both the burger and the close cross, from an
   inline stylesheet — hence !important to hand them back to the button colour */
.ast-header-break-point .menu-toggle .ast-mobile-svg,
.ast-header-break-point .menu-toggle .ast-menu-svg,
.ast-header-break-point .menu-toggle .ast-close-svg,
.ast-header-break-point .menu-toggle svg { fill: currentColor !important; }
.ast-header-break-point .menu-toggle[aria-expanded="true"],
.ast-header-break-point .menu-toggle:active {
	border-color: var(--dl-gold) !important;
	background: rgba(201, 168, 76, .1) !important;
}

.ast-header-break-point .main-header-bar-navigation {
	background: linear-gradient(180deg, #0b0b0e, #08080a);
	border-top: 1px solid var(--dl-line);
}
.ast-header-break-point .main-header-menu .menu-item { border-bottom: 1px solid rgba(255, 255, 255, .05); }
.ast-header-break-point .main-header-menu .menu-item:last-child { border-bottom: 0; }

/* Sans rather than the display serif: at menu size the serif read as body copy
   set too large, and long page titles wrapped into something that looked like an
   article rather than navigation. */
.ast-header-break-point .ast-builder-menu-1 .menu-item > .menu-link,
.ast-header-break-point .main-header-menu .menu-link {
	font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
	font-size: .95rem;
	font-weight: 500;
	letter-spacing: .03em;
	text-transform: none;
	color: var(--dl-cream);
	border-radius: 0;
	/* Astra's header line-height is ~53px so the bar fills vertically. Inherited
	   into the mobile panel it turned every row into an 80px slab. */
	line-height: 1.35 !important;
	padding: 15px 20px !important;
	padding-right: 66px !important;    /* clear of the submenu toggle */
}
/* top-level items carry a touch more weight than their children */
.ast-header-break-point .main-header-menu > .menu-item > .menu-link {
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	font-size: .82rem;
}
.ast-header-break-point .main-header-menu > .menu-item > .menu-link::after { display: none; }
/* gold bar wipes down the left edge of the active item */
.ast-header-break-point .main-header-menu > .menu-item > .menu-link::before {
	content: "";
	position: absolute;
	left: 0; top: 22%; bottom: 22%;
	width: 2px;
	background: var(--dl-gold-grad);
	transform: scaleY(0);
	transform-origin: top center;
	transition: transform .35s var(--dl-ease-out);
}
.ast-header-break-point .main-header-menu > .menu-item:active > .menu-link::before,
.ast-header-break-point .main-header-menu > .current-menu-item > .menu-link::before,
.ast-header-break-point .main-header-menu > .current-menu-ancestor > .menu-link::before,
.ast-header-break-point .main-header-menu > .current_page_item > .menu-link::before { transform: scaleY(1); }

/* children sit in a recessed well, indented and quieter than their parent */
.ast-header-break-point .main-header-menu .sub-menu {
	/* a light tint, not a darker one: on near-black a darker panel is invisible */
	background: #17171a !important;
	border: 0 !important;
	border-radius: 0;
	box-shadow: none;
	padding: 0 !important;
}
/* no rules between children: the panel's own tint already separates them from
   the parent list, and a divider per row made it look like a second menu */
.ast-header-break-point .main-header-menu .sub-menu .menu-item { border-bottom: 0 !important; }
.ast-header-break-point .main-header-menu .sub-menu .menu-link {
	font-size: .88rem;
	font-weight: 400;
	letter-spacing: .02em;
	text-transform: none;
	color: var(--dl-muted) !important;
	padding: 12px 20px 12px 34px !important;
}
/* a hairline runs down the indent so the nesting is legible without a chevron */
.ast-header-break-point .main-header-menu .sub-menu .menu-item > .menu-link::before {
	content: "";
	position: absolute;
	left: 20px;
	top: 0;
	bottom: 0;
	width: 1px;
	background: rgba(201, 168, 76, .22);
	transform: none;
}

/* Astra's own footer is replaced by .dl-footer, so its builder rows come off */
.site-footer,
.ast-small-footer,
.site-below-footer-wrap,
.site-primary-footer-wrap { display: none !important; }

/* ── our footer ── */
.dl-footer {
	position: relative;
	border-top: 1px solid var(--dl-line);
	background:
		radial-gradient(90% 60% at 50% 0%, rgba(201,168,76,.045), transparent 65%),
		linear-gradient(180deg, #0b0b0e, var(--dl-black));
	padding: var(--sp-7) 0 var(--sp-5);
	margin-top: var(--sp-7);
}

/* brand and bookings sit side by side, bookings narrower so the number leads */
.dl-foot__top {
	display: grid;
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	gap: var(--sp-3);
	margin-bottom: var(--sp-5);
}
@media (max-width: 782px) { .dl-foot__top { grid-template-columns: 1fr; } }

.dl-foot__mark {
	margin: 0 0 var(--sp-3);
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.5rem;
	line-height: 1;
	color: var(--dl-muted);
}
.dl-foot__mark a {
	display: inline-block;
	color: inherit;
	transition: color .3s var(--dl-ease);
}
@media (hover: hover) { .dl-foot__mark a:hover { color: var(--dl-cream); } }
/* A phone never matches (hover: hover), so the wordmark gave no feedback at all on
   tap. Bind the same change to the press instead. */
@media (hover: none) { .dl-foot__mark a:active { color: var(--dl-cream); } }
.dl-foot__mark span {
	font-weight: 700;
	background: var(--dl-gold-grad);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: var(--dl-gold);
	margin-right: 8px;
}
.dl-foot__blurb { margin: 0 0 var(--sp-4); color: var(--dl-muted); font-size: .92rem; }
.dl-foot__meta { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-5); }
.dl-foot__meta li { font-size: .8rem; color: var(--dl-muted); letter-spacing: .04em; }
.dl-foot__meta strong {
	display: block;
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.6rem;
	color: var(--dl-gold-lt);
	line-height: 1.1;
}

.dl-foot__contact { display: flex; flex-direction: column; align-items: flex-start; }

/* small icon action in the card's corner rather than a full-width button */
.dl-foot__book {
	position: absolute;
	top: var(--sp-4);
	right: var(--sp-4);
	width: 38px; height: 38px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background: rgba(255, 255, 255, .03);
	background-clip: padding-box;
	color: var(--dl-gold-lt);
	transition: border-color .3s var(--dl-ease), background .3s var(--dl-ease), color .3s var(--dl-ease);
}
.dl-foot__book svg { width: 17px; height: 17px; fill: currentColor; }
@media (hover: hover) {
	.dl-foot__book:hover { border-color: var(--dl-gold); background: rgba(201, 168, 76, .12); color: var(--dl-cream); }
}
.dl-foot__book:active { border-color: var(--dl-gold); background: rgba(201, 168, 76, .16); }
/* email sits to the left of the booking action, same treatment */
.dl-foot__book--mail { right: calc(var(--sp-4) + 46px); }

/*
 * [hidden] has to beat any display set by a class.
 *
 * The browser's own rule is [hidden] { display: none }, which any class selector
 * outranks. .dl-grid sets display:grid, so the filtered results stayed on screen
 * after Clear even though the attribute was set correctly. This makes the
 * attribute mean what it says everywhere, not just where it was patched by hand.
 */
[hidden] { display: none !important; }

/* ── live filter ── */
.dl-filter {
	margin-bottom: var(--sp-5);
	padding: var(--sp-4);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	background: linear-gradient(180deg, #0c0c10, #08080a);
}
.dl-filter__top {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-3);
	margin-bottom: var(--sp-3);
	padding-bottom: var(--sp-3);
	border-bottom: 1px solid var(--dl-line);
}
.dl-filter__search { flex: 1 1 220px; min-width: 0; }
.dl-filter__search input {
	width: 100%;
	padding: 11px 14px;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background: rgba(255, 255, 255, .03);
	color: var(--dl-cream);
	font-family: inherit;
	font-size: 16px;                    /* under 16px and iOS zooms on focus */
}
.dl-filter__search input:focus { outline: none; border-color: var(--dl-gold); background: rgba(201,168,76,.05); }
/* Gold, but held just under full strength so it still reads as a prompt rather
   than as something already typed into the field. */
.dl-filter__search input::placeholder { color: rgba(201, 168, 76, .8); opacity: 1; }
.dl-filter__search input::-webkit-input-placeholder { color: rgba(201, 168, 76, .8); }

/*
 * What you type has to be readable.
 *
 * Astra prints its form colours as inline CSS in the <head>, which lands after
 * this stylesheet, and its rule is input[type="…"]:focus — specificity (0,2,1).
 * A plain `.dl-filter__search input` is (0,1,1), so it lost twice over, on
 * weight and on order, and typed text came out #475569: dark slate on a dark
 * field. Measured, the search box and the review form's phone field were both
 * doing it; text and textarea happened to be covered already.
 *
 * Repeating the attribute selector and adding a class beats it outright rather
 * than depending on load order. -webkit-text-fill-color as well, because that is
 * what actually paints the glyphs in Safari when it is set.
 */
.dl-filter__search input[type="search"],
.dl-filter__search input[type="search"]:focus,
.dl-form input[type="text"],
.dl-form input[type="text"]:focus,
.dl-form input[type="tel"],
.dl-form input[type="tel"]:focus,
.dl-form input[type="email"],
.dl-form input[type="email"]:focus,
.dl-form textarea,
.dl-form textarea:focus {
	color: var(--dl-cream);
	-webkit-text-fill-color: var(--dl-cream);
	caret-color: var(--dl-gold);
}
/* the label is a hint, not a heading — it should not compete with the value */
.dl-filter__price { display: inline-flex; align-items: center; gap: 7px; }
.dl-filter__price > span {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	line-height: 1.15;
	color: var(--dl-muted);
	white-space: nowrap;
}
/* Native chevron dropped for a gold one; color-scheme keeps the options panel
   dark on the platforms that honour it rather than a white OS list on black. */
.dl-filter__price select {
	-webkit-appearance: none;
	appearance: none;
	padding: 9px 34px 9px 14px;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background-color: rgba(255, 255, 255, .03);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23c9a84c' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 13px center;
	background-size: 10px 7px;
	color: var(--dl-cream);
	color-scheme: dark;
	font-family: inherit;
	font-size: .85rem;
	line-height: 1.2;
	cursor: pointer;
	transition: border-color .25s var(--dl-ease), background-color .25s var(--dl-ease);
}
@media (hover: hover) {
	.dl-filter__price select:hover { border-color: var(--dl-gold); background-color: rgba(201, 168, 76, .07); }
}
.dl-filter__price select:focus { outline: none; border-color: var(--dl-gold); background-color: rgba(201, 168, 76, .07); }
/* Firefox and Windows still paint the popup from the OS; this at least keeps it dark */
.dl-filter__price select option { background: #0d0d11; color: var(--dl-cream); }
.dl-filter__count { margin: 0; margin-left: auto; font-size: .82rem; color: var(--dl-gold-lt); }
/*
 * Idle, the count is empty — but an empty flex item still claims a line and the
 * 12px row gap that comes with it, so the space under the Max hourly row ran to
 * 25px against 12px above it. Dropping it from the flow when it has nothing to
 * say balances the two. The JS writes '' when not filtering, so this switches
 * itself back on the moment there is a result to report.
 */
.dl-filter__count:empty { display: none; }
.dl-filter__clear {
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background: none;
	color: var(--dl-muted);
	font-family: inherit;
	font-size: .78rem;
	padding: 8px 14px;
	cursor: pointer;
	transition: color .25s var(--dl-ease), border-color .25s var(--dl-ease), background-color .25s var(--dl-ease);
}
/* the same gold wash every other pill on the site uses, rather than its own
   one-off of cream text on a bare border. Guarded, so iOS cannot leave it
   latched on after a tap. */
@media (hover: hover) {
	.dl-filter__clear:hover {
		color: var(--dl-gold-lt);
		border-color: var(--dl-gold);
		background-color: rgba(201, 168, 76, .07);
	}
}
.dl-filter__clear:active {
	color: var(--dl-gold-lt);
	border-color: var(--dl-gold);
	background-color: rgba(201, 168, 76, .1);
}

/* one dropdown per facet, four across on desktop */
.dl-filter__selects {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 8px;
}
.dl-filter__select { display: block; min-width: 0; }
.dl-filter__picker {
	-webkit-appearance: none;
	appearance: none;
	width: 100%;
	padding: 10px 32px 10px 14px;
	border: 1px solid var(--dl-line);
	border-radius: 999px;
	background-color: rgba(255, 255, 255, .03);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23c9a84c' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 13px center;
	background-size: 10px 7px;
	color: var(--dl-cream);
	color-scheme: dark;
	font-family: inherit;
	font-size: .85rem;
	/*
	 * Must match .dl-filter__price select. Without it the select inherits the
	 * theme's 24px line-height, which cannot fit inside a 40px border-box once
	 * 10px of padding and two borders are taken out — the line box overflowed
	 * downward and the label sat low while the chevron stayed centred.
	 */
	line-height: 1.2;
	cursor: pointer;
	transition: border-color .25s var(--dl-ease), background-color .25s var(--dl-ease);
}
@media (hover: hover) {
	.dl-filter__picker:hover { border-color: var(--dl-gold); background-color: rgba(201, 168, 76, .07); }
}
.dl-filter__picker:focus { outline: none; border-color: var(--dl-gold); background-color: rgba(201, 168, 76, .07); }
.dl-filter__picker option { background: #0d0d11; color: var(--dl-cream); }

/* what is currently selected, as removable pills */
.dl-filter__active {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: var(--sp-3);
	padding-top: var(--sp-3);
	border-top: 1px solid var(--dl-line);
}
.dl-filter__pill {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 6px 8px 6px 13px;
	border: 1px solid var(--dl-gold);
	border-radius: 999px;
	background: linear-gradient(180deg, #f0d98c, var(--dl-gold));
	color: #14100a;
	font-family: inherit;
	font-size: .78rem;
	font-weight: 600;
	cursor: pointer;
	transition: opacity .2s var(--dl-ease);
}
/* Brighten the gold rather than fading the pill. opacity dropped the label's
   contrast along with everything else, so hovering made it harder to read the
   thing you were about to remove. The text stays dark throughout. */
@media (hover: hover) {
	.dl-filter__pill:hover {
		background: linear-gradient(180deg, #f7e8b4, #d9b95f);
		border-color: var(--dl-gold-lt);
		color: #14100a;
	}
}
.dl-filter__pill:active {
	background: linear-gradient(180deg, var(--dl-gold), #b08f3c);
	border-color: var(--dl-gold);
	color: #14100a;
}
/*
 * Drawn, not typed.
 *
 * The multiplication sign sits high in its em box, so centring the line box
 * still left it riding above the middle of the circle — no amount of flex
 * alignment fixes that, because the glyph is off-centre within the box being
 * aligned. Two rotated bars are positioned from the centre outwards, so it is
 * exact at any size. The character stays in the markup and is simply not
 * rendered; the button already carries an aria-label saying what it removes.
 */
.dl-filter__x {
	position: relative;
	display: inline-flex;
	width: 16px; height: 16px;
	border-radius: 999px;
	background: rgba(20, 16, 10, .22);
	font-size: 0;
	line-height: 0;
}
.dl-filter__x::before,
.dl-filter__x::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 8px;
	height: 1.5px;
	border-radius: 1px;
	background: currentColor;
}
.dl-filter__x::before { transform: translate(-50%, -50%) rotate(45deg); }
.dl-filter__x::after  { transform: translate(-50%, -50%) rotate(-45deg); }
.dl-filter__empty { padding: var(--sp-6) 0; text-align: center; color: var(--dl-muted); }
.dl-filter__empty a { color: var(--dl-gold-lt); }

@media (max-width: 782px) {
	.dl-filter { padding: var(--sp-3); }
	.dl-filter__group { flex-direction: column; gap: 7px; }
	.dl-filter__label { flex: none; padding-top: 0; }
	.dl-filter__count { width: 100%; margin-left: 0; }
}
.dl-foot__tel {
	display: block;
	margin: 4px 0 6px;
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: clamp(1.5rem, 3.4vw, 2rem);
	line-height: 1.1;
	color: var(--dl-cream);
	letter-spacing: .01em;
	transition: color .3s var(--dl-ease);
}
@media (hover: hover) { .dl-foot__tel:hover { color: var(--dl-gold-lt); } }
.dl-foot__tel:active { color: var(--dl-gold-lt); }
.dl-foot__hours { margin: 0 0 var(--sp-3); font-size: .82rem; color: var(--dl-muted); }
.dl-foot__addr {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	margin: 0 0 var(--sp-4);
	padding-top: var(--sp-3);
	border-top: 1px solid var(--dl-line);
	font-size: .85rem;
	line-height: 1.55;
	color: var(--dl-muted);
}
.dl-foot__icon {
	flex: 0 0 auto;
	width: 15px; height: 15px;
	margin-top: 3px;                  /* sits on the first line, not above it */
	fill: var(--dl-gold);
	opacity: .8;
}

/* ── link columns ──
   <details> so a phone gets five closed rows instead of five open lists; JS
   forces them open above the breakpoint, where the space exists. */
.dl-foot__cols {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
	gap: var(--sp-3) var(--sp-5);
	padding: var(--sp-5) 0;
	border-top: 1px solid var(--dl-line);
	border-bottom: 1px solid var(--dl-line);
}
.dl-foot__col > summary {
	list-style: none;
	cursor: pointer;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--dl-gold);
	padding: 10px 0;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
}
.dl-foot__col > summary::-webkit-details-marker { display: none; }
/* chevron: shown only while the column is collapsible */
.dl-foot__col > summary::after {
	content: "";
	width: 7px; height: 7px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg) translateY(-2px);
	transition: transform .3s var(--dl-ease);
}
.dl-foot__col[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
.dl-foot__col ul { list-style: none; margin: 0; padding: 0 0 var(--sp-3); display: grid; gap: 9px; }
.dl-foot__col li a { font-size: .88rem; color: var(--dl-muted); transition: color .25s var(--dl-ease); }
@media (hover: hover) { .dl-foot__col li a:hover { color: var(--dl-gold-lt); } }
.dl-foot__col li a:active { color: var(--dl-gold-lt); }
/* the gold is enough to set it apart from the terms above it */
.dl-foot__more a { color: var(--dl-gold-lt) !important; font-weight: 400; }

.dl-foot__bottom {
	padding-top: var(--sp-4);
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: var(--sp-3);
	font-size: .8rem;
	color: var(--dl-muted);
}
.dl-foot__bottom p { margin: 0; }
.dl-foot__legal { font-size: .72rem; opacity: .65; }

/* Plain small text links, centred between the copyright and the legal line.
   Deliberately not pills: this row is the quiet one, and three bordered
   buttons in it pulled more attention than the booking number above. */
.dl-foot__links {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--sp-3);
}
.dl-foot__links a {
	font-size: .8rem;
	color: var(--dl-muted);
	transition: color .25s var(--dl-ease);
}
@media (hover: hover) { .dl-foot__links a:hover { color: var(--dl-gold-lt); } }
.dl-foot__links a:active { color: var(--dl-gold-lt); }

/* desktop: columns are always open, so the summary stops behaving like a button */
@media (min-width: 783px) {
	.dl-foot__col > summary { cursor: default; }
	.dl-foot__col > summary::after { display: none; }
}

/* ── supporting copy laid out as cards, not a wall of text ── */
.dl-copygrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--sp-3); }
.dl-copygrid h3 {
	margin: 0 0 10px;
	font-size: 1.12rem;
	color: var(--dl-gold-lt);
}
.dl-copygrid p { margin: 0 0 10px; font-size: .93rem; color: var(--dl-text); }
.dl-copygrid p:last-child { margin-bottom: 0; }
.dl-copygrid a { color: var(--dl-gold-lt); border-bottom: 1px solid rgba(201,168,76,.28); }
@media (hover: hover) { .dl-copygrid a:hover { border-bottom-color: var(--dl-gold); } }

/* ── escorts near me: areas grouped by region ── */
.dl-region { margin-bottom: var(--sp-5); }
.dl-region:last-child { margin-bottom: 0; }
.dl-region__title {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	margin: 0 0 var(--sp-3);
	padding-bottom: var(--sp-2);
	border-bottom: 1px solid var(--dl-line);
	font-size: 1.25rem;
	color: var(--dl-cream);
}

/* ── journal ── */
.dl-post__date { margin: 0 0 6px; font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: var(--dl-muted); }
.dl-post__excerpt { margin: 6px 0 0; font-size: .88rem; color: var(--dl-muted); }
.dl-post .dl-card__title { font-size: 1.1rem; line-height: 1.3; }
.dl-post__hero {
	margin: 0 0 var(--sp-4);
	border-radius: var(--dl-radius);
	overflow: hidden;
	border: 1px solid var(--dl-line);
}
.dl-post__hero img { display: block; width: 100%; height: auto; }
.dl-post__body { padding: clamp(var(--sp-4), 3vw, var(--sp-6)); }
.dl-article-page .dl-post__date { justify-content: center; }

/* ── duo / trio combination cards ──
   The pairing is the unit, so the faces sit together as one object and the price
   is the pair's, not each girl's. */
.dl-combos { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--sp-3); }
.dl-combo {
	position: relative;
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius);
	overflow: hidden;
	background: linear-gradient(180deg, #0c0c10, #08080a);
	transition: border-color .3s var(--dl-ease);
}
@media (hover: hover) { .dl-combo:hover { border-color: rgba(201,168,76,.5); } }

.dl-combo__tag {
	position: absolute;
	bottom: 10px; right: 10px;
	z-index: 2;
	box-shadow: 0 2px 10px rgba(0, 0, 0, .45);   /* lifts it off a busy photo */
	padding: 4px 10px;
	border-radius: 999px;
	font-size: 9px;
	font-weight: 700;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: #14100a;
	background: linear-gradient(135deg, #ffed8c, var(--dl-gold));
}
/* one strip of faces, split evenly however many there are */
.dl-combo__faces { position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 2px; }
.dl-combo__face { display: block; position: relative; overflow: hidden; aspect-ratio: 3 / 4; background: var(--dl-surface-3); }
.dl-combo__face img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%; display: block; transition: transform .7s var(--dl-ease-out); }
@media (hover: hover) { .dl-combo__face:hover img { transform: scale(1.06); } }

.dl-combo__body { padding: var(--sp-3); }
.dl-combo__names { margin: 0 0 4px; font-size: 1.05rem; line-height: 1.3; color: var(--dl-cream); }
.dl-combo__names a { color: inherit; }
@media (hover: hover) { .dl-combo__names a:hover { color: var(--dl-gold-lt); } }
.dl-combo__meta { margin: 0 0 6px; font-size: .78rem; color: var(--dl-muted); }
.dl-combo__price { margin: 0; font-size: .95rem; font-weight: 600; color: var(--dl-gold-lt); }
.dl-combo__price span { font-weight: 400; font-size: .74rem; color: var(--dl-muted); }

@media (max-width: 600px) {
	.dl-combos { grid-template-columns: 1fr; }
	.dl-combo__body { padding: var(--sp-3) 14px; }
	.dl-combo__names { font-size: .98rem; }
}

/* ── booking page ── */
.dl-btn--tel { font-size: 13px; letter-spacing: .12em; text-transform: none; }
/* The note belongs to the number above it, so it sits close to that and keeps a
   clear gap before the next button — otherwise it reads as a label for "Book her". */
.dl-booking__callnote { margin: 12px 0; font-size: .74rem; color: var(--dl-muted); text-align: center; }
/* the tel button gives up its own bottom margin when the note follows it */
.dl-booking .dl-btn--tel { margin-bottom: 0; }

.dl-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-3); }
.dl-step { padding-top: var(--sp-5); }
.dl-step__n {
	display: block;
	font-family: "Cormorant Garamond", Georgia, serif;
	font-size: 1.7rem;
	line-height: 1;
	color: var(--dl-gold);
	opacity: .55;
	margin-bottom: var(--sp-2);
}
.dl-step__title { font-size: 1.15rem; margin: 0 0 10px; color: var(--dl-cream); }
.dl-step p { margin: 0; font-size: .92rem; color: var(--dl-text); }

.dl-callbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--sp-4);
}
/* The text block takes the row; the phone button keeps only what it needs. Without
   this the block sized to its content and a 60ch cap on the paragraph held it to
   557px inside a 1098px card, so it broke to three lines with 541px sitting empty
   to its right. min-width:0 lets a flex item wrap below its content width. */
/* Only while the bar is a row. Below 600px it becomes a column, and flex-basis
   is measured along the main axis — so the same 46rem that sets a width here
   would set a 736px HEIGHT there, leaving 600px of empty card under the text. */
@media (min-width: 601px) {
	.dl-callbar > div { flex: 1 1 46rem; min-width: 0; }
	.dl-callbar .dl-btn { flex: 0 0 auto; }
}
.dl-callbar p { margin: 6px 0 0; color: var(--dl-muted); font-size: .92rem; }
@media (max-width: 600px) {
	.dl-callbar { flex-direction: column; align-items: stretch; }
	.dl-callbar .dl-btn { width: 100%; }
}

/* ==========================================================================
   10. FORMS
   ========================================================================== */
input[type="text"], input[type="email"], input[type="search"],
input[type="url"], input[type="tel"], textarea, select {
	background: var(--dl-surface-2);
	border: 1px solid var(--dl-line);
	border-radius: var(--dl-radius-sm);
	color: var(--dl-cream);
	padding: 12px 15px;
	transition: border-color .3s var(--dl-ease), box-shadow .3s var(--dl-ease);
}
input:focus, textarea:focus, select:focus {
	border-color: var(--dl-gold);
	box-shadow: 0 0 0 3px rgba(201, 168, 76, .14);
	outline: none;
}
::placeholder { color: var(--dl-muted); opacity: 1; }

/* ==========================================================================
   11. SCROLLBAR + MISC POLISH
   ========================================================================== */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--dl-black); }
::-webkit-scrollbar-thumb {
	background: linear-gradient(180deg, var(--dl-gold-dp), var(--dl-surface-3));
	border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--dl-gold); }

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

/* ==========================================================================
   12. RESPONSIVE / MOBILE — iPhone-first
   ========================================================================== */

/* iOS: stop Safari inflating text in landscape, and respect the notch */
html { -webkit-text-size-adjust: 100%; }
body { overflow-x: hidden; }             /* nothing should ever scroll sideways */
.dl-shell { padding-inline: max(18px, env(safe-area-inset-left)) max(18px, env(safe-area-inset-right)); }

/* Wide content scrolls inside itself rather than breaking the page — but only
   where it actually needs to. `display:block` on a table stops it filling its
   container, so this must never apply on desktop. */
@media (max-width: 600px) {
	.dl-article table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}
.dl-article pre, .dl-article img { max-width: 100%; }

@media (max-width: 900px) {
	.dl-hero { min-height: 52vh; }
	.dl-profile__cards { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
	:root { --dl-radius: 12px; }

	/* Exactly two per row. auto-fill falls back to one when the grid sits in a
	   narrower container (the guide sections do), so pin the count rather than
	   leave it to the algorithm. minmax(0,1fr) stops content forcing an overflow. */
	.dl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); }
	.dl-duo  { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	/* Two across. auto-fit was asking for 150px a column, and two of those plus
	   the gap needs 308px against the ~300px this panel actually has — so it fell
	   to one per row and the four dropdowns took half the screen. minmax(0,1fr)
	   lets them size to what is there instead of holding out for 150px. */
	.dl-filter__selects { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	/* The journal index, and the "more from the journal" row under an article.
	   These cards are all text, and two columns of it on a phone gives four-word
	   lines and a wall of hyphenation. One per row reads. */
	.dl-journal .dl-grid,
	.dl-article-page .dl-grid { grid-template-columns: 1fr; gap: var(--sp-3); }

	.dl-card__body { padding: var(--sp-3); gap: 4px; }
	/* Her name is the point of the card, and at 1rem in a serif with a small
	   x-height it was barely leading the area line under it. */
	.dl-card__title { font-size: 1.18rem; line-height: 1.2; }
	.dl-card__excerpt { display: none; }         /* excerpt is noise at this width */
	.dl-listing__meta { font-size: .74rem; }
	.dl-listing__price { font-size: .84rem; margin-bottom: 8px; }
	.dl-card__more { font-size: 10px; }
	.dl-badge { font-size: 8.5px; padding: 3px 7px; }
	.dl-badges { top: 7px; left: 7px; right: 7px; gap: 4px; }

	.dl-hero { min-height: 46vh; }
	.dl-hero__title { font-size: clamp(1.9rem, 9vw, 2.6rem); }
	.dl-hero__count strong { font-size: 1.25rem; }
	.dl-hero__cta { flex-direction: column; }
	.dl-hero__cta .dl-btn { width: 100%; }

	.dl-lede { font-size: .95rem; }
	/*
	 * Sized against a 16px root, now that the root shrink above is undone.
	 * These were briefly much larger numbers, compensating per-component for
	 * the 91.2% root; with the cause fixed they go back to ordinary values.
	 * The article was previously set SMALLER on a phone than on desktop
	 * (.98rem against a 1.06rem base), which was backwards to begin with.
	 */
	.dl-article { font-size: 1.1rem; line-height: 1.68; }
	.dl-article h2 { font-size: 1.8rem; }
	.dl-article h3 { font-size: 1.5rem; }
	.dl-btn { padding: 13px 24px; }

	.dl-profile__name { font-size: clamp(1.8rem, 8vw, 2.3rem); }
	.dl-card-lux { padding: 16px; }
	/* they're links, so on touch they keep enough height to hit reliably —
	   shrinking these the way the desktop pills shrink makes them fiddly */
	.dl-likes li { font-size: .7rem; }
	.dl-likes li a, .dl-likes li:not(.is-link) { padding: 5px 9px; }
	.dl-stats dt, .dl-stats dd { font-size: .82rem; }

	.dl-nearby li a { padding: 7px 13px; font-size: .8rem; }
	.dl-guide-promo { padding: 22px 18px; }
	.dl-guide-promo__links { flex-direction: column; gap: 10px; }

	/*
	 * No font-size here on purpose: the questions now inherit the base 1.2rem,
	 * which lands at 19.2px once the root shrink is undone. They used to be
	 * knocked down to 1.05rem, putting them BELOW the body copy in a serif with
	 * a small x-height, which is why they read as the smallest thing on screen.
	 * Only the tighter padding is worth keeping on a narrow screen.
	 */
	.dl-faq__q { padding: 16px 2px; }
	.dl-crumbs { font-size: .75rem; }
}

/* Touch devices: kill hover states that stick, give real tap feedback instead.
   This is the fix for the "gold border stuck on the first card" class of bug. */
@media (hover: none) {
	/*
	 * Every ring goes back down on a stuck :hover.
	 *
	 * iOS latches :hover on to whatever was tapped last, so without these the
	 * ring stayed lit on the tile you just left — which is exactly the flicker
	 * the duo cards were showing. The resting border comes back with it, so a
	 * card is never left with no edge at all.
	 */
	.dl-card:hover { transform: none; box-shadow: none; }
	.dl-card:hover::before { opacity: 0; }
	.dl-duo__item:hover { transform: none; border-color: var(--dl-line); }
	.dl-arealinks li a:hover,
	.dl-nearby li a:hover { border-color: var(--dl-line); }
	.dl-likes li.is-link:hover { border-color: rgba(201,168,76,.28); }
	.dl-likes li.is-link:hover::before,
	.dl-arealinks li a:hover::before,
	.dl-nearby li a:hover::before,
	.dl-duo__item:hover::before { opacity: 0; }

	/*
	 * No transition on the ring here. Measured, not assumed.
	 *
	 * The gradient is painted through a mask, and WebKit will not begin the fade
	 * until it has rasterised that layer. Sampled on an iPhone every 100ms, the
	 * opacity sat at 0 for 300ms on a duo tile and 400ms on a listing card, then
	 * snapped to 1 — not a fade at all, a stall followed by a jump. A tap is over
	 * in about 100ms, so the ring never appeared and the press read as broken.
	 *
	 * Dropping the transition skips the wait entirely: measured at full opacity
	 * within 60ms. Nothing is lost — there was never a visible fade to keep.
	 */
	.dl-card::before,
	.dl-likes li.is-link::before,
	.dl-arealinks li a::before,
	.dl-nearby li a::before,
	.dl-duo__item::before { transition: none; }

	/* The elements themselves too, for the same reason. The resting border has to
	   get out of the way the instant the ring arrives, and a .25s border-color
	   fade meant the old gold was still sitting under the new ring for the whole
	   length of a tap — which is precisely the doubled edge that kept showing. */
	.dl-likes li,
	.dl-arealinks li a,
	.dl-nearby li a,
	.dl-duo__item { transition: none; }

	/*
	 * The gold-to-teal edge on press.
	 *
	 * It is only revealed on :hover higher up, inside (hover: hover) and
	 * (pointer: fine), so on a phone the gradient border never appeared at all —
	 * a corner accent that was desktop-only without anyone deciding it should be.
	 *
	 * :active is paired with :hover rather than written alone because iOS leaves
	 * :hover stuck on the last element tapped, which is the very thing the two
	 * rules above exist to undo. Both states are set during a real tap, and at
	 * equal specificity the neutraliser would win on order. :hover:active outranks
	 * it outright, so the press lands whichever way the browser reports itself.
	 *
	 * Transition cut right down: a tap is over in about a tenth of a second, and
	 * the 450ms fade never got far enough to be seen.
	 */
	.dl-card:active,
	.dl-card:hover:active {
		transform: scale(.985);
		border-color: transparent;
		box-shadow: var(--dl-glow-gold);
	}
	.dl-card:active::before,
	.dl-card:hover:active::before { opacity: 1; }

	/*
	 * .is-pressed, set from JS on touchstart, is what actually carries this on a
	 * listing card — the :active rules above only cover the cards you can press
	 * directly.
	 *
	 * A tap on a listing card lands on the <a class="dl-card__img"> inside it, so
	 * :active is a state propagated up from a child. Measured on WebKit, that
	 * propagated state restyles the card itself (the glow lands) but never its
	 * ::before, so the gradient edge stayed at zero however the rule was written
	 * — :active, :hover:active and :has(:active) all failed the same way while the
	 * box-shadow beside them worked. A real class forces a full recalculation and
	 * the pseudo-element repaints. Listed after the :hover neutraliser above so it
	 * wins on order at equal specificity.
	 */
	.dl-card.is-pressed {
		transform: scale(.985);
		border-color: transparent;
		box-shadow: var(--dl-glow-gold);
	}
	.dl-duo__item.is-pressed { transform: scale(.985); border-color: transparent; }
	.dl-likes li.is-pressed,
	.dl-arealinks li a.is-pressed,
	.dl-nearby li a.is-pressed { border-color: transparent; }

	/* Listed last so they outrank the :hover neutralisers above at equal
	   specificity. Every one of these is tapped through a child element — the
	   chip's own <a>, the tile's photo — and a propagated :active restyles the
	   element but never repaints its ::before, so the class is what carries it. */
	.dl-card.is-pressed::before,
	.dl-duo__item.is-pressed::before,
	.dl-likes li.is-pressed::before,
	.dl-arealinks li a.is-pressed::before,
	.dl-nearby li a.is-pressed::before { opacity: 1; }

	/* the ring is the press state now; the covers variant adds its photo outline
	   on the same class */
	.dl-nearby--covers li a:hover .dl-cloud__pic { box-shadow: none; }
	.dl-btn:active { transform: scale(.98); }

	/*
	 * Services get the area chips' structure, because that is why theirs works.
	 *
	 * An area chip is <li><a>, with the border and the ring both on the <a> —
	 * the element the finger lands on. A service chip is the same markup, but
	 * the border and ring were on the <li> while the tap landed on the <a>
	 * inside it, so the press had to propagate up a level, and WebKit restyles
	 * the element without repainting its ::before when it does. Nothing to do
	 * with them being smaller.
	 *
	 * Moving both onto the <a> here puts the state on the tapped element. The
	 * <li> gives up its border rather than hiding it, so the <a>'s lands in
	 * exactly the same place and nothing shifts. Touch only — the desktop hover
	 * already works from the <li> and is left alone.
	 */
	.dl-likes li.is-link { border: 0; }
	.dl-likes li.is-link::before { display: none; }

	.dl-likes li.is-link a {
		position: relative;
		border: 1px solid rgba(201,168,76,.28);
		border-radius: 5px;
		transition: none;
	}
	.dl-likes li.is-link a::before {
		content: "";
		position: absolute;
		inset: 0;
		border-radius: inherit;
		padding: 1px;
		background: linear-gradient(135deg, var(--dl-gold-lt), transparent 35%, transparent 65%, var(--dl-teal));
		-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
		mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
		-webkit-mask-composite: xor;
		mask-composite: exclude;
		opacity: 0;
		transition: none;
		pointer-events: none;
		z-index: 3;
	}
	.dl-likes li.is-link a.is-pressed { border-color: transparent; }
	.dl-likes li.is-link a.is-pressed::before { opacity: 1; }
}

/* Tap targets: WCAG wants ~44px minimum. */
@media (pointer: coarse) {
	.dl-btn, .dl-faq__q, .dl-nearby li a, .main-header-menu a { min-height: 44px; }
	.dl-nearby li a { display: flex; align-items: center; }
}

/* ==========================================================================
   13. REDUCED MOTION — respect the OS setting
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
		scroll-behavior: auto !important;
	}
	.dl-js .dl-reveal { opacity: 1; transform: none; }
	.dl-hero__flourish { width: 190px; }
}
