/* =============================================================================
   PROJECT SHEMA — the visual system
   =============================================================================

   Loads after tour.css and extends it. tour.css owns the page: bands, type,
   buttons, the booking card. This file owns the *world* the page sits in —
   the surfaces, the depth, the map, the objects that drift behind the
   photographs.

   THE RULES
   ---------
   1. Photography leads. Every drawn element here is support: it frames a
      photograph, explains a route, or carries a label. Nothing competes.
   2. One light. The icon set is lit from the upper left; so are the plinths
      they sit on, and so are the floating objects. Shadows fall the same way
      on every surface.
   3. Texture is felt, not seen. Paper grain runs at 4% opacity, zellige at 5%.
      If you can name the pattern at a glance it is too strong.
   4. Motion is slow. Nothing here is faster than 400ms except a hover, and the
      ambient layer runs in tens of seconds. Speed reads as cheap.
   5. Everything degrades. Reduced motion stops the drift. No JavaScript still
      leaves a readable page with a legible map.

   Brand colours are inherited from style.css and never redefined here.
   ========================================================================== */

.tour,
.shema {
	/* ---- Heritage neutrals — the archive register -------------------- */
	--s-paper:      #FAF5EC;   /* archive paper, the warm ground        */
	--s-paper-deep: #F0E6D4;   /* the same paper in shadow              */
	--s-ink:        #12212F;   /* manuscript ink, deeper than body text */
	--s-brass:      #C9971E;   /* the darker half of the gold gradient  */

	/* ---- Depth ------------------------------------------------------- */
	--s-lift-1: 0 1px 2px rgba(18, 33, 47, .04), 0 4px 14px rgba(3, 95, 165, .06);
	--s-lift-2: 0 2px 6px rgba(18, 33, 47, .05), 0 16px 38px rgba(3, 95, 165, .10);
	--s-lift-3: 0 6px 16px rgba(18, 33, 47, .07), 0 34px 70px rgba(3, 95, 165, .16);

	/* ---- Motion ------------------------------------------------------ */
	--s-ease:  cubic-bezier(.2, .8, .2, 1);
	--s-ease-o: cubic-bezier(.16, 1, .3, 1);
}

/* The shared gradient sheet is markup, not a graphic. */
.sh-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* =============================================================================
   1. SURFACES — the textures the whole site is built on
   ========================================================================== */

/* Archive paper. Fractal noise at 4%: you read it as tooth on the page rather
   than as a pattern. */
.sx-paper { position: relative; background-color: var(--s-paper); }
.sx-paper::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23p)' opacity='.5'/%3E%3C/svg%3E");
	opacity: .05;
	mix-blend-mode: multiply;
}

/* Zellige watermark — the same computed khatim-and-saft geometry as the dado
   in inc/zellige.php, reduced to a stroke.
   Tuned down twice: at 5.5% it read as a grid of stars across the whole band,
   nameable at a glance, which by rule 3 above means too strong. A 176px repeat
   at 2.6%, faded through the middle of the section where the cards sit, reads
   as tooth on a surface rather than as wallpaper. */
.sx-zellige { position: relative; }
.sx-zellige::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='176' height='176' viewBox='0 0 176 176'%3E%3Cg fill='none' stroke='%23035FA5' stroke-width='1.6'%3E%3Cpath d='M44 0L31.1 12.9L31.1 31.1L12.9 31.1L0 44L-12.9 31.1L-31.1 31.1L-31.1 12.9L-44 0L-31.1 -12.9L-31.1 -31.1L-12.9 -31.1L0 -44L12.9 -31.1L31.1 -31.1L31.1 -12.9Z'/%3E%3Cpath d='M44 88L31.1 100.9L31.1 119.1L12.9 119.1L0 132L-12.9 119.1L-31.1 119.1L-31.1 100.9L-44 88L-31.1 75.1L-31.1 56.9L-12.9 56.9L0 44L12.9 56.9L31.1 56.9L31.1 75.1Z'/%3E%3Cpath d='M44 176L31.1 188.9L31.1 207.1L12.9 207.1L0 220L-12.9 207.1L-31.1 207.1L-31.1 188.9L-44 176L-31.1 163.1L-31.1 144.9L-12.9 144.9L0 132L12.9 144.9L31.1 144.9L31.1 163.1Z'/%3E%3Cpath d='M132 0L119.1 12.9L119.1 31.1L100.9 31.1L88 44L75.1 31.1L56.9 31.1L56.9 12.9L44 0L56.9 -12.9L56.9 -31.1L75.1 -31.1L88 -44L100.9 -31.1L119.1 -31.1L119.1 -12.9Z'/%3E%3Cpath d='M132 88L119.1 100.9L119.1 119.1L100.9 119.1L88 132L75.1 119.1L56.9 119.1L56.9 100.9L44 88L56.9 75.1L56.9 56.9L75.1 56.9L88 44L100.9 56.9L119.1 56.9L119.1 75.1Z'/%3E%3Cpath d='M132 176L119.1 188.9L119.1 207.1L100.9 207.1L88 220L75.1 207.1L56.9 207.1L56.9 188.9L44 176L56.9 163.1L56.9 144.9L75.1 144.9L88 132L100.9 144.9L119.1 144.9L119.1 163.1Z'/%3E%3Cpath d='M220 0L207.1 12.9L207.1 31.1L188.9 31.1L176 44L163.1 31.1L144.9 31.1L144.9 12.9L132 0L144.9 -12.9L144.9 -31.1L163.1 -31.1L176 -44L188.9 -31.1L207.1 -31.1L207.1 -12.9Z'/%3E%3Cpath d='M220 88L207.1 100.9L207.1 119.1L188.9 119.1L176 132L163.1 119.1L144.9 119.1L144.9 100.9L132 88L144.9 75.1L144.9 56.9L163.1 56.9L176 44L188.9 56.9L207.1 56.9L207.1 75.1Z'/%3E%3Cpath d='M220 176L207.1 188.9L207.1 207.1L188.9 207.1L176 220L163.1 207.1L144.9 207.1L144.9 188.9L132 176L144.9 163.1L144.9 144.9L163.1 144.9L176 132L188.9 144.9L207.1 144.9L207.1 163.1Z'/%3E%3Cpath d='M44 0L31.1 12.9L31.1 31.1L12.9 31.1L0 44L12.9 56.9L31.1 56.9L31.1 75.1L44 88L56.9 75.1L56.9 56.9L75.1 56.9L88 44L75.1 31.1L56.9 31.1L56.9 12.9Z'/%3E%3Cpath d='M57.6 44L53.6 48L53.6 53.6L48 53.6L44 57.6L40 53.6L34.4 53.6L34.4 48L30.4 44L34.4 40L34.4 34.4L40 34.4L44 30.4L48 34.4L53.6 34.4L53.6 40Z'/%3E%3Cpath d='M44 88L31.1 100.9L31.1 119.1L12.9 119.1L0 132L12.9 144.9L31.1 144.9L31.1 163.1L44 176L56.9 163.1L56.9 144.9L75.1 144.9L88 132L75.1 119.1L56.9 119.1L56.9 100.9Z'/%3E%3Cpath d='M57.6 132L53.6 136L53.6 141.6L48 141.6L44 145.6L40 141.6L34.4 141.6L34.4 136L30.4 132L34.4 128L34.4 122.4L40 122.4L44 118.4L48 122.4L53.6 122.4L53.6 128Z'/%3E%3Cpath d='M132 0L119.1 12.9L119.1 31.1L100.9 31.1L88 44L100.9 56.9L119.1 56.9L119.1 75.1L132 88L144.9 75.1L144.9 56.9L163.1 56.9L176 44L163.1 31.1L144.9 31.1L144.9 12.9Z'/%3E%3Cpath d='M145.6 44L141.6 48L141.6 53.6L136 53.6L132 57.6L128 53.6L122.4 53.6L122.4 48L118.4 44L122.4 40L122.4 34.4L128 34.4L132 30.4L136 34.4L141.6 34.4L141.6 40Z'/%3E%3Cpath d='M132 88L119.1 100.9L119.1 119.1L100.9 119.1L88 132L100.9 144.9L119.1 144.9L119.1 163.1L132 176L144.9 163.1L144.9 144.9L163.1 144.9L176 132L163.1 119.1L144.9 119.1L144.9 100.9Z'/%3E%3Cpath d='M145.6 132L141.6 136L141.6 141.6L136 141.6L132 145.6L128 141.6L122.4 141.6L122.4 136L118.4 132L122.4 128L122.4 122.4L128 122.4L132 118.4L136 122.4L141.6 122.4L141.6 128Z'/%3E%3C/g%3E%3C/svg%3E");
	opacity: .026;
	-webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 46%, transparent 62%, #000 100%);
	        mask-image: linear-gradient(180deg, #000 0%, transparent 46%, transparent 62%, #000 100%);
}

/* The graticule — the fine latitude/longitude rule of a printed chart. */
.sx-graticule { position: relative; }
.sx-graticule::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		repeating-linear-gradient(0deg,  rgba(3, 95, 165, .07) 0 1px, transparent 1px 72px),
		repeating-linear-gradient(90deg, rgba(3, 95, 165, .07) 0 1px, transparent 1px 72px);
	-webkit-mask-image: radial-gradient(ellipse at 50% 40%, #000 20%, transparent 78%);
	        mask-image: radial-gradient(ellipse at 50% 40%, #000 20%, transparent 78%);
}

/* Contour lines, for bands that sit over terrain. */
.sx-contour { position: relative; }
.sx-contour::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='200' viewBox='0 0 320 200'%3E%3Cg fill='none' stroke='%23024A82' stroke-width='1.2'%3E%3Cpath d='M-10 40Q80 6 160 40T330 40'/%3E%3Cpath d='M-10 68Q80 34 160 68T330 68'/%3E%3Cpath d='M-10 96Q80 62 160 96T330 96'/%3E%3Cpath d='M-10 124Q80 90 160 124T330 124'/%3E%3Cpath d='M-10 152Q80 118 160 152T330 152'/%3E%3Cpath d='M-10 180Q80 146 160 180T330 180'/%3E%3C/g%3E%3C/svg%3E");
	opacity: .07;
}

/* Cinematic grain, laid over photography only. */
.sx-grain::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 3;
	pointer-events: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
	opacity: .09;
	mix-blend-mode: overlay;
}

/* Glass. Used for anything that floats over a photograph. */
.sx-glass {
	background: rgba(255, 255, 255, .12);
	backdrop-filter: blur(16px) saturate(160%);
	-webkit-backdrop-filter: blur(16px) saturate(160%);
	border: 1px solid rgba(255, 255, 255, .28);
}

/* =============================================================================
   1b. THE ZELLIGE DADO
   Real tilework, laid the way a Moroccan wall lays it: the pattern covers the
   lower part of the surface, closes on a listel, and the plaster above stays
   plain. Geometry comes from inc/zellige.php, which computes the khatim and
   the saft rather than approximating them.
   ========================================================================== */

.zdado {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 0;
	pointer-events: none;
	/* Exactly one course. The pattern tile is 2 x 58 = 116px in user units and
	   does not scale with the viewport, so any other height cuts the stars
	   mid-motif. Locking the band to the module means the course always
	   closes on whole tiles. */
	height: 116px;
}

.zdado__field {
	display: block;
	width: 100%;
	height: 100%;
	/* No soft fade. Tiling has an edge — it is a physical material, and
	   dissolving it into the plaster reads as a smudge rather than as a
	   moulding. The listel below is what closes it. */
}

/* The listel: the moulded strip that finishes the top course. Two rules, gold
   over blue, running the full width the way a real one does. It is a
   decorative rule rather than type, so the charter's ban on gold *text* does
   not apply — nothing here has to be read. */
.zdado__listel {
	position: absolute;
	left: 0;
	right: 0;
	top: -5px;
	height: 5px;
	background:
		linear-gradient(180deg,
			var(--color-accent) 0 3px,
			var(--color-primary-dark) 3px 5px);
	box-shadow: 0 -1px 0 rgba(255, 255, 255, .55);
}

/* And the skirting that closes it at the bottom. Without it the course runs
   off the section edge and reads as a background that got cropped rather than
   as tilework that was set. */
.zdado::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 4px;
	background: linear-gradient(180deg,
		var(--color-primary-dark) 0 2px,
		var(--color-accent) 2px 4px);
}

/* The markers band is the one place the tilework is meant to be looked at. */
.tmarkers { position: relative; overflow: hidden; }
.tmarkers > .tour__shell { position: relative; z-index: 1; }
.tmarkers .tmarkers__grid { margin-bottom: clamp(5rem, 11vw, 9rem); }

@media (max-width: 700px) {
	/* Half a course on a phone, cut on the horizontal centre line of the
	   stars, which is a join real tilework also uses. */
	.zdado { height: 58px; }
	.tmarkers .tmarkers__grid { margin-bottom: 4.5rem; }
}

/* =============================================================================
   2. THE ICON SYSTEM
   ========================================================================== */

.sh-i { display: block; overflow: visible; }

/* The plinth an icon stands on. Lit from the same upper-left as the drawing,
   with a hairline top highlight so the tile reads as a raised surface. */
.sh-tile {
	position: relative;
	display: grid;
	place-items: center;
	flex-shrink: 0;
	width: 72px;
	height: 72px;
	border-radius: 20px;
	background: linear-gradient(150deg, #FFFFFF 0%, var(--color-primary-light) 100%);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, .9),
		inset 0 -1px 0 rgba(3, 95, 165, .07),
		var(--s-lift-1);
	transition: transform .45s var(--s-ease), box-shadow .45s var(--s-ease);
}
.sh-tile::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='88' viewBox='0 0 88 88'%3E%3Cg fill='none' stroke='%23035FA5' stroke-width='1.1'%3E%3Crect x='24' y='24' width='40' height='40' transform='rotate(45 44 44)'/%3E%3C/g%3E%3C/svg%3E") center / 60px 60px no-repeat;
	opacity: .07;
	pointer-events: none;
}
.sh-tile--sm { width: 54px; height: 54px; border-radius: 16px; }
.sh-tile--lg { width: 92px; height: 92px; border-radius: 26px; }

/* On a dark or photographic ground the plinth turns to glass. */
.sh-tile--glass {
	background: rgba(255, 255, 255, .13);
	backdrop-filter: blur(14px) saturate(150%);
	-webkit-backdrop-filter: blur(14px) saturate(150%);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .34), 0 10px 30px -12px rgba(2, 46, 82, .6);
}

/* Gold plinth, reserved for the one thing in a group that is the point. */
.sh-tile--gold {
	background: linear-gradient(150deg, #FFF4CE 0%, #F2C94C 100%);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 10px 26px -10px rgba(242, 201, 76, .7);
}

/* =============================================================================
   3. THE FLOATING LAYER
   Archive objects drifting behind the content. Purely ambient: aria-hidden,
   pointer-events off, and the first thing to go when motion is reduced.
   ========================================================================== */

/* z-index -1, not 0. The section shells are static, and a positioned element
   at z-index 0 paints *above* static in-flow content — which put archive
   objects on top of the headings instead of behind them. A negative index
   drops the layer below the content while keeping it above the section's own
   background, which is exactly where these belong. */
.sf-layer {
	position: absolute;
	inset: 0;
	z-index: -1;
	overflow: hidden;
	pointer-events: none;
}

.sf-obj {
	position: absolute;
	opacity: 0;
	filter: drop-shadow(0 18px 30px rgba(2, 46, 82, .16));
	animation: sf-in 1.4s var(--s-ease-o) forwards;
	will-change: transform;
}

/* Two drift keyframes at different periods, so a group never pulses in
   unison. The translate is small — this is buoyancy, not orbit. */
@keyframes sf-in   { to { opacity: var(--sf-o, .55); } }
@keyframes sf-driftA {
	0%, 100% { transform: translate3d(0, 0, 0) rotate(var(--sf-r, 0deg)); }
	50%      { transform: translate3d(0, -18px, 0) rotate(calc(var(--sf-r, 0deg) + 4deg)); }
}
@keyframes sf-driftB {
	0%, 100% { transform: translate3d(0, 0, 0) rotate(var(--sf-r, 0deg)); }
	50%      { transform: translate3d(10px, -13px, 0) rotate(calc(var(--sf-r, 0deg) - 5deg)); }
}

.sf-obj > * { animation: sf-driftA var(--sf-d, 17s) ease-in-out infinite; }
.sf-obj:nth-child(even) > * { animation-name: sf-driftB; }

/* The pointer nudges the whole layer. shema.js writes --sf-px / --sf-py. */
.sf-obj {
	transform: translate3d(
		calc(var(--sf-px, 0) * var(--sf-depth, 1) * 1px),
		calc(var(--sf-py, 0) * var(--sf-depth, 1) * 1px), 0);
	transition: transform .9s var(--s-ease-o);
}

/* Objects never crowd the reading column on small screens. */
@media (max-width: 900px) {
	.sf-obj { display: none; }
	.sf-obj--keep { display: block; }
}

/* =============================================================================
   4. HERO — the cinematic opening
   Layers, back to front: photograph, the grade, chart lines, coordinates,
   grain, content.
   ========================================================================== */

/* ---- The composition -----------------------------------------------------
   The hero used to measure 1120px against a 900px viewport: the booking card
   was cut in half by the fold and the log sat entirely below it, so the first
   screen showed a headline and half a price. Everything here serves one
   sentence — where, what, why, how much, how to reserve, in one screen.

   Three changes carry it:

   1. The column split moved from 832/384 to roughly 58/42. A 384px card
      alongside an 88px headline reads as a widget parked next to a poster;
      at ~500px it reads as the other half of the composition.
   2. The readout came out of the top-left corner and into the head of the
      reading column, where it opens the hierarchy instead of floating in
      250px of dead space.
   3. Both columns are anchored to the same baseline, and the log spans them.
      One grid, three rows, no element free-floating over the photograph.

   The scale of the hero is deliberately held: a headline that fills the
   screen is a poster, and this page has to sell a $3,890 journey, not shout.
   -------------------------------------------------------------------------- */
.thero {
	/* The hero's own palette. Not added to :root on purpose — the charter
	   palette is fixed and site-wide, and these are three deeper values of it
	   that only this composition uses. The gold is the charter gold, not a
	   new one: it is the single colour the whole brand is recognised by. */
	--h-night: #071D2D;
	--h-navy:  #062A42;
	--h-ivory: #F8F5ED;
	--h-sand:  #E8D8B5;
	--h-mist:  #7FA8BA;
	--h-gold:  var(--color-accent);

	min-height: min(94svh, 1000px);
	padding-block: clamp(4.25rem, 7.5vh, 5.5rem) clamp(1.5rem, 3vh, 2.25rem);
}

.thero__grid {
	/* 58/42 rather than 68/32. The headline and the price read as one object
	   rather than two — see the alignment note below for which edge joins them. */
	grid-template-columns: minmax(0, 1.38fr) minmax(0, 1fr);
	column-gap: clamp(2rem, 4vw, 4rem);
	align-items: end;
}

/* ---- The join between the two columns ------------------------------------
   The composition originally hung both columns off their BOTTOM edge, which
   worked while the panel held a price, a departure and one select and came out
   roughly as tall as the reading column. The panel now carries the two package
   lists as well and runs some 400px taller, so bottom-alignment left the
   headline stranded in the lower third of the frame with an empty blue field
   above it. The client asked twice for the opposite: the headline reads first,
   so it is the TOP edge that has to line up.

   Two rules, because the top of the column and the top of the headline are not
   the same line: the column opens with the decorative coordinate readout. The
   grid rule joins the columns; the offset on the panel drops it by exactly the
   height of that readout plus one column gap, so the panel's top edge and the
   first line of the headline sit on the same horizontal.

   Scoped to the two-column width. Below 901px the grid is a single column
   (see the narrow-screen block), where the panel is already ordered directly
   under the reading column and an offset would only open a hole.
   -------------------------------------------------------------------------- */
@media (min-width: 901px) {
	.thero__grid { align-items: start; }

	.thero .tbook {
		/* 4.1875rem is the measured height of .thero__coords — three lines of
		   .6875rem monospace on the body leading, plus its two .34rem gaps.
		   The second term is .thero__col's own gap, repeated here rather than
		   hard-coded so the two cannot drift apart. */
		margin-top: calc(4.1875rem + clamp(1.1rem, 2.2vh, 1.6rem));
	}
}

.thero__col {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	/* An explicit rhythm rather than a margin on every child: the steps of the
	   hierarchy are all one value apart, and the headline gets a little more
	   air above it because it is the thing the eye should land on. */
	gap: clamp(1.1rem, 2.2vh, 1.6rem);
}

/* ---- The grade -----------------------------------------------------------
   tour.css laid a flat blue wash across the whole frame to guarantee contrast
   for the headline. It works, and it also drowns the photograph — Tangier
   became a blue rectangle with a ghost of a city in it.

   This replaces it with a directional grade in three zones, which is what the
   composition actually needs: a deep, quiet ground on the left where every
   line of type lives; a clearing through the middle where the photograph is
   the loudest thing on the screen; and a light hand on the right, so the
   picture is still alive behind and around the card rather than blanked out
   under it. Contrast is bought where it is needed rather than everywhere.
   -------------------------------------------------------------------------- */
.thero::before {
	background:
		/* Weighted DOWN, but late.
		   The old curve reached .80 by a third of the way down and .96 at the
		   foot, which was tuned when the hero held one photograph and the type
		   sat over the whole lower half of it. The slider changed the problem:
		   eight photographs now pass through this frame, and a curve that dark
		   turned every one of them into the blue rectangle this file was
		   written to avoid — Meknes lost its gate, Chefchaouen lost its town.

		   So the darkening is deferred to where it is actually earned. The log
		   occupies the bottom sixth of the hero and needs a genuine ground; the
		   headline and the lead do not, because the sideways grade below
		   already gives them one. Between the two, the picture breathes. */
		linear-gradient(180deg,
			rgba(7, 29, 45, .52) 0%,      /* seats the white header */
			rgba(7, 29, 45, .14) 13%,
			rgba(6, 42, 66, .02) 30%,     /* clear — sky, horizon, the ridge line */
			rgba(6, 42, 66, .06) 44%,
			rgba(6, 36, 58, .34) 62%,
			rgba(6, 34, 54, .70) 80%,
			rgba(7, 29, 45, .88) 92%,     /* the log starts here */
			rgba(7, 29, 45, .94) 100%),
		/* The load-bearing half of the pair. Every line of type is inside the
		   left 58%, and the gold eyebrow is the most fragile of them: at 13px
		   the brand gold needs a genuinely dark ground to clear 4.5:1, which
		   the charter is explicit about.

		   The right end lifts back to almost nothing rather than to a second
		   dark band. The card carries its own ground; darkening the glass
		   behind it as well would put the one part of the photograph the eye
		   has room to enjoy under two scrims at once. */
		linear-gradient(90deg,
			rgba(7, 29, 45, .93) 0%,
			rgba(7, 29, 45, .90) 24%,
			rgba(6, 42, 66, .66) 42%,
			rgba(6, 42, 66, .24) 56%,
			rgba(6, 42, 66, .08) 70%,
			rgba(6, 42, 66, .04) 100%);
}


/* The photograph itself, graded rather than left flat. A little contrast and
   saturation, and a slow push-in that makes the frame feel alive without
   reading as a slideshow. */
.thero__media img {
	filter: contrast(1.07) saturate(1.1) brightness(1.03);
}

/* The front page carries a single photograph, so the push-in sits on it
   directly. The tour hero carries eight, and puts the same push on the stack
   instead — see below. */
.thero__media > img,
.thero__plates {
	transform: scale(1.06);
	animation: thero-push 26s var(--s-ease-o) forwards;
}
@keyframes thero-push { to { transform: scale(1); } }

/* ---- The plates ----------------------------------------------------------
   Eight photographs in one frame, one lit at a time.

   The push-in lives on the stack rather than on each photograph on purpose.
   Per-plate zooms have to reset when a plate hands over, and that reset lands
   in the middle of the crossfade as a visible snap. One transform across the
   whole stack cannot snap, and a single 26-second drift reads as a camera
   still rolling rather than as eight separate zooms.

   Only the opening plate carries a `src`. The other seven hold `data-src` and
   are fetched by shema.js one stop ahead of being asked for — all eight are
   inside the viewport from the first paint, so `loading="lazy"` would have
   downloaded every one of them regardless.
   -------------------------------------------------------------------------- */
.thero__plates { position: absolute; inset: 0; }
.thero__plate {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 1200ms var(--s-ease);
}
.thero__plate.is-active { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
	.thero__media > img,
	.thero__plates { animation: none; transform: none; }
	.thero__plate { transition-duration: 300ms; }
}


/* The navigator's chart drawn faintly over the photograph. */
.thero__chart {
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	opacity: .3;
	-webkit-mask-image: linear-gradient(100deg, transparent 8%, #000 42%, #000 68%, transparent 96%);
	        mask-image: linear-gradient(100deg, transparent 8%, #000 42%, #000 68%, transparent 96%);
}
.thero__chart svg { width: 100%; height: 100%; }

.thero__chart .sj-ring {
	fill: none;
	stroke: rgba(255, 255, 255, .5);
	stroke-width: .6;
}
.thero__chart .sj-rhumb { stroke: rgba(242, 201, 76, .55); stroke-width: .5; }
.thero__chart .sj-grid  { stroke: rgba(255, 255, 255, .22); stroke-width: .5; }

/* The coordinate readout. Real coordinates, read off the map data — one
   reading per stop, stacked in a single cell so the block never resizes as
   the hero walks the route. */
.thero__coords {
	display: grid;
	/* An instrument, not a label: hung off a hairline, set in mono, tracked
	   wide, and indented so the rule reads as the edge of a panel. */
	padding-left: clamp(.9rem, 1.4vw, 1.15rem);
	border-left: 1px solid rgba(242, 201, 76, .45);
	font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
	font-size: .6875rem;
	letter-spacing: .16em;
	/* .82 measured at 3.9:1 over the brightest part of the horizon. Decorative
	   and aria-hidden, but nothing on this page should be text you cannot
	   actually read. */
	color: rgba(255, 255, 255, .82);
	text-transform: uppercase;
	pointer-events: none;
}
.thero__coord {
	grid-area: 1 / 1;
	display: grid;
	gap: .34rem;
	margin: 0;
	opacity: 0;
	transition: opacity 700ms var(--s-ease);
}
.thero__coord.is-active { opacity: 1; }
/* The zone line is the least of the three and says so. */
.thero__coord span + span { color: var(--h-mist); }

/* Same reasoning for the separator between the brand and the duration. */
.thero__meta span { color: rgba(255, 255, 255, .8); }
/* The departure window is content, not punctuation, so it keeps the accent
   colour of the line it sits on. Tabular figures so the two days line up. */
.thero__meta .thero__meta-dates {
	color: inherit;
	font-variant-numeric: tabular-nums;
}
.thero__coords strong {
	display: flex;
	align-items: center;
	gap: .5rem;
	font-weight: 600;
	color: var(--color-accent);
}
.thero__coords strong::before {
	content: "";
	width: 7px; height: 7px;
	border-radius: 50%;
	background: var(--color-accent);
}
/* The beacon pulses only where the traveller actually is: seven hidden
   readouts running an infinite animation each is seven compositor layers
   doing nothing anyone can see. */
.thero__coord.is-active strong::before {
	box-shadow: 0 0 0 0 rgba(242, 201, 76, .7);
	animation: sh-beacon 2.8s ease-out infinite;
}
@keyframes sh-beacon {
	0%   { box-shadow: 0 0 0 0 rgba(242, 201, 76, .65); }
	70%  { box-shadow: 0 0 0 12px rgba(242, 201, 76, 0); }
	100% { box-shadow: 0 0 0 0 rgba(242, 201, 76, 0); }
}

/* ---- The reading column --------------------------------------------------
   The steps of the hierarchy, tuned as a set. Sizes are held below the tokens
   the rest of the site uses: at 88px the headline was wider than its own
   column and pushed the lead and the pillars off the first screen. */
.thero__meta { margin-bottom: 0; }

.thero__title {
	/* Three lines, always — the markup sets the first two breaks itself, since
	   the gold half is its own block. The measure only has to be wide enough
	   that the longest of the three, "Jewish Heritage & Culture" at 25
	   characters, is not broken a fourth time; 14ch was cut for the old
	   33-character headline and split it into five.

	   The size comes down with it. The headline went from 33 characters to 53,
	   and at the old 4.5rem ceiling three lines of it stood 243px tall and
	   pushed the lead, the pillars and the call to action off the first
	   screen. A quarter off the ceiling buys the extra line back. */
	max-width: 22ch;
	font-size: clamp(2.125rem, 3.7vw, 3.375rem);
	line-height: .97;
	letter-spacing: -.038em;
	margin-bottom: 0;
	/* Fraunces has a real optical-size axis: pushed to display, the hairlines
	   thin and the serifs sharpen, which is the whole reason the face is here. */
	font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 0;
}
/* The emotional half of the title. Gold, and set a hair lighter — at this size
   the gold reads heavier than the ivory at the same weight. */
.thero__title em { font-weight: 500; }

.thero__lead {
	max-width: 47ch;          /* ≈ 620px at this size */
	font-size: clamp(1rem, 1.15vw, 1.125rem);
	line-height: 1.62;
	/* .94, not the .88 used elsewhere over photographs: measured against the
	   brightest pixel the lead actually sits on, .88 came to 4.29:1 and this
	   clears 4.5. The headline can afford to be looser; body copy cannot. */
	color: rgba(255, 255, 255, .94);
	margin-bottom: 0;
}

/* ---- The trust row -------------------------------------------------------
   Four claims, hairline-separated, one line. As stacked icon chips they
   competed with the pillars section further down the page; as a rule they
   read as a footnote to the headline, which is what they are. */
.thero__pillars {
	/* A grid, not a wrapping flex row. Wrapped, the fourth claim carried its
	   separator to the head of a new line and left a rule hanging in space;
	   four fixed columns keep every rule between two claims. */
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 0;
	margin-bottom: 0;
	padding-top: clamp(.3rem, .8vh, .7rem);
	/* Held to a measure, not run full width. Free, the fourth claim lands at
	   750px — out past where the grade has cleared — and drops to 3.3:1 over a
	   bright frame. Inside 680px the worst pixel under it measures 4.84:1. */
	max-width: 680px;
}
.thero__pillar {
	max-width: none;
	align-items: flex-start;
	gap: .45rem;
	padding-inline: clamp(.55rem, 1.1vw, .85rem);
	font-size: .78125rem;
	letter-spacing: .01em;
	color: rgba(255, 255, 255, .92);      /* same measurement, same reason */
	border-left: 1px solid rgba(255, 255, 255, .16);
}
.thero__pillar:first-child { padding-left: 0; border-left: 0; }
.thero__pillar svg { width: 16px; height: 16px; opacity: .9; }

.thero__cta { margin-top: clamp(.2rem, .6vh, .5rem); }

/* Between a small laptop and the tablet break the shell is narrow enough that
   58/42 leaves the panel at 333px. The split evens out. */
@media (min-width: 901px) and (max-width: 1150px) {
	.thero__grid { grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr); column-gap: 2rem; }
	/* The same quarter off the ceiling as the unqualified rule above, for the
	   same reason: the reading column is only 1.08fr here, so the longer
	   headline runs out of measure sooner rather than later.

	   Held a little above the strict ratio (3.4vw rather than the 3.1vw the
	   old 4.2/4.9 relationship would give). Measured at 1024px the strict
	   value put the headline at 31.7px against a 24px card heading, which is
	   not enough separation for the largest type on the page to read as the
	   largest type on the page. 34.8px restores it, and the longest line still
	   clears the 473px column by 145px. */
	.thero__title { font-size: clamp(2rem, 3.4vw, 2.75rem); }
}

/* ---- Narrow screens ------------------------------------------------------
   Not the desktop composition scaled down. Below 900px the two columns become
   one, which changes what each element is for: the readout is no longer a
   caption floating beside a picture but the first line of the page, and the
   gold call to action is no longer a shortcut to a card on the right — the
   card is the very next thing on the screen.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
	/* ---- The photograph gets a band of its own ---------------------------
	   Full-bleed was a desktop assumption, and on a phone it cost the hero its
	   picture twice over.

	   Measured at 390px: the hero is 1702px tall and 390px wide, so
	   `object-fit: cover` on a 1920x1080 plate shows **12% of the photograph's
	   width, upscaled 1.7x** — the sky over Tangier, never the medina. And the
	   scrim above it, calibrated for a reading column that occupies the left
	   58% of a wide frame, sits at ~95% opacity over that sliver because on one
	   column the type spans the full width. Photograph gone; blue rectangle
	   left. It stayed that way up to 900px (30% of the plate at best).

	   So the plate is given a band at the top of the hero and the type sits
	   below it on the brand ground. The band keeps its own proportions, so 46%
	   of the photograph survives at 390px and 90% at 768px, none of it
	   upscaled — and no line of type stands over a photograph any more, which
	   is the whole reason the scrim was that heavy.
	   -------------------------------------------------------------------- */
	/* THE EMPTY SPACE ABOVE THE HEADLINE ON MOBILE.
	   -------------------------------------------------------------------
	   --thero-band is the whole cause. Below 901px the photograph stops being
	   a background and becomes a band at the top of the hero, and the type is
	   pushed clear of it by padding-top on .thero. That padding is the band's
	   height, so the band's height *is* the distance to the first line of
	   type — nothing else on this page contributes to it.

	   At 44svh capped to 24rem, a tall handset resolved the cap: 384px of
	   photograph before the headline, and the price panel opening near 900px.
	   The visitor met a picture, scrolled, and only then learned what they
	   were looking at.

	   30svh capped to 17rem takes 112px out of that, which is the movement
	   asked for. The plate stays a photograph — 272px at the cap, still
	   markedly wider than it is tall on a 390-416px screen — and object-fit:
	   cover means the framing is unchanged, only the window onto it is
	   shorter. Headline, duration, dates and lead now open on the first
	   screen with the panel immediately after.

	   Two things deliberately NOT touched, having been measured rather than
	   assumed:
	   - min-height on .thero. tour.css:949 tries to release it at this width
	     and loses the cascade to the unconditional rule at line 346 of this
	     file. It looks like a bug and is worth knowing about, but it creates
	     no gap here: on mobile the hero also carries the price panel and the
	     stop carousel, so it is far taller than the 1000px floor and the
	     floor never applies.
	   - .thero__media / the gradient stops. Both are already measured off
	     --thero-band, so they follow this single value with no edit.
	   -------------------------------------------------------------------- */
	.thero {
		/* The band is now a rule, not a plate. The client asked four times for
		   the top of this page to close up and then sent the target: header,
		   a warm seam of sky, and straight into the headline. 44svh reserved
		   384px before a word was read; this reserves about 56.

		   The photograph is not lost — .thero__media still carries it and the
		   journey's images run through the stops carousel and the gallery
		   below. What changes is that the hero no longer spends half a phone
		   screen introducing itself before saying what it is. */
		--thero-band: 3rem;                         /* svh fallback */
		--thero-band: clamp(2rem, 6svh, 3.5rem);
		padding-block: calc(var(--thero-band) + clamp(1rem, 3vw, 1.4rem)) clamp(1.25rem, 3vh, 2rem);
	}

	/* THE PHOTOGRAPH IS THE GROUND AGAIN (client request, 17/08/2026).
	   ------------------------------------------------------------------
	   It had been cropped to a seam of sky at the very top — a deliberate
	   earlier decision, to stop the hero spending half a phone screen
	   introducing itself. The ask has changed: the eight plates are to run
	   behind the whole hero on mobile as they already do on desktop.

	   The band variable is kept and still governs the padding, so the
	   headline lands exactly where it does now. Only the plate's height
	   changes — nothing above moves.

	   6rem of headroom stays: the parallax pushes the plate *down* by 18% of
	   its own height, and without the overhang the top edge would ride into
	   frame at the end of the scroll. `overflow: hidden` on the hero clips it. */
	.thero__media {
		inset: -6rem 0 0;
		height: auto;
	}

	/* A panorama cropped to a phone's aspect keeps its horizon rather than its
	   centre: the skyline is the half worth seeing, the foreground pavement is
	   not. */
	.thero__media img { object-position: center 32%; }

	/* The scrim now has a photograph to cover for its whole height, so it
	   deepens steadily instead of landing on flat navy. Measured for white
	   type: .48 at the headline is 7.4:1 over the lightest sky in the eight
	   plates, and the gold eyebrow holds 4.9:1 at the same point. */
	.thero__media::after {
		content: "";
		position: absolute;
		inset: 0;
		background: linear-gradient(180deg,
			rgba(7, 29, 45, .52) 0,
			rgba(7, 29, 45, .30) 6rem,
			rgba(7, 29, 45, .34) calc(6rem + var(--thero-band)),
			rgba(7, 29, 45, .58) 46%,
			rgba(7, 29, 45, .76) 78%,
			rgba(7, 29, 45, .88) 100%);
	}

	/* The hero's own scrim stays light: two heavy veils stacked would grey the
	   photograph out entirely, which is the failure this change exists to
	   undo. It only adds the last of the contrast under the log, where the
	   type is densest. */
	.thero::before {
		background: linear-gradient(180deg,
			rgba(7, 29, 45, 0) 0,
			rgba(7, 29, 45, .06) calc(var(--thero-band) + 6rem),
			rgba(7, 29, 45, .18) 72%,
			rgba(7, 29, 45, .34) 100%);
	}

	/* tour.css already collapses the hero to one column here. The 58/42 split
	   above is unqualified and outranks it by load order, so it has to be
	   handed back explicitly — without this the reading column is 189px wide
	   at 390px and the headline breaks into four lines. */
	.thero__grid { grid-template-columns: 1fr; }

	/* 22ch is the desktop break. 20ch was cut for the old two-line headline;
	   with the current one it breaks the gold line a second time. 24ch holds
	   the three lines the headline is written as down to a 390px screen. */
	.thero__title { max-width: 24ch; }

	/* The coordinate line is 22 characters of tracked monospace: at .16em it
	   cannot fit 358px and wrapped mid-reading. */
	.thero__coords { font-size: .625rem; letter-spacing: .1em; }

	.thero__meta { flex-wrap: wrap; gap: .35rem .75rem; font-size: .75rem; }

	/* Two up rather than four down. */
	.thero__pillars {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: .6rem 0;
	}
	.thero__pillar { padding-inline: 0 .9rem; border-left: 0; }
	.thero__pillar:nth-child(2n) { padding-inline: .9rem 0; border-left: 1px solid rgba(255, 255, 255, .16); }

	/* The gold button pointed at #tour-book, which on this width is the panel
	   directly beneath it — a scroll of zero. The route link still goes
	   somewhere the visitor cannot already see. */
	.thero__cta .tbtn--gold { display: none; }

	/* tour.css put the card last on this width, behind the log. That was right
	   when the hero was a headline and a card; it is wrong now that the left
	   column ends on a call to action, because it buries the price under 400px
	   of stop narrative. Panel first, log after it. */
	.thero .tbook { order: 0; }
	.thero__log { order: 3; }
}

/* ---- The log -------------------------------------------------------------
   What the readout in the sky cannot hold: the day, what the place is, and
   what the journey actually visits there.

   It spans both columns beneath the headline and the booking card rather than
   floating anywhere near them. A panel placed alongside the title collides
   with it the moment the viewport gets short — this one cannot, at any height,
   because it is a row in the same grid and the grid resolves the collision.

   The eight entries share one cell, so the tallest sets the height once and
   nothing below the hero moves as the route advances.
   -------------------------------------------------------------------------- */
.thero__grid { row-gap: clamp(1.5rem, 3vw, 2.25rem); }

.thero__log {
	grid-column: 1 / -1;
	display: grid;
	gap: clamp(1rem, 2vw, 1.4rem);
	padding-top: clamp(1.1rem, 2.2vw, 1.6rem);
	border-top: 1px solid rgba(255, 255, 255, .18);
}

.thero__log__stack { display: grid; }

.thero__entry {
	grid-area: 1 / 1;
	max-width: 64ch;
	opacity: 0;
	transform: translateY(8px);
	transition: opacity 620ms var(--s-ease), transform 620ms var(--s-ease);
	pointer-events: none;
}
.thero__entry.is-active { opacity: 1; transform: none; pointer-events: auto; }

.thero__entry__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .6rem;
	margin: 0 0 .5rem;
	font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
	font-size: .6875rem;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .78);
}
.thero__entry__meta span[aria-hidden] { color: rgba(255, 255, 255, .4); }
.thero__entry__step { color: var(--color-accent); font-weight: 600; }

/* The name is the readout's job, at every width. */
.thero__entry__name { display: none; }

.thero__entry__note {
	margin: 0 0 .35rem;
	font-family: var(--et-font-head);
	/* Held down from 1.75rem: the log is a footnote to the hero, and at the
	   old size it competed with the headline two rows above it for the same
	   eye — while costing the first screen 30px it could not spare. */
	font-size: clamp(1.1875rem, 1.6vw, 1.4375rem);
	font-weight: 600;
	line-height: 1.15;
	color: #fff;
}

.thero__entry__blurb {
	margin: 0 0 .55rem;
	max-width: 68ch;
	font-size: clamp(.875rem, 1vw, .9375rem);
	line-height: 1.55;
	color: rgba(255, 255, 255, .78);
}

.thero__entry__sites {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .35rem .9rem;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: .8125rem;
	letter-spacing: .01em;
	color: rgba(255, 255, 255, .68);
}
.thero__entry__sites li { display: flex; align-items: center; gap: .9rem; }
.thero__entry__sites li + li::before {
	content: "";
	width: 3px; height: 3px;
	border-radius: 50%;
	background: rgba(242, 201, 76, .75);
}

/* ---- The controls --------------------------------------------------------
   Dots first, arrows after: the dots are the map of where you are in the
   route, the arrows are only a convenience on top of them.
   -------------------------------------------------------------------------- */
.thero__controls {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
}

.thero__dots {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.thero__dot {
	display: grid;
	place-items: center;
	/* A 9px dot is not a tap target. The button is, and it is the same height
	   as the arrows beside it so the whole row sits on one line. */
	min-width: 24px;
	min-height: 44px;
	padding: 0 .2rem;
	border: 0;
	background: none;
	cursor: pointer;
}
.thero__dot i {
	display: block;
	position: relative;
	width: 9px; height: 9px;
	border-radius: 999px;
	background: rgba(255, 255, 255, .34);
	overflow: hidden;
	transition: width 420ms var(--s-ease-o), background-color 300ms var(--s-ease);
}
.thero__dot:hover i { background: rgba(255, 255, 255, .6); }
.thero__dot.is-active i { width: 46px; background: rgba(255, 255, 255, .22); }

/* The dwell, drawn. The bar fills over exactly the time the stop is held, so
   the slider tells you it is about to move instead of surprising you. */
.thero__dot.is-active i::after {
	content: "";
	position: absolute;
	inset: 0;
	transform: scaleX(0);
	transform-origin: left center;
	background: var(--color-accent);
	animation: thero-dwell var(--slider-dwell, 6800ms) linear forwards;
}
@keyframes thero-dwell { to { transform: scaleX(1); } }

/* Paused — pointer over the hero, focus inside it, tab in the background, or
   the hero scrolled out of view. The bar holds where it stopped. */
.thero.is-paused .thero__dot.is-active i::after { animation-play-state: paused; }

/* No autoplay at all: reduced motion, or a single stop. Nothing to count
   down, so the active dot simply reads as full. */
.thero.is-manual .thero__dot.is-active i::after { animation: none; transform: scaleX(1); }

.thero__arrows { display: flex; gap: .5rem; }
.thero__arrow {
	display: grid;
	place-items: center;
	width: 2.75rem; height: 2.75rem;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, .28);
	background: rgba(255, 255, 255, .07);
	-webkit-backdrop-filter: blur(6px);
	        backdrop-filter: blur(6px);
	color: #fff;
	cursor: pointer;
	transition: background-color 300ms var(--s-ease), border-color 300ms var(--s-ease);
}
.thero__arrow:hover { background: rgba(255, 255, 255, .18); border-color: var(--color-accent); }
.thero__arrow svg { width: 18px; height: 18px; }
.thero__arrow[data-hero-prev] svg { transform: rotate(180deg); }

/* The site-wide focus ring is brand blue, which is the one colour that
   disappears against this hero. Gold, and offset clear of the dot. */
.thero__dot:focus-visible,
.thero__arrow:focus-visible {
	outline: 3px solid var(--color-accent);
	outline-offset: 3px;
	border-radius: 999px;
}

/* Wide enough to seat the controls beside the entry rather than under it.
   The hero is already a tall composition — the booking card alone is most of
   a viewport — so a row saved here is a row the visitor does not have to
   scroll past to reach the rest of the page. */
@media (min-width: 1101px) {
	.thero__log {
		grid-template-columns: minmax(0, 1fr) auto;
		align-items: end;
		column-gap: clamp(2rem, 5vw, 4rem);
	}
	.thero__controls { justify-content: flex-end; }
}

/* The 1100px fallback that put the name back in the log is gone with the
   reason for it: the readout now sits in the reading column and survives to
   the narrowest phone, so the name is never missing and never doubled. */

@media (max-width: 640px) {
	/* The blurb is not truncated here. It is the reason the log exists, and
	   the two lines it costs are cheap on a page this long. */
	.thero__controls { justify-content: flex-start; }
	/* Tighter dots so the eight of them and both arrows still fit one row at
	   390px — but the arrows keep their 44px, which is the point of them. */
	.thero__dots { gap: .25rem; }
	.thero__dot { min-width: 20px; }
}

/* Golden light raking in from the upper right, matching the hour in the
   photograph underneath. */
.thero__light {
	position: absolute;
	right: -14%;
	top: -22%;
	width: 62vw;
	max-width: 820px;
	aspect-ratio: 1;
	z-index: -1;
	pointer-events: none;
	background: radial-gradient(circle, rgba(255, 214, 120, .30) 0%, rgba(242, 201, 76, .10) 42%, transparent 70%);
}

/* Slow ambient particles — dust in a sunbeam, six of them, nothing more. */
.thero__motes { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.thero__mote {
	position: absolute;
	width: 3px; height: 3px;
	border-radius: 50%;
	background: rgba(255, 235, 180, .8);
	filter: blur(.4px);
	animation: sh-mote var(--m-d, 26s) linear infinite;
	animation-delay: var(--m-delay, 0s);
	opacity: 0;
}
@keyframes sh-mote {
	0%   { opacity: 0; transform: translate3d(0, 0, 0); }
	12%  { opacity: .85; }
	88%  { opacity: .5; }
	100% { opacity: 0; transform: translate3d(var(--m-x, 40px), -74vh, 0); }
}

/* The scroll cue that used to sit at the foot of the hero is gone: the log and
   its dots now occupy that edge, and two things at the bottom of the frame
   both saying "there is more below" is one thing too many. */

/* =============================================================================
   5. THE JOURNEY MAP
   The centrepiece. Left: a real projection of northern Morocco carrying the
   route. Right: the stop the visitor has selected.
   ========================================================================== */

.sjmap { position: relative; overflow: hidden; }

.sjmap__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr);
	gap: clamp(1.75rem, 4vw, 3.5rem);
	align-items: center;
	margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

.sjmap__grid > .sh-rise:nth-child(2) { --i: 2; }

/* ---- The canvas ---------------------------------------------------------- */
.sjmap__canvas {
	position: relative;
	border-radius: 28px;
	overflow: hidden;
	background:
		radial-gradient(120% 90% at 18% 22%, #F3FAFE 0%, #DFF0FA 46%, #C4E2F3 100%);
	box-shadow: var(--s-lift-2), inset 0 0 0 1px rgba(3, 95, 165, .1);
}
.sjmap__canvas svg { display: block; width: 100%; height: auto; }

/* Sea. The graticule sits on the water only, the way a chart is ruled. */
.sj-sea-grid { stroke: rgba(3, 95, 165, .13); stroke-width: 1; fill: none; }

.sj-land {
	fill: url(#sj-land-fill);
	stroke: none;
}
.sj-coast {
	fill: none;
	stroke: #A8875A;
	stroke-width: 2.4;
	stroke-linejoin: round;
	stroke-linecap: round;
	opacity: .75;
}

/* Terrain. A wide soft band carries the mass of the range, a hairline on top
   carries its spine — together they read as relief instead of as roads. */
.sj-relief-band {
	fill: none;
	stroke: #C8A87A;
	stroke-width: 26;
	stroke-linecap: round;
	opacity: .2;
	filter: blur(9px);
}
.sj-relief-line {
	fill: none;
	stroke: #B08D5E;
	stroke-width: 1.5;
	stroke-linecap: round;
	opacity: .38;
}

.sj-sea-label {
	fill: #0B6FA8;
	font-size: 21px;
	font-weight: 600;
	letter-spacing: .3em;
	text-transform: uppercase;
	opacity: .4;
}

/* ---- The route ----------------------------------------------------------- */
.sj-route-glow {
	fill: none;
	stroke: rgba(3, 95, 165, .17);
	stroke-width: 13;
	stroke-linecap: round;
	filter: blur(7px);
}
.sj-route {
	fill: none;
	stroke: var(--color-primary);
	stroke-width: 3.6;
	stroke-linecap: round;
	stroke-dasharray: 11 9;
}
/* Drawn on first sight. shema.js measures the path and sets --sj-len. */
.sjmap.is-drawing .sj-route,
.sjmap.is-drawing .sj-route-glow {
	stroke-dasharray: var(--sj-len);
	stroke-dashoffset: var(--sj-len);
}
.sjmap.is-drawn .sj-route,
.sjmap.is-drawn .sj-route-glow {
	stroke-dashoffset: 0;
	transition: stroke-dashoffset 2.6s cubic-bezier(.4, 0, .2, 1);
}
/* Once drawn, hand the stroke back to its travelling dash. */
.sjmap.is-drawn.is-settled .sj-route { stroke-dasharray: 11 9; animation: sj-flow 1.4s linear infinite; }
@keyframes sj-flow { to { stroke-dashoffset: -20; } }

/* The traveller: a bead that runs the route once it is drawn. */
.sj-bead { fill: var(--color-accent); stroke: #fff; stroke-width: 2.4; opacity: 0; transition: opacity .5s ease; }
.sjmap.is-settled .sj-bead { opacity: 1; }
.sj-bead-halo { fill: rgba(242, 201, 76, .3); opacity: 0; transition: opacity .5s ease; }
.sjmap.is-settled .sj-bead-halo { opacity: 1; }

/* ---- Markers ------------------------------------------------------------- */
.sj-stop { cursor: pointer; }
.sj-stop:focus { outline: none; }
.sj-stop:focus-visible .sj-stop__hit {
	stroke: var(--color-primary);
	stroke-width: 3;
	stroke-dasharray: 4 3;
	opacity: 1;
}
.sj-stop__hit { fill: transparent; opacity: 0; }

.sj-stop__pulse {
	fill: rgba(3, 95, 165, .22);
	transform-box: fill-box;
	transform-origin: center;
	opacity: 0;
}
.sj-stop.is-active .sj-stop__pulse { opacity: 1; animation: sj-pulse 2.6s ease-out infinite; }
@keyframes sj-pulse {
	0%   { transform: scale(.6); opacity: .7; }
	80%  { transform: scale(2.5); opacity: 0; }
	100% { transform: scale(2.5); opacity: 0; }
}

.sj-stop__dot {
	fill: #FFFFFF;
	stroke: var(--color-primary);
	stroke-width: 3.4;
	transition: fill .3s var(--s-ease), stroke .3s var(--s-ease), r .3s var(--s-ease);
}
.sj-stop:hover .sj-stop__dot { stroke: var(--color-primary-dark); }
.sj-stop.is-active .sj-stop__dot { fill: var(--color-accent); stroke: var(--color-primary-dark); }

.sj-stop__num {
	fill: var(--color-primary-dark);
	font-size: 20px;
	font-weight: 700;
	text-anchor: middle;
	dominant-baseline: central;
	pointer-events: none;
}

.sj-stop__label {
	fill: var(--color-text-primary);
	font-size: 26px;
	font-weight: 600;
	dominant-baseline: central;
	pointer-events: none;
	paint-order: stroke;
	stroke: rgba(255, 255, 255, .85);
	stroke-width: 5;
	stroke-linejoin: round;
	transition: fill .3s var(--s-ease);
}
.sj-stop.is-active .sj-stop__label { fill: var(--color-primary-dark); }
.sj-stop__label--left  { text-anchor: end; }
.sj-stop__label--right { text-anchor: start; }

.sj-stop__days {
	fill: var(--color-text-secondary);
	font-size: 18px;
	font-weight: 600;
	letter-spacing: .1em;
	dominant-baseline: central;
	pointer-events: none;
	paint-order: stroke;
	stroke: rgba(255, 255, 255, .85);
	stroke-width: 4;
	stroke-linejoin: round;
}
.sj-stop__days--left  { text-anchor: end; }
.sj-stop__days--right { text-anchor: start; }

/* ---- The detail panel ---------------------------------------------------- */
.sjmap__panel {
	position: relative;
	border-radius: 26px;
	overflow: hidden;
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	box-shadow: var(--s-lift-2);
}

.sjmap__media {
	position: relative;
	aspect-ratio: 4 / 3;
	overflow: hidden;
	background: var(--color-primary-light);
}
.sjmap__media img {
	position: absolute;
	inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
}
/* Cross-fade between stops rather than a hard swap. */
.sjmap__media .sj-shot { opacity: 0; transition: opacity .6s var(--s-ease), transform 1.4s var(--s-ease); transform: scale(1.06); }
.sjmap__media .sj-shot.is-shown { opacity: 1; transform: scale(1); }

.sjmap__media::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(2, 74, 130, .06) 40%, rgba(2, 74, 130, .82) 100%);
}

.sjmap__stamp {
	position: absolute;
	left: 1.15rem; top: 1.15rem;
	z-index: 2;
	display: flex;
	align-items: center;
	gap: .6rem;
	padding: .42rem .85rem .42rem .5rem;
	border-radius: 100px;
	background: rgba(255, 255, 255, .16);
	backdrop-filter: blur(14px) saturate(150%);
	-webkit-backdrop-filter: blur(14px) saturate(150%);
	border: 1px solid rgba(255, 255, 255, .3);
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: #fff;
}
.sjmap__stamp b {
	display: grid;
	place-items: center;
	width: 22px; height: 22px;
	border-radius: 50%;
	background: var(--color-accent);
	color: var(--color-primary-dark);
	font-size: .75rem;
}

.sjmap__emblem {
	position: absolute;
	right: 1rem; bottom: 1rem;
	z-index: 2;
	width: 74px; height: 74px;
	filter: drop-shadow(0 12px 24px rgba(2, 46, 82, .5));
}
/* All eight emblems are drawn once and stacked; selecting a stop cross-fades
   between them rather than rebuilding SVG on every click. */
.sjmap__emblem > span {
	position: absolute;
	inset: 0;
	opacity: 0;
	transform: scale(.9);
	transition: opacity .45s var(--s-ease), transform .45s var(--s-ease);
}
.sjmap__emblem > span.is-shown { opacity: 1; transform: none; }

.sjmap__title {
	position: absolute;
	left: 1.4rem; bottom: 1.15rem;
	z-index: 2;
	color: #fff;
}
.sjmap__title h3 { font-size: clamp(1.5rem, 2.4vw, 2rem); color: #fff; margin: 0; }
.sjmap__title p {
	margin: .1rem 0 0;
	font-size: .8125rem;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--color-accent);
}

.sjmap__body { padding: 1.5rem 1.5rem 1.65rem; }
.sjmap__body > p { font-size: .9375rem; line-height: 1.7; color: var(--color-text-secondary); margin: 0 0 1.1rem; }

.sjmap__sites { list-style: none; padding: 0; margin: 0; display: grid; gap: .5rem; }
.sjmap__sites li {
	display: flex;
	align-items: flex-start;
	gap: .6rem;
	font-size: .875rem;
	line-height: 1.5;
	color: var(--color-text-primary);
}
.sjmap__sites li::before {
	content: "";
	flex-shrink: 0;
	width: 6px; height: 6px;
	margin-top: .48rem;
	border-radius: 1px;
	background: var(--color-accent);
	transform: rotate(45deg);
}

/* Fading the panel out and in keeps the swap from reading as a jump cut. */
.sjmap__panel .sj-swap { transition: opacity .32s ease, transform .32s var(--s-ease); }
.sjmap__panel.is-swapping .sj-swap { opacity: 0; transform: translateY(7px); }

/* ---- The stop rail — the map's keyboard-friendly twin --------------------- */
.sjmap__rail {
	display: flex;
	flex-wrap: wrap;
	gap: .45rem;
	margin-top: clamp(1.5rem, 3vw, 2rem);
	justify-content: center;
}
.sjmap__railbtn {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	padding: .5rem .95rem;
	border: 1px solid var(--color-border);
	border-radius: 100px;
	background: var(--color-surface);
	color: var(--color-text-secondary);
	font: inherit;
	font-size: .8125rem;
	font-weight: 600;
	cursor: pointer;
	transition: border-color .3s var(--s-ease), color .3s var(--s-ease),
	            background-color .3s var(--s-ease), transform .3s var(--s-ease);
}
.sjmap__railbtn b {
	display: grid;
	place-items: center;
	width: 19px; height: 19px;
	border-radius: 50%;
	background: var(--color-primary-light);
	color: var(--color-primary);
	font-size: .6875rem;
}
.sjmap__railbtn:hover { border-color: var(--color-secondary); color: var(--color-text-primary); transform: translateY(-2px); }
.sjmap__railbtn.is-active {
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: #fff;
}
.sjmap__railbtn.is-active b { background: var(--color-accent); color: var(--color-primary-dark); }

@media (max-width: 980px) {
	.sjmap__grid { grid-template-columns: 1fr; }
	.sj-stop__label { font-size: 30px; }
	.sj-stop__days { font-size: 22px; }
	.sj-stop__num  { font-size: 20px; }
}

/* =============================================================================
   6. EIGHT CITIES — ONE STORY
   One city at a time. The grid of eight postcards this replaces made the
   visitor compare, which the map and the itinerary already ask of them; this
   gives a single city the room to be read.
   ========================================================================== */

/* ---- The rail ------------------------------------------------------------
   Names, not dots. These are places a visitor came looking for, and the same
   pill language the map rail already speaks two sections up.
   -------------------------------------------------------------------------- */
.scities__rail {
	display: flex;
	flex-wrap: wrap;
	gap: .45rem;
	margin-top: clamp(2rem, 4vw, 2.75rem);
}

.scities__tab {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	padding: .5rem .95rem;
	border: 1px solid var(--color-border);
	border-radius: 100px;
	background: var(--color-surface);
	color: var(--color-text-secondary);
	font: inherit;
	font-size: .8125rem;
	font-weight: 600;
	cursor: pointer;
	overflow: hidden;
	transition: border-color .3s var(--s-ease), color .3s var(--s-ease),
	            background-color .3s var(--s-ease), transform .3s var(--s-ease);
}
.scities__tab b {
	display: grid;
	place-items: center;
	width: 19px; height: 19px;
	border-radius: 50%;
	background: var(--color-primary-light);
	color: var(--color-primary);
	font-size: .6875rem;
}
.scities__tab:hover {
	border-color: var(--color-secondary);
	color: var(--color-text-primary);
	transform: translateY(-2px);
}
.scities__tab.is-active {
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: #fff;
}
.scities__tab.is-active b { background: var(--color-accent); color: var(--color-primary-dark); }

/* The dwell, drawn along the foot of the live tab: the band says it is about
   to move rather than surprising anyone. */
.scities__tab i {
	position: absolute;
	/* Inset rather than edge to edge: a pill this round clips a full-width
	   bar down to a sliver at its own bottom curve. */
	left: .95rem; right: .95rem; bottom: 5px;
	height: 2px;
	border-radius: 2px;
	background: var(--color-accent);
	transform: scaleX(0);
	transform-origin: left center;
}
.scities__tab.is-active i {
	animation: scity-dwell var(--slider-dwell, 9000ms) linear forwards;
}
@keyframes scity-dwell { to { transform: scaleX(1); } }

.scities.is-paused .scities__tab.is-active i { animation-play-state: paused; }
/* Autoplay is over — the visitor chose a city, or asked for reduced motion.
   Nothing left to count down. */
.scities.is-manual .scities__tab.is-active i { animation: none; transform: scaleX(0); }

/* ---- The stage ----------------------------------------------------------- */
.scities__stage {
	display: grid;
	grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
	gap: clamp(1.5rem, 3.5vw, 3rem);
	/* Stretched, so the arrows can sit on the photograph's bottom edge rather
	   than orphaned in whatever whitespace the shortest entry leaves. */
	align-items: stretch;
	margin-top: clamp(1.5rem, 3vw, 2.25rem);
}

.scities__plates {
	position: relative;
	aspect-ratio: 4 / 3;
	border-radius: 22px;
	overflow: hidden;
	isolation: isolate;
	background: var(--color-primary-light);
	border: 1px solid var(--color-border);
	box-shadow: var(--s-lift-2);
}
.scities__plate {
	position: absolute;
	inset: 0;
	margin: 0;
	opacity: 0;
	transition: opacity 900ms var(--s-ease);
}
.scities__plate.is-active { opacity: 1; }
.scities__plate img { width: 100%; height: 100%; object-fit: cover; }

/* A corner shadow under the step plate, and a breath of blue along the top —
   depth, and a darker corner for the plate to sit in. */
.scities__plate::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(58% 42% at 0% 0%, rgba(1, 30, 56, .40), transparent 74%),
		linear-gradient(180deg, rgba(2, 74, 130, .12) 0%, transparent 28%);
}

/* The step number, set as a plate the way a plan is annotated.
   Measured at .16 white over the eight photographs it now has to sit on, the
   number came in between 1.29:1 and 2.72:1 — a glass plate borrows its ground
   from whatever is behind it, and behind it is sometimes a blown-out sky. It
   carries its own ground now: deep navy at .88, which holds white above 4.5:1
   on every one of them, with the brand gold kept as a hairline. */
.scities__step {
	position: absolute;
	top: .9rem; left: .9rem;
	z-index: 2;
	display: grid;
	place-items: center;
	width: 38px; height: 38px;
	border-radius: 12px;
	background: rgba(1, 34, 63, .88);
	-webkit-backdrop-filter: blur(10px);
	        backdrop-filter: blur(10px);
	border: 1px solid rgba(242, 201, 76, .5);
	font-family: var(--et-font-head);
	font-size: 1rem;
	font-weight: 600;
	color: #fff;
}

/* ---- The panels ---------------------------------------------------------- */
.scities__panels {
	display: grid;
	grid-template-rows: auto auto;
	align-content: space-between;
	gap: clamp(1.25rem, 2.5vw, 1.75rem);
}

/* Eight panels in one cell: the longest entry sets the height once, and
   nothing below this section moves when the city changes. */
.scities__stack { display: grid; }
.scities__panel {
	grid-area: 1 / 1;
	position: relative;
	opacity: 0;
	transform: translateY(10px);
	transition: opacity 520ms var(--s-ease), transform 520ms var(--s-ease);
	pointer-events: none;
}
.scities__panel.is-active { opacity: 1; transform: none; pointer-events: auto; }

.scities__emblem {
	display: block;
	margin-bottom: .75rem;
	filter: drop-shadow(0 10px 22px rgba(2, 46, 82, .18));
}

.scities__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .55rem;
	margin: 0;
	font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
	font-size: .6875rem;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--color-text-secondary);
}
.scities__meta span[aria-hidden] { color: var(--color-border); }
.scities__count { color: var(--color-primary); font-weight: 700; }

.scities__name {
	margin: .35rem 0 0;
	font-family: var(--et-font-head);
	font-size: clamp(1.75rem, 3.2vw, 2.5rem);
	line-height: 1.1;
	color: var(--color-text-primary);
}
.scities__note {
	margin: .3rem 0 0;
	font-size: clamp(1rem, 1.3vw, 1.125rem);
	font-weight: 600;
	color: var(--color-primary);
}
.scities__blurb {
	margin: .85rem 0 0;
	font-size: 1rem;
	line-height: 1.65;
	color: var(--t-text-2);
}

.scities__sites {
	margin: 1.1rem 0 0;
	padding: 1rem 0 0;
	border-top: 1px solid var(--color-border);
	list-style: none;
	display: grid;
	gap: .5rem;
}
.scities__sites li {
	display: flex;
	gap: .6rem;
	font-size: .9375rem;
	line-height: 1.45;
	color: var(--color-text-primary);
}
.scities__sites li::before { content: "—"; color: var(--color-accent); }

.scities__arrows { display: flex; gap: .5rem; }
.scities__arrow {
	display: grid;
	place-items: center;
	width: 2.75rem; height: 2.75rem;
	border-radius: 50%;
	border: 1px solid var(--color-border);
	background: var(--color-surface);
	color: var(--color-primary);
	cursor: pointer;
	transition: border-color .3s var(--s-ease), background-color .3s var(--s-ease),
	            color .3s var(--s-ease);
}
.scities__arrow:hover {
	border-color: var(--color-primary);
	background: var(--color-primary);
	color: #fff;
}
.scities__arrow svg { width: 18px; height: 18px; }
.scities__arrow[data-slider-prev] svg { transform: rotate(180deg); }

@media (max-width: 900px) {
	.scities__stage { grid-template-columns: 1fr; }
	.scities__plates { aspect-ratio: 16 / 10; }
	/* The rail becomes a swipe rather than four stacked rows of pills. */
	.scities__rail {
		flex-wrap: nowrap;
		overflow-x: auto;
		scroll-snap-type: x proximity;
		padding-bottom: .5rem;
		-webkit-overflow-scrolling: touch;
	}
	.scities__tab { flex: 0 0 auto; scroll-snap-align: start; }
}

/* =============================================================================
   7. ITINERARY — the nine days
   ========================================================================== */

/* A progress rail under the horizontal track, filled by shema.js as it scrolls. */
.titin__progress {
	position: relative;
	height: 3px;
	margin-top: -.4rem;
	border-radius: 3px;
	background: var(--color-border);
	overflow: hidden;
}
.titin__progress i {
	position: absolute;
	inset: 0 auto 0 0;
	width: var(--sj-progress, 12%);
	border-radius: 3px;
	background: linear-gradient(90deg, var(--color-primary), var(--color-accent));
	transition: width .25s linear;
}

/* The day emblem, sitting on the photograph. */
.tday__emblem {
	position: absolute;
	right: .75rem; top: .75rem;
	z-index: 2;
	opacity: .95;
	filter: drop-shadow(0 8px 16px rgba(2, 46, 82, .45));
	transition: transform .5s var(--s-ease);
}
.tday:hover .tday__emblem { transform: translateY(-3px) scale(1.05); }

/* A nine-node rail showing where this day sits in the whole journey, so a card
   lifted out of context still reads as "six of nine". Built from spans rather
   than SVG: it has to stretch to the card width without distorting its nodes,
   which is exactly what SVG does badly and flexbox does for free. */
.tday__mini {
	display: flex;
	align-items: center;
	gap: 4px;
	margin: 0 0 .85rem;
}
.tday__mini span {
	flex: 1;
	height: 3px;
	border-radius: 3px;
	background: var(--color-border);
	transition: background-color .4s var(--s-ease), flex-grow .4s var(--s-ease);
}
.tday__mini .is-done { background: var(--color-primary); opacity: .45; }
.tday__mini .is-here {
	flex-grow: 2.2;
	height: 5px;
	background: linear-gradient(90deg, var(--color-primary), var(--color-accent));
}

/* =============================================================================
   8. HOW WE TRAVEL + INCLUSIONS
   ========================================================================== */

.tpillar { overflow: hidden; }
.tpillar .sh-tile { margin-bottom: 1.15rem; }
.tpillar:hover .sh-tile { transform: translateY(-4px) rotate(-3deg); box-shadow: var(--s-lift-2); }

/* A zellige corner that only appears on hover — ornament as reward. */
.tpillar__corner {
	position: absolute;
	right: -18px; bottom: -18px;
	width: 96px; height: 96px;
	pointer-events: none;
	opacity: 0;
	transform: rotate(-12deg) scale(.86);
	transition: opacity .5s var(--s-ease), transform .5s var(--s-ease);
}
.tpillar:hover .tpillar__corner { opacity: .13; transform: rotate(0) scale(1); }

/* Included / not included, with real iconography instead of tick boxes. */
.sincl__list { list-style: none; padding: 0; margin: 0; display: grid; gap: .3rem; }
.sincl__list li {
	display: flex;
	align-items: center;
	gap: .9rem;
	padding: .7rem .25rem;
	border-bottom: 1px solid var(--color-border);
	font-size: .9375rem;
	line-height: 1.5;
}
.sincl__list li:last-child { border-bottom: 0; }
.sincl__list .sh-tile { width: 46px; height: 46px; border-radius: 14px; }

.tincl--in  .sincl__list li { color: var(--color-text-primary); }
.tincl--out .sincl__list li { color: var(--color-text-secondary); }

/* What is excluded is drawn in the same hand but drained of colour, so the
   two columns read as one system with one of them switched off. */
.tincl--out .sh-tile {
	background: linear-gradient(150deg, #FFFFFF 0%, #EEF1F4 100%);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), var(--s-lift-1);
}
.tincl--out .sh-i { filter: grayscale(1); opacity: .5; }

.sincl__head {
	display: flex;
	align-items: center;
	gap: .7rem;
	margin-bottom: 1rem;
}
.sincl__head h3 { margin: 0; }
.sincl__badge {
	display: grid;
	place-items: center;
	width: 26px; height: 26px;
	border-radius: 50%;
	background: var(--color-primary);
	color: #fff;
}
.tincl--out .sincl__badge { background: var(--color-text-secondary); }

/* =============================================================================
   9. BOOKING — the reassurance layer
   ========================================================================== */

.tbook { position: relative; overflow: hidden; }

/* Zellige watermark behind the price, so the most commercial block on the page
   still belongs to the same world as the rest. */
.tbook::before {
	content: "";
	position: absolute;
	right: -30px; top: -30px;
	width: 150px; height: 150px;
	pointer-events: none;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='88' viewBox='0 0 88 88'%3E%3Cg fill='none' stroke='%23035FA5' stroke-width='1.4'%3E%3Crect x='24' y='24' width='40' height='40'/%3E%3Crect x='24' y='24' width='40' height='40' transform='rotate(45 44 44)'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
	opacity: .06;
}

.tbook__price { position: relative; }
.tbook__deposit {
	display: flex;
	align-items: center;
	gap: .7rem;
	margin: -.4rem 0 1.25rem;
	padding: .7rem .85rem;
	border-radius: 14px;
	background: linear-gradient(120deg, #FFF9E6, #FDF2CE);
	border: 1px solid rgba(242, 201, 76, .55);
	font-size: .8125rem;
	line-height: 1.45;
	color: var(--color-text-primary);
}
.tbook__deposit strong { font-weight: 700; white-space: nowrap; }

.tbook__row { position: relative; }
.tbook__row--icon select,
.tbook__row--icon input { padding-left: 2.65rem; }
.tbook__row .sh-i {
	position: absolute;
	left: .7rem;
	bottom: .58rem;
	pointer-events: none;
}

.tbook__trust {
	display: grid;
	gap: .55rem;
	margin-top: 1.15rem;
	padding-top: 1.15rem;
	border-top: 1px solid var(--color-border);
}
.tbook__trust li {
	display: flex;
	align-items: center;
	gap: .6rem;
	font-size: .78rem;
	line-height: 1.4;
	color: var(--color-text-secondary);
}
.tbook__trust { list-style: none; padding: 0; }

/* =============================================================================
   9b. THE CONCIERGE PANEL — the booking card as it appears inside the hero
   -----------------------------------------------------------------------------
   Everywhere else on this site a card is a white rectangle on a white page,
   which is correct. Over a photograph it was the one element that looked
   pasted on: pure #FFF against a graded photograph reads as a browser dialog.

   Warm ivory instead, on a vertical grade so the surface has a light source,
   with the shadow doing the lifting rather than a border. Opaque, not glass:
   this panel holds a price, two selects and the button that takes the money,
   and every one of them has to be readable before it is beautiful.
   ========================================================================== */
.thero .tbook {
	background: linear-gradient(177deg, #FDFBF6 0%, var(--h-ivory) 58%, #F2EDE1 100%);
	border: 1px solid rgba(6, 42, 66, .10);
	border-radius: 26px;
	padding: clamp(1.4rem, 1.9vw, 1.85rem);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, .9),
		0 2px 8px -3px rgba(4, 22, 38, .20),
		0 36px 72px -36px rgba(4, 22, 38, .75);
	color: #4A5C6B;
	transition: transform .6s var(--s-ease), box-shadow .6s var(--s-ease);
}
/* The elevation is three pixels. Anything more and a form starts to hover. */
.thero .tbook:hover {
	transform: translateY(-3px);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, .9),
		0 2px 8px -3px rgba(4, 22, 38, .20),
		0 46px 84px -38px rgba(4, 22, 38, .8);
}

/* Brass edge. Clipped by the card's own overflow, so it follows the radius. */
.thero .tbook::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 3px;
	background: linear-gradient(90deg,
		var(--h-gold) 0%, rgba(242, 201, 76, .55) 34%, rgba(242, 201, 76, .08) 68%, transparent 100%);
	pointer-events: none;
}

.tbook__eyebrow {
	display: flex;
	align-items: center;
	gap: .6rem;
	margin-bottom: .55rem;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--color-primary);
}
.tbook__eyebrow::before {
	content: "";
	width: 1.5rem; height: 2px;
	border-radius: 2px;
	background: var(--h-gold);
}

.thero .tbook__title { font-size: 1.5rem; color: var(--h-night); letter-spacing: -.02em; }
.thero .tbook__note  { margin-bottom: 1.35rem; color: #5B6C79; }

/* The price is the largest thing in the panel and the only thing set in the
   display face — stacked, not laid beside its qualifier, so the number lands
   before the small print. Tabular figures so the amount cannot shuffle. */
.thero .tbook__price {
	display: block;
	padding-bottom: 1.1rem;
	margin-bottom: 1.1rem;
	border-bottom: 1px solid rgba(6, 42, 66, .10);
}
.thero .tbook__amount {
	display: block;
	font-size: clamp(2.5rem, 3.4vw, 3.125rem);
	color: var(--h-night);
	letter-spacing: -.035em;
	font-variant-numeric: tabular-nums;
	font-variation-settings: "opsz" 120;
}
.thero .tbook__per {
	display: block;
	margin-top: .3rem;
	font-size: .78125rem;
	letter-spacing: .04em;
	color: #63737F;
}

/* The scheduled departure. Built like the deposit panel — icon, label, value —
   but in the card's own paper rather than sand: this is a fact the traveller
   needs before the price, not an incentive competing with it. */
.tbook__depart {
	display: flex;
	align-items: center;
	gap: .8rem;
	margin: 0 0 1.35rem;
	padding: .8rem .95rem;
	border-radius: 16px;
	background: rgba(6, 42, 66, .035);
	border: 1px solid rgba(6, 42, 66, .09);
}
.tbook__depart > .sh-i { flex: none; }
.tbook__depart em {
	display: block;
	font-style: normal;
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: #7B8994;
}
.tbook__depart strong {
	display: block;
	margin-top: .1rem;
	font-family: var(--et-font-head);
	font-size: 1.0625rem;
	font-weight: 600;
	letter-spacing: -.01em;
	color: var(--h-night);
	font-variant-numeric: tabular-nums;
}

/* The deposit is reassurance, not a promotion: sand rather than yellow, and
   the amount given its own line so the eye reads "what it costs to hold a
   place" before it reads the sentence explaining it. */
.thero .tbook__deposit {
	align-items: flex-start;
	gap: .8rem;
	margin: 0 0 1.35rem;
	padding: .85rem .95rem;
	border-radius: 16px;
	background: linear-gradient(120deg, #FBF6E7, #F7EFDB);
	border: 1px solid rgba(232, 216, 181, .95);
	color: #4A5C6B;
}
.thero .tbook__deposit strong {
	display: block;
	font-family: var(--et-font-head);
	font-size: 1.0625rem;
	font-weight: 600;
	letter-spacing: -.01em;
	color: var(--h-night);
}
.tbook__deposit em {
	display: block;
	margin-top: .1rem;
	font-style: normal;
	font-size: .78125rem;
	line-height: 1.45;
}

/* One control left in the panel — the room — so the two-column split that used
   to pair Departure with the traveller count is gone. A single select in a
   1.42fr/1fr grid would have stopped at 58% of the card. */
.thero .tbook__form {
	display: grid;
	grid-template-columns: 1fr;
	column-gap: .7rem;
}
.thero .tbook__form > .tbtn,
.thero .tbook__trust,
.thero .tbook__fine { grid-column: 1 / -1; }
/* A hidden input is still a grid item in some engines; never let it take a
   cell and push the button out of line. */
.thero .tbook__form input[type="hidden"] { display: none; }

.thero .tbook__row label { color: #5B6C79; letter-spacing: .14em; }
.thero .tbook select {
	background: #fff;
	border-color: rgba(6, 42, 66, .14);
	color: var(--h-night);
	font-weight: 500;
	font-size: .875rem;
	padding-block: .75rem;
	text-overflow: ellipsis;
}
.thero .tbook__row--icon select { padding-left: 2.45rem; }
.thero .tbook select:focus {
	border-color: var(--color-primary);
	box-shadow: 0 0 0 3px rgba(242, 201, 76, .35);
}

/* ---- The rate unit -------------------------------------------------------
   "/person" and "/couple" are the unit the amount is quoted in, not part of
   the amount. Left to inherit they came out in Fraunces at 1.5rem — the same
   weight on the page as $4,350 itself, which is the one number in this panel
   that has to be read first. Set back in the interface face at fine size, they
   read as the annotation they are.
   -------------------------------------------------------------------------- */
.tbook__rate-unit {
	display: inline;
	margin-left: .12rem;
	font-family: var(--et-font-body);
	font-size: .8125rem;
	font-weight: 500;
	letter-spacing: 0;
	color: var(--t-text-2);
}

/* ---- What the package covers ---------------------------------------------
   Ten lines of small print inside a card that already holds a price, a
   departure and a rate table. The brief is explicit that the panel must not
   double in height, so this block is set as tightly as it can be read: the two
   headings demoted from card titles to eyebrows, the items at fine size on
   short leading, and the icons at 14px hung off the first line rather than
   centred on the item.
   -------------------------------------------------------------------------- */
.tbook__incl {
	margin: 0 0 1.25rem;
	padding-top: 1rem;
	/* The same hairline that separates the rate table from what precedes it —
	   without it the block runs straight on from the last rate. */
	border-top: 1px solid var(--t-border);
}

/* <h3> by rights, but a card heading at 1.5rem would cost more height than the
   list it introduces. Treated as a surtitle instead. */
.tbook__incl-title {
	margin: 0 0 .5rem;
	font-family: var(--et-font-body);
	font-size: .8125rem;
	font-weight: 700;
	line-height: 1.35;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--t-text);
}
/* Air between the two lists, carried by the second heading so the first list
   keeps its own bottom edge tight. */
.tbook__incl-list + .tbook__incl-title { margin-top: 1rem; }

.tbook__incl-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: .35rem;
}
.tbook__incl-list li {
	display: flex;
	align-items: flex-start;
	gap: .5rem;
	font-size: .8438rem;
	line-height: 1.4;
	color: var(--t-text-2);
}
.tbook__incl-list svg {
	flex: none;
	width: 14px;
	height: 14px;
	/* Optical, not metric: seats the glyph on the first line of the item. */
	margin-top: .18rem;
}
/* The check is an affirmation and takes the brand blue; the minus is an
   exclusion and must not read as an error, so it stays in the text-secondary
   grey the item itself is set in. */
.tbook__incl-list--yes svg { color: var(--t-primary); }
.tbook__incl-list--no  svg { color: var(--t-text-2); opacity: .7; }

/* Measured, not assumed. --t-text-2 is #6B7280, which is 4.83:1 on the white
   page these tokens were set for but only 4.44:1 on the panel's ivory — under
   AA for text this size, and there are now eleven lines of it. #5B6C79 is the
   ink the panel already uses for its own supporting copy and comes to 4.99:1
   on the same ground, so the block joins the card rather than fighting it. */
.thero .tbook__rate-unit,
.thero .tbook__incl-list li { color: #5B6C79; }
.thero .tbook__incl-list--no svg { color: #5B6C79; }

.thero .tbook .tbtn--gold {
	margin-top: 1rem;
	padding-block: 1.1rem;
	font-size: 1rem;
	letter-spacing: .01em;
	box-shadow: 0 10px 26px -10px rgba(242, 201, 76, .8);
}

.thero .tbook__trust {
	gap: .5rem;
	margin-top: 1.05rem;
	padding-top: 1.05rem;
	border-top: 1px solid rgba(6, 42, 66, .10);
}
.thero .tbook__trust li { font-size: .75rem; color: #63737F; }
.thero .tbook__fine { margin-top: .85rem; font-size: .6875rem; color: #7B8994; }

/* =============================================================================
   10. GALLERY — editorial, with a full-screen viewer
   ========================================================================== */

/* Masonry via CSS columns: photographs keep their own proportions, which is
   the whole argument for a gallery. */
.sgal__masonry {
	columns: 3 17rem;
	column-gap: clamp(.8rem, 1.6vw, 1.15rem);
	margin-top: clamp(2rem, 4vw, 3rem);
	padding: 0;
	list-style: none;
}
@media (max-width: 700px) { .sgal__masonry { columns: 2 9rem; } }

.sgal__item {
	break-inside: avoid;
	margin-bottom: clamp(.8rem, 1.6vw, 1.15rem);
}

.sgal__fig {
	position: relative;
	margin: 0;
	border-radius: 18px;
	overflow: hidden;
	background: var(--color-primary-light);
	box-shadow: var(--s-lift-1);
	cursor: zoom-in;
	border: 0;
	padding: 0;
	display: block;
	width: 100%;
	transition: transform .5s var(--s-ease), box-shadow .5s var(--s-ease);
}
.sgal__fig:hover { transform: translateY(-4px); box-shadow: var(--s-lift-2); }
.sgal__fig img { width: 100%; height: auto; display: block; transition: transform 1.2s var(--s-ease); }
.sgal__fig:hover img { transform: scale(1.05); }

.sgal__cap {
	position: absolute;
	inset: auto 0 0;
	padding: 3rem .9rem .8rem;
	text-align: left;
	background: linear-gradient(180deg, rgba(2, 74, 130, 0), rgba(2, 46, 82, .93));
	opacity: 0;
	transform: translateY(10px);
	transition: opacity .4s ease, transform .4s var(--s-ease);
}
.sgal__fig:hover .sgal__cap,
.sgal__fig:focus-visible .sgal__cap { opacity: 1; transform: none; }
.sgal__place {
	display: block;
	font-size: .625rem;
	font-weight: 700;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--color-accent);
}
.sgal__text { display: block; font-size: .875rem; line-height: 1.35; color: #fff; margin-top: .1rem; }
.sgal__no {
	position: absolute;
	top: .7rem; left: .7rem;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: .625rem;
	letter-spacing: .1em;
	color: #fff;
	background: rgba(2, 46, 82, .5);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	padding: .18rem .45rem;
	border-radius: 6px;
	opacity: 0;
	transition: opacity .4s ease;
}
.sgal__fig:hover .sgal__no { opacity: 1; }

@media (hover: none) {
	.sgal__cap { opacity: 1; transform: none; }
}

/* ---- Full-screen viewer -------------------------------------------------- */
.sgal__viewer {
	position: fixed;
	inset: 0;
	z-index: 999;
	display: grid;
	/* minmax(0, 1fr), not 1fr. A bare 1fr track has an auto minimum, so a tall
	   photograph pushes the track past the viewport and shoves the caption bar
	   off screen. */
	grid-template-rows: minmax(0, 1fr) auto;
	background: rgba(4, 22, 38, .96);
	backdrop-filter: blur(22px);
	-webkit-backdrop-filter: blur(22px);
	opacity: 0;
	visibility: hidden;
	transition: opacity .38s ease, visibility .38s;
}
.sgal__viewer.is-open { opacity: 1; visibility: visible; }

/* Flex, not grid, and the photograph is sized by the box rather than by a
   percentage of it. A percentage max-height on a grid item resolves against a
   track whose height the grid algorithm treats as indefinite, so Chrome
   dropped the constraint entirely and rendered a 1024px photograph inside a
   906px stage. Sizing the element to the stage and letting object-fit letterbox
   the picture inside it has no percentage to resolve, so it cannot fail. */
.sgal__stage {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 0;
	overflow: hidden;
	padding: clamp(1rem, 4vw, 3rem);
}
.sgal__stage img {
	width: 100%;
	height: 100%;
	min-height: 0;
	object-fit: contain;
	opacity: 0;
	transform: scale(.97);
	transition: opacity .42s var(--s-ease), transform .42s var(--s-ease);
}
.sgal__stage img.is-shown { opacity: 1; transform: none; }

.sgal__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 1rem 1.5rem;
	padding: 1rem clamp(1rem, 4vw, 3rem) clamp(1.25rem, 3vw, 2rem);
	text-align: center;
	color: rgba(255, 255, 255, .82);
}
.sgal__bar h3 { color: #fff; font-size: 1.0625rem; margin: 0; }
.sgal__bar p { margin: .1rem 0 0; font-size: .75rem; letter-spacing: .16em; text-transform: uppercase; color: var(--color-accent); }
.sgal__counter { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8125rem; letter-spacing: .1em; }

.sgal__ctrl {
	display: grid;
	place-items: center;
	width: 46px; height: 46px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, .28);
	background: rgba(255, 255, 255, .08);
	color: #fff;
	cursor: pointer;
	transition: background-color .3s ease, transform .3s var(--s-ease);
}
.sgal__ctrl:hover { background: rgba(255, 255, 255, .2); transform: scale(1.06); }
.sgal__close { position: absolute; top: 1rem; right: 1rem; z-index: 2; }

/* =============================================================================
   11. SECTION FURNITURE
   ========================================================================== */

.tour__section-head { max-width: 46rem; }

/* An eyebrow that carries its own emblem. */
.sh-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: .7rem;
	margin-bottom: 1.1rem;
}
.sh-eyebrow span {
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--color-primary);
}
.tcta .sh-eyebrow span,
.thigh .sh-eyebrow span { color: var(--color-accent); }

/* A drawn rule with a zellige node at its centre — the section divider. */
.sh-rule {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin: clamp(2rem, 4vw, 3rem) 0;
	color: var(--color-border);
}
.sh-rule::before,
.sh-rule::after {
	content: "";
	flex: 1;
	height: 1px;
	background: linear-gradient(90deg, transparent, currentColor, transparent);
}

/* =============================================================================
   12. MOTION PRIMITIVES
   Used by shema.js. Every one has a resting state that is fully visible, so a
   failed observer can never leave content hidden.
   ========================================================================== */

.sh-rise { opacity: 0; transform: translateY(24px); }
.sh-rise.is-in { opacity: 1; transform: none; transition: opacity .8s var(--s-ease-o), transform .8s var(--s-ease-o); }
html:not(.js-shema) .sh-rise { opacity: 1; transform: none; }

/* Staggered entrance. Each child is observed on its own, so the delay has to
   ride on the child rather than on the group. --i is set inline per item. */
.sh-rise.is-in { transition-delay: calc(var(--i, 0) * 60ms); }

@media (prefers-reduced-motion: reduce) {
	.sf-obj,
	.sf-obj > *,
	.thero__mote,
	.thero__coords strong::before,
	.thero__scroll i::after,
	.sj-stop.is-active .sj-stop__pulse,
	.sjmap.is-settled .sj-route {
		animation: none !important;
	}
	.sf-obj { opacity: var(--sf-o, .4); transform: none !important; transition: none !important; }
	.sh-rise { opacity: 1 !important; transform: none !important; }
	.sjmap.is-drawn .sj-route,
	.sjmap.is-drawn .sj-route-glow { transition: none; stroke-dashoffset: 0; }
	.sjmap .sj-route { stroke-dasharray: 11 9; }
	.sgal__viewer, .sgal__stage img, .sjmap__media img { transition: none; }
}
