/*
 * DJ Orel Sasportas — landing page.
 *
 * Everything is scoped under #djo-root so nothing leaks into the host theme,
 * and nothing the theme ships can reach in.
 *
 * IMPORTANT — the default state of every element here is its FINAL, visible
 * state. Pre-animation ("before") states live behind `.djo-js`, which app.js
 * adds only once GSAP is confirmed present. Consequences:
 *   - the block editor preview (which never loads viewScript) shows a complete page
 *   - a blocked CDN or JS-off degrades to a complete page
 *   - no flash-of-invisible-content is possible
 */

/* ========================================================================== */
/* Tokens                                                                     */
/* ========================================================================== */

#djo-root{
	/* palette — strict black & white. */
	--djo-bg: #000;
	--djo-fg: #fff;
	--djo-dim: rgba(255, 255, 255, 0.56);
	--djo-faint: rgba(255, 255, 255, 0.14);
	--djo-hair: rgba(255, 255, 255, 0.18);
	--djo-panel: #0a0a0a;

	/* the one functional colour on the page, per brief. */
	--djo-wa: #25d366;

	--djo-gap: 6px;
	--djo-pad: clamp(18px, 5vw, 84px);
	--djo-sec-y: clamp(72px, 9vw, 148px);
	/*
	 * The gap between a section's head and the block under it. Every section
	 * had drifted to its own value (38/42/44px floors, 78/80/82/84px ceilings)
	 * which read as uneven spacing down the page. One token, one rhythm.
	 */
	--djo-head-gap: clamp(40px, 6vw, 80px);

	/* type */
	--djo-hebrew: 'Heebo', 'Assistant', system-ui, 'Segoe UI', Arial, sans-serif;
	--djo-body: 'Assistant', 'Heebo', system-ui, 'Segoe UI', Arial, sans-serif;
	--djo-latin: 'Anton', 'Heebo', Impact, 'Haettenschweiler', sans-serif;
	/* The Didone in the monogram and the menu's numerals — one face, two jobs. */
	--djo-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;

	--djo-h1: clamp(2.9rem, 10.5vw, 9.5rem);
	--djo-h2: clamp(2.1rem, 6.4vw, 5.6rem);

	/* weighted easing — nothing on this page uses a browser default curve. */
	--djo-ease: cubic-bezier(0.16, 0.84, 0.3, 1);
	--djo-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/*
 * The RTL full-bleed guard. Scoped to the canvas template's body class so it
 * can never affect the rest of the site. On RTL pages a stray overflow shows up
 * as a gap on the LEFT specifically, which is easy to miss when testing in LTR.
 */
body.djo-canvas{
	margin: 0;
	background: #000;
	overflow-x: hidden;
}

body.djo-canvas .alignfull,
body.djo-canvas .wp-block-acf-djo-landing{
	max-width: none;
	margin-inline: 0;
}

/* ========================================================================== */
/* Base                                                                       */
/* ========================================================================== */

#djo-root{
	position: relative;
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
	/* clip, not hidden: does not create a scroll container the way hidden does. */
	overflow-x: clip;
	background: var(--djo-bg);
	color: var(--djo-fg);
	font-family: var(--djo-body);
	font-size: 16px;
	line-height: 1.65;
	text-align: right;
	direction: rtl;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

/*
 * Element resets are wrapped in :where() so they carry ZERO specificity.
 *
 * Written as plain `#djo-root p { margin: 0 }` they inherit the ID's
 * specificity (1,0,1) and silently beat any component class — which had
 * already broken the CTA button colours, the carousel dots, and the centring
 * of centred section copy. :where() keeps the scoping without the weight, so
 * a `.djo-thing { … }` rule always wins over the reset, as you would expect.
 */
#djo-root *,
#djo-root *::before,
#djo-root *::after{
	box-sizing: inherit;
}

#djo-root :where(img, video){
	display: block;
	max-width: 100%;
}

#djo-root :where(picture){
	display: contents;
}

/*
 * Inside a media frame the <picture> becomes a real box, 112% of the frame's
 * height and offset up by 6%.
 *
 * That extra 12% is the parallax travel: the frame never moves (so it can't
 * drift into the copy beneath it, which is what translating the frame itself
 * used to do), the picture slides within it, and no edge is ever exposed.
 * It also separates ownership of `transform` — GSAP drives the <picture>,
 * CSS drives the <img> on hover — so the two never overwrite each other.
 */
#djo-root .djo-mosaic__cell picture,
#djo-root .djo-about__media picture,
#djo-root .djo-card__media picture{
	display: block;
	position: relative;
	top: -6%;
	width: 100%;
	height: 112%;
}

#djo-root :where(a){
	color: inherit;
	text-decoration: none;
}

#djo-root :where(button){
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	cursor: pointer;
}

#djo-root :where(p){
	margin: 0;
}

#djo-root :where(h1, h2, h3){
	margin: 0;
	font-family: var(--djo-hebrew);
	font-weight: 900;
	line-height: 0.92;
	letter-spacing: -0.02em;
}

#djo-root :focus-visible{
	outline: 2px solid var(--djo-fg);
	outline-offset: 3px;
}

#djo-root .djo-skip{
	position: absolute;
	top: 0;
	inset-inline-start: 0;
	z-index: 999;
	padding: 12px 20px;
	background: #fff;
	color: #000;
	/* Off-screen without a huge offset — a negative inset under RTL resolves to
	   the right edge and reads as thousands of pixels of phantom overflow. */
	transform: translateY(-120%);
	transition: transform 0.2s var(--djo-ease);
}

#djo-root .djo-skip:focus{
	transform: translateY(0);
}

/*
 * Media sits at 70% colour — a real desaturation via grayscale(0.3), not a
 * saturation dial, so the darks stay put and the page keeps its black & white
 * discipline while the footage still reads as colour.
 *
 * On hover the picture returns to full colour and pushes in 5%. The frame is
 * fixed: only the media inside scales, so nothing shifts in the layout.
 *
 * The hero and the product shots are deliberately exempt — the hero has to
 * land at full strength, and merchandise has to show its true colour.
 */
#djo-root .djo-media,
#djo-root .djo-mosaic__cell img,
#djo-root .djo-about__media img,
#djo-root .djo-clips__item video,
#djo-root .djo-band video{
	filter: grayscale(0.3) contrast(1.04);
	transition: filter 0.55s var(--djo-ease), transform 0.85s var(--djo-ease);
}

#djo-root .djo-mosaic__cell:hover img,
#djo-root .djo-about__media:hover img,
#djo-root .djo-clips__item:hover video,
#djo-root .djo-band:hover video{
	filter: grayscale(0) contrast(1.04);
	transform: scale(1.05);
}

/* Exempt: hero grid, hero video, product shots — merchandise must show its
   true colour, and that includes the flag clip. */
#djo-root .djo-cell__img,
#djo-root .djo-hero__video,
#djo-root .djo-card__media img,
#djo-root .djo-card__media video{
	filter: contrast(1.04) saturate(1.03);
}

/* ========================================================================== */
/* Cursor                                                                     */
/*                                                                            */
/* A white disc that trails the pointer and deforms with its velocity —       */
/* stretching along the direction of travel and thinning across it, so a fast */
/* sideways flick reads as a horizontal oval. mix-blend-mode: difference means */
/* it inverts whatever it crosses, so it stays visible over both the black    */
/* grounds and the photography without needing a second colour.               */
/* Pointer-fine devices only; see the JS guard.                               */
/* ========================================================================== */

.djo-cursor{
	position: fixed;
	top: 0;
	left: 0;
	z-index: 120;
	width: 26px;
	height: 26px;
	margin: -13px 0 0 -13px;
	border-radius: 50%;
	background: #fff;
	pointer-events: none;
	mix-blend-mode: difference;
	will-change: transform;
	opacity: 0;
	transition: opacity 0.3s linear, width 0.35s var(--djo-ease), height 0.35s var(--djo-ease);
}

.djo-cursor.is-live{
	opacity: 1;
}

/* Over anything clickable the disc opens up into a ring. */
.djo-cursor.is-hot{
	width: 62px;
	height: 62px;
	margin: -31px 0 0 -31px;
	background: transparent;
	border: 1.5px solid #fff;
}

/*
 * Over the menu, drop the blend. `difference` makes the compositor re-blend the
 * cursor against everything under it every frame, and with the panel up that is
 * a translucent full-screen layer sitting over a playing video — easily the most
 * expensive composite on the page. A ticker-driven cursor shows those dropped
 * frames as lag and smear, not as honest stutter.
 *
 * Nothing is lost: white on a near-black sheet is already white, which is all
 * the inversion was buying here.
 *
 * The cursor is appended to <body> after #djo-root, so the sibling combinator
 * reaches it — it is not inside the block.
 */
#djo-root.is-menu-open ~ .djo-cursor{
	mix-blend-mode: normal;
}

/* The real pointer stays hidden only while ours is actually running. */
#djo-root.has-cursor,
#djo-root.has-cursor a,
#djo-root.has-cursor button{
	cursor: none;
}

/* ========================================================================== */
/* Atmosphere                                                                 */
/*                                                                            */
/* Pure #000 across seven full-height sections reads flat and cheap — it is a */
/* void rather than a ground. These layers give the black some depth without  */
/* introducing colour: a film grain over the whole frame, soft light bleeds   */
/* anchored per section, a hairline grid, and an oversized monogram           */
/* watermark. All of them are decorative and pointer-transparent.             */
/* ========================================================================== */

/* Film grain. One fixed layer over the entire page, at the threshold of
   visibility — it mostly kills the banding that flat black shows on wide
   gradients, and lends the whole thing a printed quality. */
#djo-root::after{
	content: '';
	position: fixed;
	inset: 0;
	z-index: 100;
	pointer-events: none;
	opacity: 0.055;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Soft light bleed. Sized and placed per section so the eye is led down the
   page rather than meeting a uniform black wall each time. */
#djo-root .djo-sec::before{
	content: '';
	position: absolute;
	z-index: 0;
	pointer-events: none;
	width: min(1100px, 105%);
	aspect-ratio: 1;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.018) 42%, transparent 68%);
}

#djo-root .djo-sec--parties::before{
	top: -18%;
	inset-inline-start: -22%;
}

#djo-root .djo-sec--weddings::before{
	bottom: -22%;
	inset-inline-end: -25%;
}

#djo-root .djo-sec--about::before{
	top: 8%;
	inset-inline-end: -30%;
	width: min(880px, 90%);
}

#djo-root .djo-sec--reviews::before{
	top: 50%;
	inset-inline-start: 50%;
	transform: translate(50%, -50%);
	width: min(900px, 110%);
}

#djo-root .djo-sec--contact::before{
	bottom: -30%;
	inset-inline-start: 50%;
	transform: translateX(50%);
}

/* A hairline column grid behind the product row — structure, not decoration:
   it makes the cards read as sitting on a system. */
#djo-root .djo-sec--packages::after{
	content: '';
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background-image: repeating-linear-gradient(
		to right,
		rgba(255, 255, 255, 0.045) 0 1px,
		transparent 1px calc(100% / 6)
	);
	mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
	-webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
}

/* An oversized monogram sunk into the background of the bio. */
#djo-root .djo-sec--about::after{
	content: '';
	position: absolute;
	z-index: 0;
	pointer-events: none;
	inset-inline-start: -6%;
	bottom: 6%;
	width: min(560px, 55%);
	aspect-ratio: 1;
	opacity: 0.05;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M23 25 H77 L87 41 L50 85 L13 41 Z' fill='none' stroke='%23fff' stroke-width='3'/%3E%3C/svg%3E");
}

/* Section content has to clear the atmosphere layers. */
#djo-root .djo-sec > *{
	position: relative;
	z-index: 1;
}

/* ========================================================================== */
/* Depth layers                                                               */
/*                                                                            */
/* The atmosphere above is static: it sits still while the page scrolls past, */
/* so the lower half of the site read as flat black behind flat content.      */
/* These layers add the missing parallax — two light fields per section that  */
/* travel at different rates, plus a drifting mote field. Nothing here is     */
/* content: it is all aria-hidden, pointer-transparent and pinned to z-index  */
/* 0, and every animation is inert under prefers-reduced-motion.              */
/* ========================================================================== */

/*
 * The clipping frame. Auras are deliberately larger than their section and
 * hang past its edges — without this they would widen the document and put a
 * horizontal scrollbar on the page.
 */
#djo-root .djo-depth{
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
	/* .djo-sec > * lifts every direct child to z-index 1; this must stay under. */
}

/* ---- aura: the travelling light fields ---------------------------------- */

#djo-root .djo-aura{
	position: absolute;
	display: block;
	aspect-ratio: 1;
	border-radius: 50%;
	pointer-events: none;
	background: radial-gradient(
		circle,
		rgba(255, 255, 255, 0.05),
		rgba(255, 255, 255, 0.014) 44%,
		transparent 70%
	);
	/* Scroll drift is written to the transform by app.js; the breathe below
	   rides on top of it via a separate scale on the inner gradient box. */
	will-change: transform;
	animation: djo-breathe 19s var(--djo-ease, ease-in-out) infinite alternate;
}

/*
 * Two per section at different sizes and offsets. The pair is what sells the
 * depth — one near, one far, moving at different rates as the page scrolls.
 */
#djo-root .djo-aura--a{
	width: min(760px, 82%);
	top: -14%;
	inset-inline-start: -18%;
}

#djo-root .djo-aura--b{
	width: min(560px, 62%);
	bottom: -20%;
	inset-inline-end: -14%;
	opacity: 0.75;
	animation-delay: -7s;
	animation-duration: 24s;
}

/* Reviews is centre-aligned, so its pair straddles the carousel instead of
   sitting in the corners, or the glow fights the text for the middle. */
#djo-root .djo-sec--reviews .djo-aura--a{
	top: -22%;
	inset-inline-start: -26%;
	width: min(680px, 74%);
}

#djo-root .djo-sec--reviews .djo-aura--b{
	bottom: -26%;
	inset-inline-end: -22%;
}

/* Contact closes the page, so its near field is bigger and sits low, pooling
   light under the links rather than behind them. */
#djo-root .djo-sec--contact .djo-aura--a{
	width: min(900px, 96%);
	top: auto;
	bottom: -34%;
	inset-inline-start: 50%;
	margin-inline-start: -48%;
}

@keyframes djo-breathe{
	from{ opacity: 0.62; }
	to{ opacity: 1; }
}

/* ---- motes: a slow drifting dust field ---------------------------------- */

#djo-root .djo-motes{
	position: absolute;
	inset: 0;
	pointer-events: none;
	/* Fades in and out at the section seams so the field never starts or stops
	   on a hard edge. */
	mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 82%, transparent);
	-webkit-mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 82%, transparent);
}

/*
 * Two tiled layers at different scales and speeds. One layer alone reads as a
 * texture sliding by; two at different rates read as particles at different
 * distances, which is the whole point.
 */
#djo-root .djo-motes::before,
#djo-root .djo-motes::after{
	content: '';
	position: absolute;
	inset-inline: 0;
	/* Tall enough that the loop is never visible inside the section box. */
	top: -60%;
	bottom: -60%;
	background-repeat: repeat;
	will-change: transform;
}

#djo-root .djo-motes::before{
	background-image:
		radial-gradient(1.6px 1.6px at 12% 14%, rgba(255, 255, 255, 0.5), transparent 62%),
		radial-gradient(1.2px 1.2px at 63% 27%, rgba(255, 255, 255, 0.38), transparent 62%),
		radial-gradient(1.7px 1.7px at 31% 58%, rgba(255, 255, 255, 0.44), transparent 62%),
		radial-gradient(1.1px 1.1px at 84% 69%, rgba(255, 255, 255, 0.34), transparent 62%),
		radial-gradient(1.5px 1.5px at 47% 88%, rgba(255, 255, 255, 0.42), transparent 62%);
	background-size: 380px 380px;
	animation: djo-motes-up 54s linear infinite;
}

#djo-root .djo-motes::after{
	background-image:
		radial-gradient(1px 1px at 22% 36%, rgba(255, 255, 255, 0.3), transparent 62%),
		radial-gradient(1.3px 1.3px at 71% 12%, rgba(255, 255, 255, 0.26), transparent 62%),
		radial-gradient(1px 1px at 55% 71%, rgba(255, 255, 255, 0.3), transparent 62%),
		radial-gradient(1.2px 1.2px at 8% 82%, rgba(255, 255, 255, 0.24), transparent 62%);
	background-size: 260px 260px;
	opacity: 0.7;
	animation: djo-motes-up 82s linear infinite reverse;
}

/* Travels exactly one tile, so the loop point is invisible. */
@keyframes djo-motes-up{
	from{ transform: translate3d(0, 0, 0); }
	to{ transform: translate3d(0, -380px, 0); }
}

#djo-root .djo-motes::after{
	animation-name: djo-motes-up-sm;
}

@keyframes djo-motes-up-sm{
	from{ transform: translate3d(0, 0, 0); }
	to{ transform: translate3d(0, -260px, 0); }
}

/* ========================================================================== */
/* Shared type                                                                */
/* ========================================================================== */

#djo-root .djo-line{
	display: block;
	overflow: hidden;
	/* Headline line-height is tighter than the em box, so the mask would clip
	   the tails of Hebrew finals (ן ך ף ץ ק). Reserve room, then take it back
	   so the lines still stack tight. */
	padding-bottom: 0.14em;
	margin-bottom: -0.14em;
}

#djo-root .djo-line__i{
	display: block;
}

#djo-root .djo-kicker{
	font-family: var(--djo-body);
	font-size: 0.78rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	color: var(--djo-dim);
	text-transform: uppercase;
}

#djo-root .djo-h2{
	font-family: var(--djo-hebrew);
	font-weight: 900;
	margin-top: 0.35em;
	font-size: var(--djo-h2);
}

#djo-root .djo-h2--xl{
	font-size: clamp(3rem, 11vw, 9rem);
}

#djo-root .djo-lede{
	max-width: 46ch;
	margin-top: 1.1em;
	font-size: clamp(1rem, 1.5vw, 1.2rem);
	font-weight: 300;
	color: var(--djo-dim);
}

/* ---- buttons: blocky, sharp-cornered, high contrast --------------------- */

#djo-root .djo-btn{
	display: inline-block;
	margin-top: 2em;
	padding: 1.05em 2.6em;
	font-family: var(--djo-body);
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	border: 1px solid var(--djo-fg);
	transition: background-color 0.4s var(--djo-ease), color 0.4s var(--djo-ease);
}

#djo-root .djo-btn--solid{
	background: var(--djo-fg);
	color: #000;
}

#djo-root .djo-btn--solid:hover{
	background: transparent;
	color: var(--djo-fg);
}

#djo-root .djo-btn--ghost{
	background: transparent;
	color: var(--djo-fg);
}

#djo-root .djo-btn--ghost:hover{
	background: var(--djo-fg);
	color: #000;
}

/* ========================================================================== */
/* Nav                                                                        */
/* ========================================================================== */

#djo-root .djo-nav{
	position: fixed;
	top: 0;
	inset-inline: 0;
	z-index: 60;
	display: flex;
	align-items: center;
	gap: clamp(12px, 3vw, 40px);
	padding: 14px var(--djo-pad);
	transition: background-color 0.5s var(--djo-ease), border-color 0.5s var(--djo-ease);
	border-bottom: 1px solid transparent;
}

#djo-root .djo-nav.is-stuck{
	background: rgba(0, 0, 0, 0.82);
	border-bottom-color: var(--djo-hair);
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
}

#djo-root .djo-nav__logo{
	flex: none;
	line-height: 0;
}

/*
 * Sized by HEIGHT, width left to find itself. Pinning both (the old 44x44)
 * squashed the gem back into a square.
 */
#djo-root .djo-nav__logo .djo-mark{
	width: auto;
	height: 42px;
}

#djo-root .djo-nav__cta{
	display: inline-flex;
	align-items: center;
	gap: 8px;
	/* The links that used to fill this space are gone; the CTA takes the slack
	   so the mark stays hard left and the CTA + burger stay hard right. */
	margin-inline-start: auto;
	padding: 0.72em 1.4em;
	font-size: 0.8rem;
	font-weight: 600;
	border: 1px solid var(--djo-hair);
	transition: border-color 0.35s var(--djo-ease), background-color 0.35s var(--djo-ease);
}

#djo-root .djo-nav__cta:hover{
	border-color: var(--djo-fg);
	background: rgba(255, 255, 255, 0.06);
}

/* The single permitted spot of colour on the entire page. */
#djo-root .djo-nav__cta .djo-ico,
#djo-root .djo-card__cta .djo-ico,
#djo-root .djo-link--wa .djo-ico{
	color: var(--djo-wa);
}

#djo-root .djo-ico{
	width: 20px;
	height: 20px;
	flex: none;
}

/* The burger is the navigation now — shown at every width, never a fallback. */
#djo-root .djo-burger{
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 6px;
	/* A full 44px square: the bars stay 22px, the target does not. */
	width: 44px;
	height: 44px;
	margin-inline-end: -10px;
}

#djo-root .djo-burger span{
	width: 22px;
}

#djo-root .djo-burger span{
	display: block;
	height: 1.5px;
	background: var(--djo-fg);
	transition: transform 0.4s var(--djo-ease), opacity 0.3s linear;
}

#djo-root .djo-burger.is-open span:nth-child(1){
	transform: translateY(3.75px) rotate(45deg);
}

#djo-root .djo-burger.is-open span:nth-child(2){
	transform: translateY(-3.75px) rotate(-45deg);
}

/* ---- menu overlay ------------------------------------------------------- */

/*
 * The panel is not quite opaque — but only just. At 0.9 the hero headline read
 * straight through it and fought the menu; 0.96 leaves the section underneath
 * as a suggestion of texture, which is what keeps a full-screen black sheet
 * feeling like the same site rather than a door slammed in front of it. Push it
 * to 1 for a solid panel; there is nothing else to change if you do.
 *
 * Open and closed are CSS states, not just [hidden]. The attribute goes on only
 * once the exit transition has finished, so the overlay can animate BOTH ways;
 * app.js owns that hand-off.
 */
#djo-root .djo-menu{
	position: fixed;
	inset: 0;
	z-index: 65;
	display: grid;
	place-items: center;
	padding: clamp(88px, 12vh, 124px) var(--djo-pad) clamp(36px, 6vh, 56px);
	background: rgba(0, 0, 0, 0.96);
	/* A tall list on a short laptop must scroll, not clip — but only ever
	   downwards: the band across the top is drawn wider than the viewport on
	   purpose and must be cropped by it, not scrolled to. */
	overflow-x: hidden;
	overflow-y: auto;
	overscroll-behavior: contain;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.45s var(--djo-ease), visibility 0s linear 0.45s;
}

#djo-root .djo-menu[hidden]{
	display: none;
}

#djo-root .djo-menu.is-open{
	opacity: 1;
	visibility: visible;
	transition: opacity 0.45s var(--djo-ease), visibility 0s;
}

/* ---- the overlay's own bar ---------------------------------------------- */

/*
 * Mark left, close right — the arrangement the design was drawn in, and the
 * mirror image of where an RTL page header keeps them. The page header fades
 * out underneath (see .is-menu-open, below) so the two never argue over the
 * same two corners.
 */
#djo-root .djo-menu__bar{
	position: fixed;
	inset: 0 0 auto 0;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 14px var(--djo-pad);
	pointer-events: none;
}

#djo-root .djo-menu__bar > *{
	pointer-events: auto;
}

#djo-root .djo-menu__logo{
	line-height: 0;
}

#djo-root .djo-menu__logo .djo-mark{
	width: auto;
	height: 42px;
}

#djo-root .djo-menu__close{
	position: relative;
	display: grid;
	place-items: center;
	/* A full 44px square: the strokes stay 24px, the target does not. */
	width: 44px;
	height: 44px;
	margin-inline-end: -10px;
	transition: transform 0.4s var(--djo-ease), opacity 0.35s var(--djo-ease);
}

#djo-root .djo-menu__close span{
	position: absolute;
	width: 24px;
	height: 1.5px;
	background: var(--djo-fg);
}

#djo-root .djo-menu__close span:nth-child(1){ transform: rotate(45deg); }
#djo-root .djo-menu__close span:nth-child(2){ transform: rotate(-45deg); }

#djo-root .djo-menu__close:hover{
	transform: rotate(90deg);
}

/* ---- the two columns ---------------------------------------------------- */

/*
 * Portrait, then list. The overlay is LTR — see the note in render.php — so
 * source order IS visual order here: picture left, navigation right.
 */
#djo-root .djo-menu__inner{
	display: grid;
	grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
	align-items: center;
	gap: clamp(24px, 5vw, 72px);
	width: 100%;
	max-width: 1040px;
}

#djo-root .djo-menu__media{
	position: relative;
	display: grid;
	place-items: center;
	/* One number for the portrait's width. The hint below reads it too, so the
	   caption stays welded to the picture's corner at every breakpoint. */
	--djo-menu-frame: 380px;
}

#djo-root .djo-menu__frame{
	position: relative;
	z-index: 1;
	width: min(100%, var(--djo-menu-frame));
	aspect-ratio: 3 / 4;
	overflow: hidden;
}

#djo-root .djo-menu__frame img{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Oversized lettering, same device as the section ghosts — a texture, never a
   second thing to read. */
#djo-root .djo-menu__ghost{
	position: absolute;
	font-family: var(--djo-latin);
	line-height: 0.85;
	white-space: nowrap;
	pointer-events: none;
	user-select: none;
}

/*
 * A band across the top of the overlay, deliberately wider than the viewport
 * so it is cut off at both edges and reads as texture rather than a headline.
 * It hangs off the overlay, not the portrait, so it holds its place while the
 * columns beneath it stack.
 */
#djo-root .djo-menu__ghost--word{
	top: clamp(46px, 8vh, 92px);
	left: 50%;
	z-index: 0;
	font-size: clamp(5rem, 13vw, 12rem);
	letter-spacing: 0.02em;
	color: transparent;
	-webkit-text-stroke: 1px rgba(255, 255, 255, 0.12);
	transform: translateX(-50%);
}

/* Rides the portrait's lower-right corner, half tucked behind it, so it reads
   as part of the picture rather than a stray caption out in the gutter. */
#djo-root .djo-menu__ghost--hint{
	bottom: 15%;
	left: calc(50% + min(50%, var(--djo-menu-frame) / 2) - 2.4em);
	z-index: 2;
	font-family: var(--djo-body);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.28em;
	color: rgba(255, 255, 255, 0.38);
}

#djo-root .djo-menu__nav{
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(18px, 2.4vw, 30px);
}

#djo-root .djo-menu__list{
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(2px, 0.8vw, 10px);
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

#djo-root .djo-menu__list a{
	display: flex;
	align-items: baseline;
	gap: 0.34em;
	padding: 0.06em 0.1em;
	/* The rule under each item IS the design; it is not a hover affordance. */
	border-bottom: 2px solid var(--djo-fg);
	line-height: 1.14;
	transition: opacity 0.35s var(--djo-ease);
}

#djo-root .djo-menu__list a:hover,
#djo-root .djo-menu__list a:focus-visible{
	opacity: 0.55;
}

#djo-root .djo-menu__num{
	font-family: var(--djo-serif);
	font-size: clamp(1.1rem, 1.9vw, 1.7rem);
	font-weight: 500;
	letter-spacing: 0.02em;
}

/* Latin labels, set in the display serif that leads them. */
#djo-root .djo-menu__label{
	font-family: var(--djo-serif);
	font-size: clamp(1.85rem, 4vw, 3.05rem);
	font-weight: 600;
	letter-spacing: 0.005em;
	text-transform: uppercase;
}

#djo-root .djo-menu__social{
	display: flex;
	align-items: center;
	gap: clamp(10px, 1.6vw, 16px);
}

#djo-root .djo-menu__social a{
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	transition: opacity 0.35s var(--djo-ease), transform 0.35s var(--djo-ease);
}

#djo-root .djo-menu__social a:hover{
	opacity: 0.55;
}

#djo-root .djo-menu__social .djo-ico{
	width: 26px;
	height: 26px;
}

#djo-root .djo-menu__rule{
	width: 68px;
	height: 3px;
	background: var(--djo-fg);
}

/* ---- entry motion ------------------------------------------------------- */

/*
 * Each piece travels in from the side it lives on: the list from the right
 * edge, the portrait from the left, the row beneath them upward, the band
 * across the top downward. The delays are additive so the eye is LED through
 * the panel — band, portrait, list, socials, rule — instead of being handed
 * the whole of it in one frame.
 *
 * What follows are the resting (closed) states. .is-open resolves every one of
 * them, which means the same declarations run the exit in reverse for free —
 * with the delays dropped, because leaving should not be staggered.
 */
#djo-root .djo-menu__bar > *,
#djo-root .djo-menu__ghost,
#djo-root .djo-menu__media,
#djo-root .djo-menu__list li,
#djo-root .djo-menu__social a,
#djo-root .djo-menu__rule{
	opacity: 0;
	transition: opacity 0.55s var(--djo-ease-out), transform 0.8s var(--djo-ease-out);
}

#djo-root .djo-menu__logo{ transform: translateX(-24px); }
#djo-root .djo-menu__close{ transform: translateX(24px) rotate(-45deg); }
#djo-root .djo-menu__ghost--word{ transform: translate(-50%, -42px); }
#djo-root .djo-menu__ghost--hint{ transform: translateX(28px); }
#djo-root .djo-menu__media{ transform: translateX(-90px); }
#djo-root .djo-menu__list li{ transform: translateX(90px); }
#djo-root .djo-menu__social a{ transform: translateY(26px); }

#djo-root .djo-menu__rule{
	transform: scaleX(0);
	transform-origin: 50% 50%;
}

/* The picture is pushed the opposite way INSIDE its frame and released with
   it, so the crop slides across the face instead of the whole block arriving
   as one flat card. */
#djo-root .djo-menu__frame img{
	transform: scale(1.18) translateX(6%);
	transition: transform 1.1s var(--djo-ease-out);
}

#djo-root .djo-menu.is-open .djo-menu__bar > *,
#djo-root .djo-menu.is-open .djo-menu__ghost,
#djo-root .djo-menu.is-open .djo-menu__media,
#djo-root .djo-menu.is-open .djo-menu__list li,
#djo-root .djo-menu.is-open .djo-menu__social a,
#djo-root .djo-menu.is-open .djo-menu__rule{
	opacity: 1;
	transform: none;
}

/* The band keeps its centring transform; only the drop resolves. */
#djo-root .djo-menu.is-open .djo-menu__ghost--word{
	transform: translate(-50%, 0);
}

/* Dimmed at rest: the mark names the place, it is not the thing to click here. */
#djo-root .djo-menu.is-open .djo-menu__logo{ opacity: 0.5; }
#djo-root .djo-menu.is-open .djo-menu__frame img{ transform: none; }

#djo-root .djo-menu.is-open .djo-menu__ghost--word{ transition-delay: 0.04s; }
#djo-root .djo-menu.is-open .djo-menu__media,
#djo-root .djo-menu.is-open .djo-menu__frame img{ transition-delay: 0.1s; }
#djo-root .djo-menu.is-open .djo-menu__list li{ transition-delay: calc(0.18s + var(--i, 0) * 0.065s); }
#djo-root .djo-menu.is-open .djo-menu__social a{ transition-delay: calc(0.52s + var(--i, 0) * 0.05s); }
#djo-root .djo-menu.is-open .djo-menu__rule{ transition-delay: 0.74s; }
#djo-root .djo-menu.is-open .djo-menu__ghost--hint{ transition-delay: 0.82s; }
#djo-root .djo-menu.is-open .djo-menu__logo{ transition-delay: 0.2s; }
#djo-root .djo-menu.is-open .djo-menu__close{ transition-delay: 0.26s; }

/*
 * The page header steps aside: its mark and its burger sit on the two corners
 * this overlay wants for itself.
 *
 * !important, and it has to be. The hero timeline reveals this bar by tweening
 * it, and GSAP tweens by writing inline styles — so once the intro has run the
 * element carries style="opacity: 1", which no stylesheet rule can outrank. See
 * trap 12.
 *
 * No transition on it either, for the same reason: a CSS transition on a
 * property GSAP is writing every frame fights the tween. The header cuts, the
 * overlay fades up over it, and the overlay's own bar is delayed ~0.2s behind
 * that — which reads as a hand-off rather than a blink.
 */
#djo-root.is-menu-open .djo-nav{
	opacity: 0 !important;
	pointer-events: none;
}

/* ========================================================================== */
/* Hero                                                                       */
/* ========================================================================== */

#djo-root .djo-hero{
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: 640px;
	height: 100svh;
	padding: var(--djo-pad);
	overflow: hidden;
	background: #000;
}

#djo-root .djo-hero__grid{
	position: absolute;
	inset: 0;
	z-index: 1;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	grid-template-rows: repeat(3, 1fr);
	gap: var(--djo-gap);
}

#djo-root .djo-cell{
	position: relative;
	overflow: hidden;
	background: #050505;
	/* FINAL state: the tiles have retired and the video owns the hero. */
	opacity: 0;
}

#djo-root .djo-cell--slot{
	background: none;
}

#djo-root .djo-cell img{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Explicit placement leaves slot 5 (the video's starting rect) free. */
#djo-root .djo-cell[data-djo-cell='0']{ grid-area: 1 / 1; }
#djo-root .djo-cell[data-djo-cell='1']{ grid-area: 1 / 2; }
#djo-root .djo-cell[data-djo-cell='2']{ grid-area: 1 / 3; }
#djo-root .djo-cell[data-djo-cell='3']{ grid-area: 2 / 1; }
#djo-root .djo-cell--slot{ grid-area: 2 / 2; }
#djo-root .djo-cell[data-djo-cell='5']{ grid-area: 2 / 3; }
#djo-root .djo-cell[data-djo-cell='6']{ grid-area: 3 / 1; }
#djo-root .djo-cell[data-djo-cell='7']{ grid-area: 3 / 2; }
#djo-root .djo-cell[data-djo-cell='8']{ grid-area: 3 / 3; }

/*
 * The video layer sits above the grid and is revealed by opening a clip-path
 * inset. Clipping rather than resizing keeps the whole expansion off the layout
 * thread — no reflow per frame — and avoids the crop shifting as it grows.
 */
#djo-root .djo-hero__stage{
	position: absolute;
	inset: 0;
	z-index: 2;
	clip-path: inset(
		var(--djo-clip-t, 0%) var(--djo-clip-r, 0%)
		var(--djo-clip-b, 0%) var(--djo-clip-l, 0%)
	);
}

#djo-root .djo-hero__video{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

#djo-root .djo-hero__veil{
	position: absolute;
	inset: 0;
	z-index: 3;
	background:
		linear-gradient(to top, rgba(0, 0, 0, 0.86) 0%, rgba(0, 0, 0, 0.22) 48%, rgba(0, 0, 0, 0.46) 100%);
}

#djo-root .djo-hero__content{
	position: relative;
	z-index: 4;
	max-width: 1100px;
	padding-bottom: clamp(30px, 7vh, 90px);
}

#djo-root .djo-hero__eyebrow{
	font-family: var(--djo-body);
	font-size: 0.76rem;
	font-weight: 600;
	letter-spacing: 0.34em;
	color: var(--djo-dim);
	text-align: right;
}

#djo-root .djo-hero__title{
	font-family: var(--djo-hebrew);
	font-weight: 900;
	margin-top: 0.28em;
	font-size: var(--djo-h1);
	line-height: 0.86;
	letter-spacing: -0.035em;
}

#djo-root .djo-hero__sub{
	max-width: 42ch;
	margin-top: 1.2em;
	font-size: clamp(1rem, 1.7vw, 1.32rem);
	font-weight: 300;
	color: rgba(255, 255, 255, 0.78);
}

#djo-root .djo-hero__actions{
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	/*
	 * The offset sits on the row, not on each button. While both fit on one
	 * line the result is identical; once they wrap, a per-button margin was
	 * being added on top of the gap and pushed them 42px apart.
	 */
	margin-top: 2.2em;
}

#djo-root .djo-hero__actions .djo-btn{
	margin-top: 0;
}

#djo-root .djo-scroll{
	position: absolute;
	z-index: 4;
	bottom: 14px;
	inset-inline-start: calc(var(--djo-pad) - 10px);
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 10px;
	font-size: 0.75rem;
	letter-spacing: 0.22em;
	color: rgba(255, 255, 255, 0.72);
}

#djo-root .djo-scroll .djo-ico{
	width: 16px;
	height: 16px;
	animation: djo-bob 2.4s var(--djo-ease) infinite;
}

@keyframes djo-bob {
	0%, 100% { transform: translateY(0); }
	50%      { transform: translateY(5px); }
}

/* ========================================================================== */
/* Monogram                                                                   */
/* ========================================================================== */

/*
 * The mark is wider than it is tall — the supplied artwork is 688x454 (~1.52),
 * the fallback drawing 296x200 (1.48). Every slot therefore sets HEIGHT only
 * and leaves width auto; pinning both squashes the gem, and it also lets the
 * artwork and the fallback swap in without relaying anything out.
 */
#djo-root .djo-mark{
	display: block;
	width: auto;
	color: currentColor;
}

/* The uploaded original drops into the same slots as the drawing. */
#djo-root .djo-mark--img{
	object-fit: contain;
}

#djo-root .djo-mark__txt{
	font-family: var(--djo-serif);
	font-size: 88px;
	font-weight: 500;
}

/* ========================================================================== */
/* Marquee + ghost type                                                       */
/* ========================================================================== */

#djo-root .djo-marquee{
	/*
	 * The rail must be LTR at the CONTAINER, not just on the track.
	 *
	 * The track is width:max-content. Inside an RTL container that anchors it
	 * to the RIGHT edge, extending leftwards off-screen — so animating x
	 * negative walked it straight out of view and left dead space behind it.
	 * Anchoring the container LTR puts the track's left edge at 0, which is
	 * what the coverage maths assumes.
	 */
	direction: ltr;
	position: relative;
	padding: clamp(16px, 2.6vw, 30px) 0;
	border-block: 1px solid var(--djo-hair);
	overflow: hidden;
}

#djo-root .djo-marquee__track{
	display: flex;
	align-items: center;
	gap: clamp(20px, 3.4vw, 54px);
	width: max-content;
	will-change: transform;
}

#djo-root .djo-marquee__item{
	font-family: var(--djo-latin);
	font-size: clamp(2rem, 6.6vw, 5.4rem);
	line-height: 1;
	letter-spacing: 0.01em;
	/* outlined "ghost" lettering, the Garrix ticker device. */
	color: transparent;
	-webkit-text-stroke: 1px rgba(255, 255, 255, 0.42);
}

#djo-root .djo-marquee__item:nth-child(4n + 1){
	color: var(--djo-fg);
	-webkit-text-stroke: 0;
}

#djo-root .djo-marquee__dot .djo-mark{
	height: clamp(22px, 3vw, 40px);
	color: rgba(255, 255, 255, 0.5);
}

#djo-root .djo-ghost{
	position: absolute;
	top: clamp(10px, 3vw, 40px);
	inset-inline-start: 50%;
	transform: translateX(-50%);
	z-index: 0;
	font-family: var(--djo-latin);
	font-size: clamp(3.6rem, 17vw, 16rem);
	line-height: 0.8;
	color: transparent;
	/* Sits behind right-aligned Hebrew headings, so it has to stay a texture
	   rather than a second thing to read. */
	-webkit-text-stroke: 1px rgba(255, 255, 255, 0.055);
	pointer-events: none;
	user-select: none;
	white-space: nowrap;
}

#djo-root .djo-ghost--contact{
	top: auto;
	bottom: -0.12em;
	font-size: clamp(9rem, 40vw, 34rem);
}

/* ========================================================================== */
/* Sections                                                                   */
/* ========================================================================== */

#djo-root .djo-sec{
	position: relative;
	padding: var(--djo-sec-y) var(--djo-pad);
}

/* The header is fixed, so anchor jumps must leave room for it or every nav
   link parks the section heading behind the bar. */
#djo-root [id]{
	scroll-margin-top: 112px;
}

#djo-root .djo-sec__head{
	position: relative;
	z-index: 1;
	max-width: 900px;
}

#djo-root .djo-sec__head--center{
	margin-inline: auto;
	text-align: center;
}

#djo-root .djo-sec__head--center .djo-lede{
	margin-inline: auto;
}

/* ---- mosaics ------------------------------------------------------------ */

#djo-root .djo-mosaic{
	display: grid;
	gap: clamp(8px, 1.4vw, 18px);
	margin-top: var(--djo-head-gap);
}

#djo-root .djo-mosaic--parties{
	grid-template-columns: repeat(6, 1fr);
	grid-auto-rows: clamp(120px, 15vw, 230px);
}

/* One tall tile beside two stacked — an asymmetric trio rather than a wall. */
#djo-root .djo-mosaic--parties .djo-mosaic__cell:nth-child(1){ grid-column: span 3; grid-row: span 2; }
#djo-root .djo-mosaic--parties .djo-mosaic__cell:nth-child(2){ grid-column: span 3; grid-row: span 1; }
#djo-root .djo-mosaic--parties .djo-mosaic__cell:nth-child(3){ grid-column: span 3; grid-row: span 1; }

#djo-root .djo-mosaic--weddings{
	grid-template-columns: repeat(4, 1fr);
	grid-auto-rows: clamp(150px, 20vw, 320px);
}

#djo-root .djo-mosaic__cell{
	position: relative;
	margin: 0;
	overflow: hidden;
	background: var(--djo-panel);
}

#djo-root .djo-mosaic__cell img{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ---- weddings clip strip ------------------------------------------------ */

#djo-root .djo-clips{
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(8px, 1.4vw, 18px);
	margin-top: clamp(38px, 6vw, 78px);
	/* Without a cap, a 9:16 tile is ~750px tall at 1440px wide. */
	max-width: 940px;
	margin-inline: auto;
}

/* ---- the wide cinematic band ------------------------------------------- */

#djo-root .djo-band{
	position: relative;
	margin-top: var(--djo-head-gap);
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--djo-panel);
}

/* On anything wide, letterbox it: 16:9 across a 1440px page is 715px of
   vertical, which swamps the section. 21:9 reads as a film strip instead. */
@media (min-width: 861px){
	#djo-root .djo-band{
		aspect-ratio: 21 / 9;
	}
}

#djo-root .djo-band video{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* A hairline vignette keeps the band from floating as a bright rectangle
   against true black at the top and bottom edges. */
#djo-root .djo-band::after{
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(to bottom, rgba(0,0,0,0.5), transparent 22%, transparent 78%, rgba(0,0,0,0.5));
}

/* The parties strip runs 4:5 to match the source clips natively. */
#djo-root .djo-clips--parties{
	grid-template-columns: repeat(3, 1fr);
	margin-top: clamp(8px, 1.4vw, 18px);
	margin-bottom: clamp(8px, 1.4vw, 18px);
	max-width: 1080px;
}

#djo-root .djo-clips__item{
	position: relative;
	aspect-ratio: 9 / 16;
	overflow: hidden;
	background: var(--djo-panel);
}

/* Must follow the base rule: same specificity, so source order decides which
   aspect-ratio wins. The party sources are natively 4:5. */
#djo-root .djo-clips__item--45{
	aspect-ratio: 4 / 5;
}

#djo-root .djo-clips__item video{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ========================================================================== */
/* About                                                                      */
/* ========================================================================== */

#djo-root .djo-about{
	display: grid;
	grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
	gap: clamp(28px, 5vw, 80px);
	align-items: center;
}

#djo-root .djo-about__media{
	position: relative;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	background: var(--djo-panel);
}

#djo-root .djo-about__media img{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

#djo-root .djo-prose{
	margin-top: 1.6em;
	max-width: 62ch;
}

#djo-root .djo-prose p{
	margin-bottom: 1.15em;
	font-weight: 300;
	color: rgba(255, 255, 255, 0.72);
}

#djo-root .djo-prose p:first-child{
	font-size: 1.1em;
	color: rgba(255, 255, 255, 0.9);
}

#djo-root .djo-prose p:last-child{
	margin-bottom: 0;
}

/* ---- club ticker -------------------------------------------------------- */

#djo-root .djo-ticker{
	/* Same as the marquee: the max-content track must anchor left, not right. */
	direction: ltr;
	margin-top: clamp(48px, 7vw, 96px);
	padding-block: clamp(12px, 1.8vw, 22px);
	border-block: 1px solid var(--djo-hair);
	overflow: hidden;
}

#djo-root .djo-ticker__track{
	display: flex;
	align-items: center;
	gap: 26px;
	width: max-content;
	font-family: var(--djo-latin);
	font-size: clamp(0.95rem, 1.7vw, 1.5rem);
	letter-spacing: 0.14em;
	color: rgba(255, 255, 255, 0.6);
	white-space: nowrap;
	will-change: transform;
}

#djo-root .djo-ticker__sep{
	color: var(--djo-fg);
}

/* ========================================================================== */
/* Packages                                                                   */
/* ========================================================================== */

#djo-root .djo-cards{
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: clamp(10px, 1.4vw, 18px);
	margin-top: var(--djo-head-gap);
}

#djo-root .djo-card{
	display: flex;
	flex-direction: column;
	border: 1px solid var(--djo-hair);
	background: var(--djo-panel);
	transition: border-color 0.45s var(--djo-ease), transform 0.55s var(--djo-ease);
}

#djo-root .djo-card:hover{
	border-color: rgba(255, 255, 255, 0.42);
	transform: translateY(-5px);
}

/*
 * Portrait, not the old 4:3. Every frame in the shoot is either a 2:3 worn shot
 * or a 1:1 flat lay; a landscape crop took the top off both.
 */
#djo-root .djo-card__media{
	position: relative;
	aspect-ratio: 3 / 4;
	overflow: hidden;
}

#djo-root .djo-card__media img,
#djo-root .djo-card__media video{
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.9s var(--djo-ease);
}

#djo-root .djo-card:hover .djo-card__media img,
#djo-root .djo-card:hover .djo-card__media video{
	transform: scale(1.05);
}

/*
 * The hover reveal: a second still stacked over the resting media. It carries
 * information the first frame cannot — the flat lays are the only shots where
 * the logo and wordmark are legible, and on the flag it shows the second
 * colourway. Pointer-only by nature; on touch the card simply stays at rest.
 */
#djo-root .djo-card__alt{
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 0.5s var(--djo-ease);
}

#djo-root .djo-card:hover .djo-card__alt,
#djo-root .djo-card:focus-within .djo-card__alt{
	opacity: 1;
}

#djo-root .djo-card__body{
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: clamp(18px, 2vw, 26px);
}

#djo-root .djo-card__title{
	font-size: clamp(1.25rem, 2vw, 1.6rem);
	line-height: 1.1;
}

#djo-root .djo-card__desc{
	margin-top: 0.7em;
	font-size: 0.94rem;
	font-weight: 300;
	color: var(--djo-dim);
}

#djo-root .djo-card__cta{
	display: inline-flex;
	align-items: center;
	gap: 9px;
	margin-top: auto;
	padding-top: 1.5em;
	font-size: 0.82rem;
	font-weight: 600;
}

#djo-root .djo-card__cta span{
	border-bottom: 1px solid var(--djo-faint);
	padding-bottom: 2px;
	transition: border-color 0.35s var(--djo-ease);
}

#djo-root .djo-card__cta:hover span{
	border-bottom-color: var(--djo-fg);
}

/* ========================================================================== */
/* Reviews                                                                    */
/* ========================================================================== */

#djo-root .djo-revs{
	max-width: 940px;
	margin: var(--djo-head-gap) auto 0;
	text-align: center;
}

#djo-root .djo-revs__stage{
	position: relative;
	display: grid;
}

/* All slides stack in one grid cell so the section height never jumps
   between reviews of different lengths. */
#djo-root .djo-rev{
	grid-area: 1 / 1;
	align-self: center;
	margin: 0;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.6s var(--djo-ease);
}

#djo-root .djo-rev.is-active{
	opacity: 1;
	visibility: visible;
}

/*
 * The reviewer's own mit4mit picture, untouched. The circle is a mask, not a
 * re-crop: object-fit centres whatever aspect the source file happens to have,
 * so nothing had to be re-cut to fit and the original file stays authoritative.
 */
#djo-root .djo-rev__avatar{
	width: clamp(58px, 7vw, 76px);
	aspect-ratio: 1;
	margin: 0 auto 1.15em;
	overflow: hidden;
	border-radius: 50%;
	border: 1px solid var(--djo-hair);
}

#djo-root .djo-rev__pic{
	width: 100%;
	height: 100%;
	object-fit: cover;
}

#djo-root .djo-rev__stars{
	font-size: 1.05rem;
	letter-spacing: 0.34em;
	direction: ltr;
}

#djo-root .djo-rev__text{
	margin: 0.9em 0 0;
	font-family: var(--djo-hebrew);
	font-size: clamp(1.15rem, 2.7vw, 2.05rem);
	font-weight: 400;
	line-height: 1.42;
	letter-spacing: -0.01em;
}

#djo-root .djo-rev__by{
	margin-top: 1.5em;
	font-size: 0.8rem;
	letter-spacing: 0.16em;
	color: var(--djo-dim);
}

#djo-root .djo-rev__name{
	font-weight: 600;
	color: var(--djo-fg);
}

#djo-root .djo-rev__ev::before{
	content: '·';
	margin-inline: 8px;
}

#djo-root .djo-revs__ctrl{
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 20px;
	margin-top: clamp(28px, 4vw, 48px);
}

#djo-root .djo-revs__btn{
	width: 46px;
	height: 46px;
	font-size: 1.5rem;
	line-height: 1;
	border: 1px solid var(--djo-hair);
	transition: border-color 0.35s var(--djo-ease), background-color 0.35s var(--djo-ease);
}

#djo-root .djo-revs__btn:hover{
	border-color: var(--djo-fg);
	background: rgba(255, 255, 255, 0.07);
}

#djo-root .djo-revs__dots{
	display: flex;
	gap: 9px;
}

#djo-root .djo-revs__dot{
	position: relative;
	width: 8px;
	height: 8px;
	padding: 0;
	background: var(--djo-faint);
	transition: background-color 0.35s var(--djo-ease), transform 0.35s var(--djo-ease);
}

/* The dot stays 8px; the thing you can actually hit is 40px. */
#djo-root .djo-revs__dot::after{
	content: '';
	position: absolute;
	inset: -16px;
}

#djo-root .djo-revs__dot.is-active{
	background: var(--djo-fg);
	transform: scale(1.45);
}

/* ---- mit4mit source link ------------------------------------------------ */

/*
 * A hairline pill, not a badge: it has to read as an attribution the visitor
 * can follow, not as a third call to action competing with the WhatsApp
 * buttons. Hence no fill, no colour, and a border that only firms up on hover.
 */
#djo-root .djo-revs__source{
	display: inline-flex;
	align-items: center;
	gap: clamp(12px, 2vw, 20px);
	margin-top: clamp(30px, 4vw, 48px);
	padding: 12px clamp(16px, 2.4vw, 24px);
	border: 1px solid var(--djo-hair);
	transition: border-color 0.35s var(--djo-ease), background-color 0.35s var(--djo-ease);
}

#djo-root .djo-revs__source:hover{
	border-color: var(--djo-fg);
	background: rgba(255, 255, 255, 0.05);
}

#djo-root .djo-revs__m4m{
	width: auto;
	height: clamp(26px, 3vw, 34px);
	opacity: 0.86;
}

#djo-root .djo-revs__meta{
	display: flex;
	align-items: center;
	gap: 10px;
	text-align: start;
}

#djo-root .djo-revs__score{
	font-family: var(--djo-hebrew);
	font-size: 1.32rem;
	font-weight: 900;
	line-height: 1;
}

#djo-root .djo-revs__score small{
	font-size: 0.62em;
	font-weight: 400;
	color: var(--djo-dim);
}

#djo-root .djo-revs__cta{
	font-size: 0.78rem;
	line-height: 1.3;
	color: var(--djo-dim);
	border-inline-start: 1px solid var(--djo-hair);
	padding-inline-start: 10px;
}

/* ========================================================================== */
/* Contact                                                                    */
/* ========================================================================== */

#djo-root .djo-sec--contact{
	overflow: hidden;
}

/*
 * Five tiles into a grid leaves an orphan row hanging at one edge. Flex-wrap
 * centres whatever ends up on the last row, so 5, 4 or 3 links all balance.
 */
#djo-root .djo-links{
	position: relative;
	z-index: 1;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: clamp(10px, 1.2vw, 16px);
	margin-top: var(--djo-head-gap);
}

#djo-root .djo-link{
	flex: 1 1 180px;
	max-width: 280px;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: clamp(20px, 2.6vw, 34px) 12px;
	border: 1px solid var(--djo-hair);
	transition: background-color 0.4s var(--djo-ease), border-color 0.4s var(--djo-ease);
}

#djo-root .djo-link:hover{
	border-color: var(--djo-fg);
	background: rgba(255, 255, 255, 0.05);
}

#djo-root .djo-link__label{
	font-family: var(--djo-latin);
	font-size: 0.98rem;
	letter-spacing: 0.16em;
}

/* ========================================================================== */
/* Footer                                                                     */
/* ========================================================================== */

#djo-root .djo-foot{
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 14px;
	padding: clamp(50px, 7vw, 96px) var(--djo-pad) clamp(34px, 4vw, 56px);
	border-top: 1px solid var(--djo-hair);
	text-align: center;
}

#djo-root .djo-foot__lockup{
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
}

#djo-root .djo-foot__mark{
	height: clamp(58px, 7vw, 84px);
}

#djo-root .djo-foot__word{
	font-family: var(--djo-latin);
	font-size: clamp(0.82rem, 1.5vw, 1.05rem);
	letter-spacing: 0.14em;
	line-height: 1;
}

#djo-root .djo-foot__note{
	font-size: 0.88rem;
	color: var(--djo-dim);
}

#djo-root .djo-foot__copy{
	font-size: 0.76rem;
	letter-spacing: 0.2em;
	color: rgba(255, 255, 255, 0.32);
}

/*
 * Build credit. One notch quieter than the copyright above it and separated by
 * a hairline rather than a gap, so it reads as a signature on the page instead
 * of a fourth line of footer copy.
 */
#djo-root .djo-foot__credit{
	margin-top: 6px;
	padding-top: 8px;
	border-top: 1px solid rgba(255, 255, 255, 0.08);
	/* 12px is the floor; 0.72rem resolved to 11.5px and the audit was right. */
	font-size: 0.75rem;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.26);
}

/* inline-block + padding: the line stays 16px tall, the target is 34px. */
#djo-root .djo-foot__credit a{
	display: inline-block;
	padding-block: 9px;
	padding-inline: 2px;
	color: inherit;
	transition: color 0.35s var(--djo-ease);
}

#djo-root .djo-foot__credit a:hover,
#djo-root .djo-foot__credit a:focus-visible{
	color: var(--djo-fg);
}

/* ========================================================================== */
/* Animation "before" states — only ever applied once GSAP is confirmed.      */
/* ========================================================================== */

#djo-root .djo-js .djo-cell{
	opacity: 1;
}

#djo-root .djo-js .djo-cell--slot{
	opacity: 0;
}

#djo-root .djo-js [data-djo-in],
#djo-root .djo-js [data-djo-hero-in]{
	opacity: 0;
}

#djo-root .djo-js .djo-nav,
#djo-root .djo-js .djo-scroll{
	opacity: 0;
}

/* ========================================================================== */
/* Responsive                                                                 */
/* ========================================================================== */

@media (max-width: 1024px){
	#djo-root .djo-about{
		grid-template-columns: 1fr;
	}

	#djo-root .djo-about__media{
		max-width: 560px;
		aspect-ratio: 3 / 4;
	}
}

/*
 * The menu's two columns only work while the portrait has real width to sit
 * in. Below this it stacks, and the order inverts: list first, portrait under
 * it. The picture is kept — shrunk, not dropped — because a bare column of
 * links is not the design.
 */
@media (max-width: 900px){
	#djo-root .djo-menu{
		place-items: start center;
		padding-top: clamp(76px, 11vh, 104px);
	}

	#djo-root .djo-menu__inner{
		grid-template-columns: 1fr;
		gap: clamp(20px, 6vw, 48px);
	}

	#djo-root .djo-menu__nav{ order: 1; }
	#djo-root .djo-menu__media{ order: 2; }

	#djo-root .djo-menu__media{
		--djo-menu-frame: min(52vw, 230px);
	}

	/* Both ghosts go. The band would run straight through the list at this
	   width, and the hint has no gutter left to hang in — the section showing
	   through the glass is texture enough on a phone. */
	#djo-root .djo-menu__ghost--word,
#djo-root .djo-menu__ghost--hint{
		display: none;
	}

	/* Stacked, the portrait has no side to arrive from — it rises instead. */
	#djo-root .djo-menu__media{
		transform: translateY(64px);
	}

	#djo-root .djo-menu.is-open .djo-menu__media{
		transform: none;
	}
}

@media (max-width: 860px) {
	#djo-root .djo-nav__cta span{
		display: none;
	}

	#djo-root .djo-nav__cta{
		padding: 0.7em;
	}

	#djo-root .djo-mosaic--parties{
		grid-template-columns: repeat(2, 1fr);
		grid-auto-rows: clamp(130px, 30vw, 210px);
	}

	#djo-root .djo-mosaic--parties .djo-mosaic__cell:nth-child(1){ grid-column: span 2; grid-row: span 1; }
	#djo-root .djo-mosaic--parties .djo-mosaic__cell:nth-child(2),
#djo-root .djo-mosaic--parties .djo-mosaic__cell:nth-child(3){ grid-column: span 1; grid-row: span 1; }

	#djo-root .djo-mosaic--weddings{
		grid-template-columns: repeat(2, 1fr);
	}
}

/*
 * Below 640px the 3x3 grid becomes 2x3: nine tiles on a 390px screen is ~120px
 * each, which reads as visual noise rather than a grid. This is a re-layout,
 * not a shrink — three tiles are dropped and the video's starting slot moves to
 * the middle band, spanning the full width.
 */
@media (max-width: 640px){
	#djo-root .djo-hero__grid{
		grid-template-columns: repeat(2, 1fr);
		grid-template-rows: repeat(3, 1fr);
	}

	#djo-root .djo-cell[data-djo-cell='0']{ grid-area: 1 / 1; }
	#djo-root .djo-cell[data-djo-cell='1']{ grid-area: 1 / 2; }
	#djo-root .djo-cell--slot{ grid-area: 2 / 1 / 3 / 3; }
	#djo-root .djo-cell[data-djo-cell='2']{ grid-area: 3 / 1; }
	#djo-root .djo-cell[data-djo-cell='3']{ grid-area: 3 / 2; }

	#djo-root .djo-cell[data-djo-cell='5'],
#djo-root .djo-cell[data-djo-cell='6'],
#djo-root .djo-cell[data-djo-cell='7'],
#djo-root .djo-cell[data-djo-cell='8']{
		display: none;
	}

	/*
	 * Clip strips become an edge-to-edge swipe rail.
	 *
	 * Stacked, each 9:16 clip was ~675px tall on a 390px screen — three of them
	 * pushed the weddings section past 2,600px on its own. A snap rail keeps the
	 * whole strip to one tile's height and reads as native on touch.
	 */
	#djo-root .djo-clips{
		display: flex;
		grid-template-columns: none;
		gap: 10px;
		max-width: none;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		margin-inline: calc(var(--djo-pad) * -1);
		padding-inline: var(--djo-pad);
	}

	#djo-root .djo-clips::-webkit-scrollbar{
		display: none;
	}

	#djo-root .djo-clips__item{
		flex: 0 0 66vw;
		scroll-snap-align: center;
	}

	#djo-root .djo-clips__item--45{
		flex-basis: 58vw;
	}

	/* Merch reads as compact rows rather than three tall stacked cards. */
	#djo-root .djo-cards{
		grid-template-columns: 1fr;
	}

	#djo-root .djo-card{
		flex-direction: row;
		align-items: stretch;
	}

	#djo-root .djo-card__media{
		flex: 0 0 40%;
		aspect-ratio: auto;
	}

	#djo-root .djo-card__body{
		padding: 16px 18px;
	}

	#djo-root .djo-card__cta{
		padding-top: 1.1em;
	}

	/*
	 * Side by side rather than two full-width slabs. The longer label measures
	 * ~109px at this size, so a half-width button clears it comfortably; the
	 * tighter padding brings the height from 53px back to ~45px, still above
	 * the 44px touch target.
	 */
	#djo-root .djo-hero__actions .djo-btn{
		flex: 1 1 0;
		padding: 0.78em 1.2em;
		text-align: center;
	}

	#djo-root .djo-rev__text{
		font-size: 1.15rem;
	}

	/* The pill wraps to two rows rather than shrinking the mit4mit logo to
	   the point where its wordmark stops being readable. */
	#djo-root .djo-revs__source{
		flex-direction: column;
		gap: 12px;
		width: 100%;
	}

	#djo-root .djo-revs__cta{
		border-inline-start: 0;
		padding-inline-start: 0;
	}
}

/* ========================================================================== */
/* Reduced motion                                                             */
/* ========================================================================== */

@media (prefers-reduced-motion: reduce){
	#djo-root *,
#djo-root *::before,
#djo-root *::after{
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		transition-delay: 0s !important;
		scroll-behavior: auto !important;
	}

	/* Force the resolved end-state regardless of what the JS was mid-way through. */
	#djo-root .djo-js .djo-cell,
#djo-root .djo-js [data-djo-in],
#djo-root .djo-js [data-djo-hero-in],
#djo-root .djo-js .djo-nav,
#djo-root .djo-js .djo-scroll{
		opacity: 1;
	}

	#djo-root .djo-js .djo-cell{
		opacity: 0;
	}

	#djo-root .djo-hero__stage{
		clip-path: none;
	}

	#djo-root .djo-scroll .djo-ico{
		animation: none;
	}

	/*
	 * The blanket rule above freezes the breathe mid-cycle, which can leave an
	 * aura stuck at its dimmest. Settle them at a fixed value instead — the
	 * depth layers still read, they just stop moving.
	 */
	#djo-root .djo-aura{
		opacity: 0.85;
	}
}
