/**
 * COMPONENTS — لمبة.
 *
 * Everything this site draws that base.css does not: the frame's header and
 * footer, the gate and its four ignition mechanics, and Athar's shipped
 * sections dressed in this identity.
 *
 * Nothing here names a colour or a size directly; identity.css owns those.
 * Nothing here is defined in base.css as well: the two files are disjoint on
 * purpose, and tools/css-check.cjs in the plugin fails the build if they stop
 * being.
 */

/* ================================================================== header

   A capsule, not a bar. Saad picked the shape at fixaplan.com: a small panel
   floating at the top centre with the brand and a burger in it, and a second
   panel below it, holding the links, that opens out of a single point.

   What was taken is that shape and that gesture. The rest is this identity's:
   solid rather than glass, because there is no glass anywhere here; dark
   rather than white; and the point the menu opens out of is the filament's
   own yellow, so opening the menu is the gesture the whole site is about.
   Their two burger bars close onto each other into a single line rather than
   crossing into an X — that part is theirs and it is better than an X.

   It sticks rather than floats free, so the room above the page's first
   section is real space and nothing can collide with it. The second capsule
   is taken out of flow instead, which is why the header only ever reserves
   the height of the bar.

   Sits above the room (z 60) and below the gate (z 90). There is no light
   switch in here. There was one, and it is gone by request: the lamp is the
   work, not a control in the corner.
   ======================================================================= */

.site-head {
	/* The two capsules and the hole between them are one component, so it
	   keeps its own three numbers rather than borrowing tokens that mean
	   something else elsewhere. */
	--head-lift: clamp(0.75rem, 1.6vw, 1.4rem);
	--head-gap: 0.55rem;
	--head-dot: 4px;

	position: sticky;
	inset-block-start: 0;
	z-index: 70;

	/* Padding, not margin: a top margin here collapses through the body and
	   takes the header with it. This way the lift is inside the sticky box
	   and survives being stuck. */
	padding-block-start: var(--head-lift);

	/* Closed, the second capsule is still a point of light below the bar, and
	   it is out of flow. This is the room that point needs. A margin and not
	   padding this time: the panel is placed at 100% of the padding box, so
	   padding here would push it away from the bar it belongs to. */
	margin-block-end: calc(var(--head-gap) + 4 * var(--head-dot));

	display: flex;
	flex-direction: column;
	align-items: center;

	/* The strip of nothing between the two capsules is still part of this
	   box, and the page underneath has to stay clickable through it. Each
	   capsule takes the pointer back for itself. */
	pointer-events: none;

	/* It arrives, and no script is involved: `both` holds the from-state
	   through the delay, so the served page drops it in on its own. Under
	   reduced motion base.css collapses the duration and it is simply there. */
	animation: lamba-drop var(--l-dur-3) var(--l-ease) 220ms both;
}

/* Signed in, the admin bar is fixed across the top of the viewport and a
   sticky header knows nothing about it. Both numbers, and the breakpoint, are
   core's rather than this site's. */
.admin-bar .site-head {
	inset-block-start: 32px;
}

@media (max-width: 782px) {
	.admin-bar .site-head {
		inset-block-start: 46px;
	}
}

@keyframes lamba-drop {
	from {
		translate: 0 -100%;
		opacity: 0;
	}
}

.site-head__bar {
	pointer-events: auto;
	display: flex;
	align-items: center;
	/* Theirs is 52px between the wordmark and the burger. The capsule is its
	   content either way, so this is the only number setting how wide it
	   reads. */
	gap: clamp(1.1rem, 3.5vw, 3.25rem);
	/* Air around the artwork, not just around the text.
	 *
	 * At 0.45rem the mark stood 41px tall in a 57px capsule — eight pixels of
	 * clearance top and bottom, and the drawn lamp reads as pressed against
	 * both. Saad: «الشعار محشور شوي». The mark is what sets this capsule's
	 * height, so the only honest lever is the room left around it. */
	padding-block: 0.7rem;
	padding-inline: 1.2rem 0.8rem;
	border: 1px solid var(--l-rule);
	border-radius: var(--l-radius);
	background: var(--l-raise);
	box-shadow: 0 16px 40px -24px var(--l-black);
}

.site-name {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 0.55rem;
	text-decoration: none;
}

.site-name__mark {
	flex: 0 0 auto;
	/* The artwork is half again as tall as it is wide, and it is what sets
	   the height of the whole capsule. */
	inline-size: clamp(1.3rem, 1.8vw, 1.6rem);
}

/* Their drawn word. Sized by height, because the two lockups are different
   shapes: the Arabic word is short and wide at 2.9:1, LAMPAAH is a caps line
   at 6:1, and a single width would set one of them wrong. */
.site-name__word {
	flex: 0 0 auto;
	inline-size: auto;
	block-size: clamp(0.95rem, 1.3vw, 1.15rem);
}

.site-name__word.lamba-word--en {
	block-size: clamp(0.62rem, 0.85vw, 0.75rem);
}

/* One uploaded lockup, in place of both pieces.
 *
 * Sized by height for the same reason the drawn word is: a lockup is whatever
 * width its own artwork happens to be — a tall stacked one and a long
 * horizontal one are both «the logo» — and fixing the width would set the two
 * to two different heights. The cap stops a very wide file from pushing the
 * burger off a phone. */
.site-name__full {
	flex: 0 1 auto;
	inline-size: auto;
	block-size: clamp(1.5rem, 2.2vw, 2rem);
	max-inline-size: min(48vw, 15rem);
	object-fit: contain;
	object-position: center;
}

.site-foot__full {
	inline-size: auto;
	block-size: clamp(1.7rem, 2.6vw, 2.4rem);
	max-inline-size: min(60vw, 18rem);
	object-fit: contain;
}

.site-head__tools {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 0.35rem;
}

/* ---------------------------------------------------------- the language

   Athar prints both languages and marks the current one. In a capsule this
   size two whole words is most of the width, so only the language you are
   not reading is shown: the chip becomes a switch, which is what a reader
   wants from it anyway, and the page already says which language it is in. */

.site-head .athar-langs {
	display: flex;
	align-items: center;
}

.site-head .athar-langs__item {
	padding-block: 0.5em;
	padding-inline: 0.7em;
	border-radius: var(--l-radius-pill);
	color: var(--l-faint);
	font-size: var(--l-t-meta);
	letter-spacing: var(--l-track-meta);
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	transition: color var(--l-dur-1) var(--l-ease);
}

.site-head .athar-langs__item:hover,
.site-head .athar-langs__item:focus-visible {
	color: var(--l-text);
}

.site-head .athar-langs__item.is-current {
	display: none;
}

/* ------------------------------------------------------------- the burger */

.site-burger {
	position: relative;
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	inline-size: 2.35rem;
	block-size: 2.35rem;
	padding: 0;
	border: 0;
	border-radius: var(--l-radius-pill);
	background: none;
	color: var(--l-text);
	cursor: pointer;
}

/* With no script the menu never closes, so the control that would do nothing
   is never shown. header.php prints the one statement that adds .is-ready. */
.site-head:not(.is-ready) .site-burger {
	display: none;
}

.site-burger__bars {
	position: relative;
	display: block;
	inline-size: 17px;
	block-size: 13px;
}

.site-burger__bars > span {
	position: absolute;
	inset-inline: 0;
	block-size: 2px;
	border-radius: 2px;
	background: currentColor;
	transition:
		translate var(--l-dur-1) var(--l-ease),
		background-color var(--l-dur-1) var(--l-ease);
}

.site-burger__bars > span:first-child {
	inset-block-start: 0;
}

.site-burger__bars > span:last-child {
	inset-block-end: 0;
}

/* Open, the two bars land on each other and become one lit line. */
.site-head.is-open .site-burger__bars > span {
	background: var(--l-yellow);
}

.site-head.is-open .site-burger__bars > span:first-child {
	translate: 0 5.5px;
}

.site-head.is-open .site-burger__bars > span:last-child {
	translate: 0 -5.5px;
}

.site-burger__label {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* --------------------------------------------------------------- the menu

   Out of flow, so the header reserves the bar's height and not this one's,
   and centred with auto margins rather than a translate — a translate is
   physical, and half the time this site is read right to left.

   What is declared here is the open state, because open is what the server
   sends: a reader with no JavaScript gets every link, in a panel, reachable.
   Only once the one line in header.php has run does .is-ready close it.
   ======================================================================= */

.site-menu {
	position: absolute;
	inset-block-start: calc(100% + var(--head-gap));
	inset-inline: 0;
	margin-inline: auto;
	inline-size: max-content;
	min-inline-size: 12rem;
	max-inline-size: min(92vw, var(--l-col));
	pointer-events: auto;
	padding: 4px;
	border: 1px solid var(--l-rule);
	border-radius: var(--l-radius);
	background: var(--l-raise);
	box-shadow: 0 16px 40px -24px var(--l-black);

	/* The bloom. Closed, all that is left of the panel is a point of the
	   filament's yellow under the bar; opening grows that point out into the
	   panel and the yellow cools to the raised grey. One circle, two radii,
	   and nothing distorts on the way — scaling the panel would stretch the
	   words inside it, which is what makes that trick read as an effect. */
	clip-path: circle(900px at 50% var(--head-dot));
	transition:
		clip-path var(--l-dur-2) var(--l-ease),
		background-color var(--l-dur-2) var(--l-ease),
		border-color var(--l-dur-2) var(--l-ease);
}

.site-head.is-ready .site-menu {
	clip-path: circle(var(--head-dot) at 50% var(--head-dot));
	background: var(--l-yellow);
	border-color: transparent;
	pointer-events: none;
}

.site-head.is-ready.is-open .site-menu {
	clip-path: circle(900px at 50% var(--head-dot));
	background: var(--l-raise);
	border-color: var(--l-rule);
	pointer-events: auto;
}

.site-menu__list {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--l-t-small);
}

/* Hidden, not merely transparent: a link that cannot be seen must not be able
   to take the keyboard either. Visibility waits out the panel closing; on the
   way open it returns at once and the words fade in behind the panel. */
.site-head.is-ready .site-menu__list {
	opacity: 0;
	visibility: hidden;
	transition:
		opacity var(--l-dur-1) var(--l-ease),
		visibility 0s linear var(--l-dur-2);
}

.site-head.is-ready.is-open .site-menu__list {
	opacity: 1;
	visibility: visible;
	transition:
		opacity var(--l-dur-1) var(--l-ease) 140ms,
		visibility 0s;
}

.site-menu__list a {
	display: block;
	padding-block: 0.6rem;
	padding-inline: 1.1rem;
	border-radius: var(--l-radius-pill);
	color: var(--l-quiet);
	text-decoration: none;
	white-space: nowrap;
	transition:
		color var(--l-dur-1) var(--l-ease),
		background-color var(--l-dur-1) var(--l-ease);
}

.site-menu__list a:hover,
.site-menu__list a:focus-visible {
	color: var(--l-text);
	background: var(--l-raise-2);
}

.site-menu__list .current-menu-item > a,
.site-menu__list .current_page_item > a {
	color: var(--l-yellow);
}

/* A row of chips wants the width of every label at once, which a phone does
   not have. Below this the panel is a column and loses the pill. */
@media (min-width: 48rem) {
	.site-menu {
		border-radius: var(--l-radius-pill);
	}

	.site-menu__list {
		flex-direction: row;
		align-items: center;
	}
}

/* ============================================================== foot menu */

.foot-nav__list {
	display: flex;
	flex-wrap: wrap;
	gap: clamp(0.9rem, 2.2vw, 1.9rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* ==================================================================== mark

   Their symbol: a head in profile with a filament burning inside it. The head
   takes the page's text colour, so on this ground the artwork's black reads
   white; the filament keeps the brand yellow exactly.

   The glow is three copies of the filament path — wide amber blur, tight
   yellow blur, sharp shape — so every part of the light is the shape of the
   thing emitting it. That is what stops it reading as layers.
   ======================================================================= */

.lamba-mark {
	display: block;
	block-size: auto;
	overflow: visible;
}

.lamba-mark__body path {
	fill: var(--l-text);
}

.lamba-mark__fil {
	fill: var(--l-yellow);
}

.lamba-mark__wide path {
	fill: #ffb020;
}

.lamba-mark__tight path {
	fill: var(--l-yellow);
}

.lamba-mark__wide {
	opacity: 0.5;
	filter: url("#lamba-glow-wide");
}

.lamba-mark__tight {
	opacity: 0.8;
	filter: url("#lamba-glow-tight");
}

/* The hot core. A 1.5px shadow on a 196-character path costs nothing and is
   the difference between a yellow shape and a lit filament. */
.lamba-mark--lit .lamba-mark__fil {
	filter: drop-shadow(0 0 1.5px #ffe98a);
}

/* Only the outermost halo moves, and only its opacity, so it never leaves the
   compositor. A filament is never perfectly steady. */
.lamba-mark--lit .lamba-mark__wide {
	animation: lamba-breathe 7s ease-in-out infinite;
}

@keyframes lamba-breathe {
	0%, 100% { opacity: 0.5; }
	50% { opacity: 0.36; }
}

/* The word, split out of their stacked lockup. One colour and it is
   currentColor, so it inverts with whatever surface it lands on and there is
   nothing to keep in step by hand. */
.lamba-word {
	display: block;
	fill: currentColor;
	overflow: visible;
}

/* An uploaded logo, in the same box.
 *
 * It carries the classes the drawn one carries, so every place that sized the
 * artwork sizes this — and `object-fit: contain` is what keeps a file whose
 * proportions are not the artwork's from being stretched into them.
 *
 * The light has to come from around it rather than out of it. The drawn mark
 * blurs its own filament path twice; a PNG is one rectangle to the browser and
 * there is nothing inside it to light. drop-shadow follows the artwork's alpha
 * rather than its box, so on a transparent file the glow is still the shape of
 * the thing emitting it — the site's one rule about light, kept by other
 * means. Off at --lit: 0, exactly like everything else warm here. */
.lamba-mark--own,
.lamba-word--own {
	display: block;
	object-fit: contain;
	max-inline-size: 100%;
}

.lamba-mark--own {
	filter:
		drop-shadow(0 0 calc(var(--lit) * 7px) rgb(246 208 13 / calc(var(--lit) * 0.5)))
		drop-shadow(0 0 calc(var(--lit) * 20px) rgb(255 176 32 / calc(var(--lit) * 0.28)));
	transition: filter var(--l-dur-2) var(--l-ease);
}

/* =================================================================== ground

   The fixed layer inc/scenes.php prints, and the scenes stacked inside it.
   lamp.js decides which one is on; everything else about it is here.

   z-index -1, and the body's own background taken away for it. html keeps the
   room colour so the canvas is still ink, this layer paints over the canvas,
   and every line of the page paints over this. Put the layer at 0 instead and
   the body's background — which paints after negative layers, not before —
   would sit on top of it and nothing would ever be seen.

   The room (z 60) and the grain (z 96) still fall on top of all of it, which
   is right: the dark falls on the ground too, and the grain is the air in the
   room rather than a texture on the picture.
   ======================================================================= */

body {
	/* Taken away, not changed: see above. html still carries the room. */
	background: transparent;
}

.lamp-ground {
	position: fixed;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	overflow: clip;
}

.lamp-ground__scene {
	position: absolute;
	inset: 0;
	background: var(--ground-color, var(--l-ground));
	opacity: 0;
}

/* No transition on this line, and that is the whole point. A crossfade here
   would be a dissolve between two rooms; a light switch does not dissolve. */
.lamp-ground__scene.is-on {
	opacity: 1;
}

.lamp-ground__media {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	/* Their work is video, and stills pulled from video swing wildly in
	   temperature. This keeps every ground in the same room as the site. */
	filter: var(--l-photo);
}

/* The veil that keeps a line readable over a picture. Its own layer rather
   than a shadow on the words: a text-shadow under Arabic at this size fills
   the joins between letters and turns the line to mud. */
.lamp-ground__scene--image::after,
.lamp-ground__scene--video::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--l-black);
	opacity: var(--ground-dim, 0.52);
}

/* Where a video keeps its address until lamp.js decides whether to fetch it. */
.lamp-ground__src {
	display: none;
}

/* ---------------------------------------------------------------- the tone

   A pale ground, and the page's ink turns over on it.

   The brand's yellow is one of the four primaries and it is a *light* colour:
   #f6d00d carries about 65% relative luminance, so the site's near-white type
   on it is not dim, it is gone. lamp.js reads the tone the active scene
   declares and puts .lamp-pale on the root.

   Scoped to the content and not to the page, deliberately. The header capsule
   carries its own dark surface with it and reads perfectly well over yellow;
   turn its ink over too and it would be black on near-black. Chrome keeps its
   own tone, and only what sits directly on the ground follows the ground.
   ======================================================================= */

.lamp-pale .site-main,
.lamp-pale .site-foot {
	--l-text: var(--l-ink);
	--l-quiet: rgb(28 28 26 / 0.72);
	--l-faint: rgb(28 28 26 / 0.48);
	--l-rule: rgb(28 28 26 / 0.2);
	--l-rule-soft: rgb(28 28 26 / 0.1);

	/* The accent has to go too: yellow on yellow says nothing. On a pale
	   ground the ink itself is the emphasis, which is exactly how the guide
	   book uses the pair the other way round. */
	--l-yellow: var(--l-ink);

	color: var(--l-text);
}

/* The strike. A lamp catches before it holds, so the room does too: one short
   flare of the filament's colour across the whole ground at the moment it
   changes, and never a second one — this is one flash per change, well under
   the three-per-second that makes a page dangerous to look at. */
.lamp-ground::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--l-yellow);
	opacity: 0;
	mix-blend-mode: screen;
}

.lamp-ground.is-struck::after {
	animation: lamba-flare 260ms var(--l-ease-io);
}

@keyframes lamba-flare {
	0%   { opacity: 0; }
	18%  { opacity: 0.16; }
	42%  { opacity: 0.03; }
	100% { opacity: 0; }
}

/* ===================================================================== hero

   Athar's cover, which is the opening of every page on this site. Not a
   section of its own: adding one would have left an editor choosing between
   two things that mean the same, and stacked two openings on any page that
   already had a cover.

   Saad, looking at the first draft: smaller, one line, centred. So the line
   is one line by construction — nowrap, and a size that scales with the
   viewport rather than a size that wraps.

   It draws no background. Its picture, or its film, is a scene in the fixed
   layer above: that is what lets the picture hold still while these words
   scroll off it, and lets the next scene replace it in a single frame.
   ======================================================================= */

.athar-scope .lamba-hero {
	position: relative;
	display: grid;
	place-items: center;
	/* The header is in the flow above this, so a full 100svh would push the
	   fold down by its height. This lands the opening on exactly one screen,
	   with a sliver of what follows showing under it — which is the only
	   invitation to scroll that has ever really worked. */
	min-block-size: calc(100svh - 7rem);
	padding-block: var(--l-rhythm-tight);
	padding-inline: var(--l-gutter);
	text-align: center;
}

/* A flat colour opening is the style tab's own background, promoted to the
   fixed layer. It is already on screen there; painting it here as well would
   scroll a second copy of it up the page. */
.athar-scope .lamba-hero.athar-s-bg--color {
	background: none;
}

.athar-scope .lamba-hero .athar-cover__body {
	display: grid;
	justify-items: center;
	gap: clamp(0.9rem, 2vw, 1.4rem);
	max-inline-size: 100%;
}

.athar-scope .lamba-hero .athar-cover__heading {
	margin: 0;
	max-inline-size: none;
	font-family: var(--l-display);
	/* Half what the opening used to be. It is the vw term that keeps the
	   promise of one line: at 5.6vw a short line holds on a phone, and the two
	   ends of the clamp stop it becoming either a whisper or a billboard. */
	font-size: clamp(1.5rem, 5.6vw, 4.25rem);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-hero);
	line-height: 1.12;
	white-space: nowrap;
	text-wrap: nowrap;
}

.athar-scope .lamba-hero .athar-cover__sub {
	margin: 0;
	max-inline-size: 46ch;
	color: var(--l-quiet);
	font-size: var(--l-t-h3);
	line-height: var(--l-lh-head);
	text-wrap: pretty;
}

.athar-scope .lamba-hero .athar-cover__button {
	display: inline-flex;
	align-items: center;
	margin-block-start: 0.4rem;
	padding-block: 0.75em;
	padding-inline: 1.5em;
	border-radius: var(--l-radius-pill);
	background: var(--l-yellow);
	color: var(--l-black);
	font-weight: var(--l-w-mid);
	text-decoration: none;
	transition: filter var(--l-dur-1) var(--l-ease);
}

.athar-scope .lamba-hero .athar-cover__button:hover {
	filter: brightness(1.12);
}

/* On a pale ground the button cannot be the ground's own colour. */
.lamp-pale .athar-scope .lamba-hero .athar-cover__button {
	background: var(--l-ink);
	color: var(--l-white);
}

/* The cue: a filament of a line at the foot of the opening, lighting from the
   top down, over and over. It is inside the section, so it leaves when the
   section does and nothing has to remember to take it away. */
.lamba-hero__cue {
	position: absolute;
	inset-block-end: clamp(1.25rem, 4vh, 2.75rem);
	inset-inline: 0;
	margin-inline: auto;
	inline-size: 1px;
	block-size: clamp(2rem, 5vh, 3.5rem);
	background: linear-gradient(to bottom, transparent, var(--l-yellow));
	opacity: 0.5;
	transform-origin: top;
	animation: lamba-cue 2.4s var(--l-ease-io) infinite;
}

@keyframes lamba-cue {
	0%   { scale: 1 0; opacity: 0; }
	35%  { scale: 1 1; opacity: 0.55; }
	70%  { scale: 1 1; opacity: 0.55; }
	100% { scale: 1 1; opacity: 0; }
}

/* =============================================================== entrances

   "تحريك جانبي فجائي" — a sudden sideways arrival. Sections travel in from
   one side and stop dead, alternating sides down the page so it reads as a
   rhythm rather than a conveyor belt.

   No fade with it, deliberately. A fade is the gentle way to arrive and there
   is nothing gentle in this identity; what sells it as a light coming on
   rather than a slide is that it does not drift to a halt, it stops.

   Reversible, because that is what was asked for: the class comes off on the
   way out, so scrolling back up plays it again.
   ======================================================================= */

.site-main {
	/* The travel happens outside the page's width. clip and not hidden: hidden
	   would make this a scroll container and take the sticky header with it. */
	overflow-x: clip;
}

.athar-scope .athar-section:not(.lamba-hero):not(.lamba-rail):not(.lamba-cta--scatter) {
	--in-x: 7vw;
	transition: translate 420ms var(--l-ease);
}

[dir="ltr"] .athar-scope .athar-section {
	--in-x: -7vw;
}

/* Every other one from the other side. */
.athar-scope .athar-section:nth-child(even) {
	--in-x: -7vw;
}

[dir="ltr"] .athar-scope .athar-section:nth-child(even) {
	--in-x: 7vw;
}

.lamp-js .athar-scope .athar-section:not(.lamba-hero):not(.lamba-rail):not(.lamba-cta--scatter):not(.is-in) {
	translate: var(--in-x) 0;
}

/* The scattering ask is excluded for the reason the rail is: it pins a child
   of itself, and a section that arrives by sliding sideways is a section whose
   pinned child arrives sideways with it. Both of them own their own entrance
   anyway — that is what they are. */

/* The opening never slides in — a first screen that assembles itself is a
   first screen nobody trusts — so it is excluded above by name rather than
   overridden here. Nothing is left to say about it. */

/* ================================================================== footer */

.site-foot {
	margin-block-start: var(--l-rhythm);
	/* The floor blurs and darkens the bottom of the window, and the foot is
	   the last thing under it. Its own words have to clear that band or the
	   end of every page is read through a smudge. */
	padding-block: var(--l-rhythm-tight) clamp(7rem, 17vh, 13rem);
	font-size: var(--l-t-small);
	color: var(--l-quiet);
}

.site-foot__row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--l-gutter);
	align-items: baseline;
	justify-content: space-between;
}

.site-foot a {
	text-decoration: none;
	border-block-end: 1px solid var(--l-rule);
}

.site-foot a:hover {
	color: var(--l-text);
	border-block-end-color: var(--l-yellow);
}

/* ==================================================================== gate

   Full screen, built by lamp.js and never present in the served HTML, so a
   reader with no JavaScript never meets it. Darker than the site it opens
   onto: the room is #1c1c1a, the gate is true black.
   ======================================================================= */

.gate {
	position: fixed;
	inset: 0;
	z-index: 90;
	display: grid;
	background: var(--l-black);
	/* Three of the four mechanics are drags, and a drag across a page selects
	   text on the way. preventDefault on pointerdown covers the pointer path;
	   this covers the rest, including a selection that started before the
	   gate was built. */
	user-select: none;
	-webkit-user-select: none;
	transition:
		opacity var(--l-dur-3) var(--l-ease),
		visibility var(--l-dur-3) step-end;
}

.gate.is-out {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

.gate__stage {
	grid-area: 1 / 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: clamp(0.9rem, 2.6vh, 1.9rem);
	padding: var(--l-gutter);
	text-align: center;
}

/* The gate's lamp is the brand mark itself, cloned from the header by lamp.js.

   The unlit state is the fiddly part. Dropping the opacity of the brand yellow
   turns it olive over black — the same sludge that made the first build look
   broken — so the unlit filament is not dim yellow, it is a neutral cold grey,
   and --lit interpolates it towards the brand colour. That is also what a real
   filament does: it is grey metal until current reaches it.

   The glow radii are lighter here than the header's on purpose. In the artwork
   the yellow is a filled field inside the head rather than a hairline, and a
   wide blur on an area that size reads as fog rather than as light.
   ======================================================================= */
.gate__orb {
	position: relative;
	inline-size: clamp(7rem, 20vmin, 12rem);
	display: grid;
	place-items: center;
}

.gate__mark {
	inline-size: 100%;
}

/* An uploaded picture, at the one size on this site where the brand is the
   only thing on the screen. Contained rather than stretched, because whatever
   was chosen here has its own proportions and the gate has no business
   deciding they were wrong. The glow comes from `.lamba-mark--own`, which
   follows the artwork's alpha — the site's one rule about light, kept for a
   file the browser sees as a rectangle. */
.gate__mark--own {
	inline-size: 100%;
	block-size: auto;
	max-block-size: clamp(7rem, 20vmin, 12rem);
	object-fit: contain;
}

.gate__mark .lamba-mark__fil {
	fill: color-mix(in oklab, var(--l-yellow) calc(var(--lit) * 100%), #55554e);
	filter: none;
}

.gate__mark .lamba-mark__wide {
	opacity: calc(var(--lit) * 0.32);
	animation: none;
}

.gate__mark .lamba-mark__tight {
	opacity: calc(var(--lit) * 0.55);
}

/* The head stays readable in the dark so the lamp has a place before it has a
   light, and comes fully up with it. */
.gate__mark .lamba-mark__body path {
	fill: var(--l-text);
	opacity: calc(0.3 + var(--lit) * 0.7);
}

.gate__slogan {
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--l-t-hero);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-hero);
	line-height: var(--l-lh-hero);
	opacity: calc(0.32 + var(--lit) * 0.68);
}

.gate__sub {
	margin: 0;
	font-size: var(--l-t-meta);
	letter-spacing: var(--l-track-meta);
	text-transform: uppercase;
	color: var(--l-faint);
}

.gate__hint {
	margin: 0;
	max-inline-size: 26ch;
	font-size: var(--l-t-small);
	color: var(--l-quiet);
	text-wrap: balance;
	/* Fades out as the light comes up: once you have understood it, it goes. */
	opacity: calc(1 - var(--lit));
}

.gate__skip {
	margin-block-start: 0.5rem;
	padding: 0.4em 0.9em;
	border: 0;
	border-radius: var(--l-radius-pill);
	background: none;
	color: var(--l-faint);
	font: inherit;
	font-size: var(--l-t-small);
	cursor: pointer;
	text-decoration: underline;
	text-underline-offset: 0.3em;
}

.gate__skip:hover {
	color: var(--l-text);
}

/* ---------------------------------------------------------------- cord

   A cord hanging from the top of the screen. The light rises with the pull,
   so the hand is holding the light rather than pressing a button that owns
   it. Identical under a finger and a mouse; the only mechanic that also
   reads as a physical object. */

/* Hangs from the inline start, which is the right in Arabic and the left in
   English. Both put it under the hand that is most likely to reach for it,
   and neither needs an override. */
.cord {
	--pull: 0;
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: clamp(1.5rem, 9vw, 7rem);
	display: flex;
	flex-direction: column;
	align-items: center;
}

.cord__rope {
	inline-size: 1px;
	block-size: calc(18vh + var(--pull) * 190px);
	background: linear-gradient(
		to bottom,
		rgb(237 237 233 / 0.06),
		rgb(237 237 233 / 0.5)
	);
	transition: block-size var(--l-dur-2) var(--l-ease);
}

.cord__grip {
	inline-size: 2.5rem;
	aspect-ratio: 1;
	border: 1px solid var(--l-rule);
	border-radius: 50%;
	background: var(--l-raise);
	cursor: grab;
	/* Or the browser takes the drag for a scroll and the cord never moves. */
	touch-action: none;
	transition: background var(--l-dur-1) var(--l-ease);
}

.cord__grip::after {
	content: "";
	display: block;
	inline-size: 0.5rem;
	aspect-ratio: 1;
	margin: auto;
	border-radius: 50%;
	background: var(--l-faint);
}

.cord__grip.is-held {
	cursor: grabbing;
	background: var(--l-raise-2);
}

/* No easing while a hand is on it: the rope has to be exactly where the
   finger is. The spring back is the only animated part. */
.cord:has(.is-held) .cord__rope {
	transition: none;
}

/* ---------------------------------------------------------------- dial

   A dimmer. The angle of the hand around the knob is the brightness, which
   makes this the one mechanic where the light is genuinely continuous. */

.dial {
	--turn: 0;
	position: relative;
	display: grid;
	place-items: center;
	inline-size: clamp(7rem, 21vmin, 10rem);
	aspect-ratio: 1;
}

.dial__track {
	position: absolute;
	inset: 0;
	border: 1px dashed rgb(237 237 233 / 0.18);
	border-radius: 50%;
}

.dial__track::after {
	content: "";
	position: absolute;
	inset: -9%;
	border-radius: 50%;
	background: conic-gradient(
		from 230deg,
		var(--l-yellow) calc(var(--turn) * 260deg),
		transparent 0
	);
	-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
	mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
}

.dial__knob {
	position: relative;
	inline-size: 66%;
	aspect-ratio: 1;
	border: 1px solid var(--l-rule);
	border-radius: 50%;
	background: var(--l-raise);
	cursor: grab;
	touch-action: none;
	rotate: calc(-130deg + var(--turn) * 260deg);
}

.dial__knob::after {
	content: "";
	position: absolute;
	inset-block-start: 12%;
	inset-inline-start: calc(50% - 1px);
	inline-size: 2px;
	block-size: 26%;
	border-radius: 2px;
	background: var(--l-quiet);
}

.dial__knob.is-held {
	cursor: grabbing;
	background: var(--l-raise-2);
}

/* ---------------------------------------------------------------- hold

   Press and keep pressing. The ring fills, the light comes up with it, and
   letting go early lets it fall back. The simplest one to explain on a
   phone, and the one that needs the clearest instruction. */

.hold {
	--charge: 0;
	display: grid;
	place-items: center;
}

.hold__btn {
	position: relative;
	display: grid;
	place-items: center;
	inline-size: clamp(5rem, 17vmin, 7rem);
	aspect-ratio: 1;
	border: 1px solid var(--l-rule);
	border-radius: 50%;
	background: var(--l-raise);
	cursor: pointer;
	touch-action: none;
	transition: background var(--l-dur-1) var(--l-ease);
}

.hold__btn.is-held {
	background: var(--l-raise-2);
}

.hold__btn::after {
	content: "";
	inline-size: 34%;
	aspect-ratio: 1;
	border-radius: 50%;
	background: var(--l-yellow);
	opacity: calc(0.22 + var(--charge) * 0.78);
	scale: calc(0.8 + var(--charge) * 0.35);
}

.hold__ring {
	position: absolute;
	inset: -8px;
	border-radius: 50%;
	background: conic-gradient(
		from -90deg,
		var(--l-yellow) calc(var(--charge) * 360deg),
		transparent 0
	);
	-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
	mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
}

/* ---------------------------------------------------------------- spot

   The dark room. The hand carries a small pool of light and the switch has to
   be found before it can be thrown. The mask follows the pointer in viewport
   coordinates, which is why the stage is stretched to fill the gate. */

/* The defaults belong on the gate, not on the stage.
   lamp.js writes --tx/--ty onto .gate as the hand moves, and a declaration on
   the stage would shadow the inherited value on the very element that reads
   it: the mask would sit at 50% 45% for ever and the switch, which lives
   outside that pool, could never be found. The same shadowing trap Athar
   documents for --athar-sbw. */
.gate--dark {
	--tx: 50%;
	--ty: 45%;
}

/* The floor is 0.1, not transparent. A pool of light in true black is the
   right drama, but it also means the hint, the skip and the switch are
   invisible until they are stumbled on, and a visitor who does not sweep the
   screen is simply stuck. A tenth of an alpha is enough to say "there is
   something here" without giving away where. */
.gate--dark .gate__stage {
	-webkit-mask-image: radial-gradient(
		circle 21vmin at var(--tx) var(--ty),
		#000 0%,
		rgb(0 0 0 / 0.5) 52%,
		rgb(0 0 0 / 0.1) 78%
	);
	mask-image: radial-gradient(
		circle 21vmin at var(--tx) var(--ty),
		#000 0%,
		rgb(0 0 0 / 0.5) 52%,
		rgb(0 0 0 / 0.1) 78%
	);
}

/* Once lit there is nothing left to hunt for, so the mask lifts. */
.gate--dark.is-out .gate__stage {
	-webkit-mask-image: none;
	mask-image: none;
}

.spot__btn {
	display: grid;
	place-items: center;
	inline-size: 4.5rem;
	aspect-ratio: 1;
	border: 1px solid var(--l-rule);
	border-radius: 50%;
	background: var(--l-raise);
	cursor: pointer;
}

.spot__dot {
	inline-size: 0.75rem;
	aspect-ratio: 1;
	border-radius: 50%;
	background: var(--l-yellow);
	opacity: 0.5;
}

.spot__btn:hover .spot__dot {
	opacity: 1;
}

/* ---------------------------------------------------- the dark and the switch

   The room is dark and a warm pool follows the hand through it, but nothing
   hides. The switch sits mid-room with the mark above it and «بس شغّلها»
   under it: the composition of a lamp, its switch, and the instruction. The
   errand this mechanic used to run — the switch by the door, found by torch —
   was cut on review: the idea is the dark and the throw, not the search.
   ========================================================================= */

.gate--hunt {
	--tx: 50%;
	--ty: 50%;
}

/* The beam. A soft warm pool under the hand, on the gate rather than on the
   stage, so it washes the room and not the words. Until the hand moves it
   rests at the centre — on the switch, which is the room's one promise. */
.gate--hunt::before {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(
		circle 26vmin at var(--tx) var(--ty),
		rgb(246 208 13 / 0.09) 0%,
		rgb(246 208 13 / 0.03) 45%,
		transparent 72%
	);
	pointer-events: none;
}

/* One line of text on the screen, and it is the one that says what to do. */
.gate--hunt .gate__sub,
.gate--hunt .gate__hint {
	display: none;
}

/* «بالنص» is the switch's row, not the group's middle. One centred column
   would let the mark's height push the switch below centre, so the stage
   becomes three rows with the switch's own row pinned to the middle: the
   flexible rows above and below stay equal, and the switch holds the centre
   of the room no matter how tall the mark or the slogan run. */
.gate--hunt .gate__stage {
	display: grid;
	grid-template-rows: 1fr auto 1fr;
	justify-items: center;
}

/* Smaller and higher than the other gates draw it: here the mark is the lamp
   hanging over its switch, not the hero of the screen. The margin is the
   lift — its air lands between the mark and the switch, while the slogan
   below keeps only the stage gap and stays tight under the switch. */
.gate--hunt .gate__orb {
	align-self: end;
	inline-size: clamp(5.25rem, 15vmin, 9rem);
	margin-block-end: clamp(1rem, 4vh, 2.5rem);
}

/* A step under hero: the slogan is the caption under the switch now, not the
   headline of the room. */
.gate--hunt .gate__slogan {
	align-self: start;
	font-size: clamp(1.8rem, 5.2vw, 4.1rem);
}

/* Small, low, and quiet enough that the slogan is read first — which was the
   whole request. It is still a real button: full size to press, full contrast
   the moment it takes focus. */
.gate--hunt .gate__skip {
	position: absolute;
	inset-inline: 0;
	inset-block-end: clamp(1.25rem, 4vh, 2.5rem);
	margin-inline: auto;
	inline-size: max-content;
	font-size: var(--l-t-meta);
	letter-spacing: var(--l-track-meta);
	color: var(--l-text);
	opacity: 0.28;
	transition: opacity var(--l-dur-1) var(--l-ease);
}

.gate--hunt .gate__skip:hover,
.gate--hunt .gate__skip:focus-visible {
	opacity: 1;
}

/* --------------------------------------------------------------- the switch */

.hunt__plate {
	inline-size: 5rem;
	padding: 0.5rem;
	border: 1px solid rgb(237 237 233 / 0.14);
	border-radius: var(--l-radius);
	background: rgb(35 35 32 / 0.9);
	transition: box-shadow var(--l-dur-1) var(--l-ease);
}

/* The room still answers the hand, just no longer as a reveal: close to the
   plate — not from across the room — it warms. An unlit switch does not glow
   on its own, so the rest state carries nothing. */
.hunt:hover .hunt__plate,
.hunt:focus-within .hunt__plate {
	box-shadow: 0 0 32px rgb(246 208 13 / 0.14);
}

.hunt__rocker {
	display: block;
	inline-size: 100%;
	block-size: 4rem;
	padding: 0;
	border: 0;
	border-radius: var(--l-radius-s);
	background: linear-gradient(to bottom, var(--l-raise-2) 0 52%, var(--l-ink) 52% 100%);
	cursor: pointer;
	transition: background var(--l-dur-2) var(--l-ease);
}

/* The throw: the lit half swaps ends, the same gesture the plain switch makes. */
.hunt.is-up .hunt__rocker {
	background: linear-gradient(to bottom, var(--l-ink) 0 48%, var(--l-raise-2) 48% 100%);
}

/* ======================================================= the slide switch

   Their own opening, rebuilt.

   lampaah.com opens on a black screen with a yellow slide switch and «يرجى
   تمرير الزر لزيارة الموقع». Copying it would have been the easy read of the
   brief and the wrong one: a visitor who has met that switch has to find this
   one *better*, not merely different. So the object is theirs and everything
   about how it behaves is not.

   The switch is unlit at rest — no glow on a switch nobody has touched, the
   same rule the plain rocker keeps — and it is the hand that lights it. One
   number, --slide, is written by lamp.js as the knob travels, and everything
   warm here is a calc() off that number: the channel fills behind the knob,
   the filament inside it warms from cold grey to the brand yellow, and the
   knob's own spill grows with the journey rather than arriving with the end
   of it.

   Cold grey and not dim yellow, for the reason the gate's mark is: brand
   yellow at low opacity over black is olive sludge, not a dim lamp. Grey metal
   warming to yellow is both the honest colour and what a filament actually
   does.
   ======================================================================= */

.gate--slide {
	/* Where the flood is born. lamp.js overwrites both the moment the knob
	   lands; the centre is the answer for a gate that is skipped instead. */
	--fx: 50%;
	--fy: 50%;
}

/* Smaller than the other gates draw it: on this screen the lamp is what the
   switch is wired to, not the hero of the room. */
.gate--slide .gate__orb {
	inline-size: clamp(5rem, 14vmin, 8.5rem);
}

/* --------------------------------------------------------------- the entrance

   The screen assembles from the bottom of itself, softest first. A blur that
   resolves reads as something coming into focus rather than as something
   sliding in, which is the difference between an opening and a transition.

   `backwards` is what makes the stagger work: without it every piece is on the
   screen at full strength for the length of its own delay and then jumps to
   the start of its animation.

   Each `to` ends at var(--rest, 1) rather than at 1, because two of these
   elements have a resting opacity of their own that is a calc() off --lit — and
   an animation that ends at 1 on top of a rule that says 0.32 is a pop at the
   end of every entrance. During the entrance --lit is 0, so --rest is 1 for
   both and the fade still finishes fully open. */

@keyframes lamba-gate-in {
	from {
		opacity: 0;
		translate: 0 1.5rem;
		filter: blur(12px);
	}

	to {
		opacity: var(--rest, 1);
		translate: 0 0;
		filter: blur(0);
	}
}

.gate--slide .gate__orb,
.gate--slide .gate__slogan,
.gate--slide .gate__sub,
.gate--slide .slide,
.gate--slide .gate__hint,
.gate--slide .gate__skip {
	animation: lamba-gate-in 820ms var(--l-ease) backwards;
}

.gate--slide .gate__orb    { animation-delay: 40ms; }
.gate--slide .gate__slogan { animation-delay: 150ms; --rest: calc(0.32 + var(--lit) * 0.68); }
.gate--slide .gate__sub    { animation-delay: 250ms; }
.gate--slide .slide        { animation-delay: 350ms; }
.gate--slide .gate__hint   { animation-delay: 470ms; --rest: calc(1 - var(--lit)); }
.gate--slide .gate__skip   { animation-delay: 570ms; }

/* ---------------------------------------------------------------- the switch

   Drawn to لمبة's own artwork, handed over 2026-09-01: a solid brand-yellow
   pill with a black knob in it, and roughly two and a fifth times as wide as
   it is tall. The first build here made a dark channel that filled with light
   as the knob travelled — a nice idea about a switch that is off, and not
   their switch. Theirs is yellow before anyone touches it.

   Which turns out to be the better reading of this screen anyway. The room is
   black, the mark and the slogan are held down at a third of their strength
   until the light comes up, and the one thing in the room already at full
   brightness is the switch. Nothing has to point at it.

   The proportion is the artwork's and is kept exactly at every size: the knob
   is the only number, and the padding and the pill are both figured from it.
   ======================================================================= */

.slide {
	--slide: 0;

	/* One number, and the rest is arithmetic — so the shape is identical on a
	   phone and on a desktop, and there is no width to keep in step by hand. */
	--knob: clamp(2.6rem, 7.5vmin, 3.4rem);
	--pad: calc(var(--knob) * 0.13);
	--rail: calc((var(--knob) + var(--pad) * 2) * 2.2);
	--travel: calc(var(--rail) - var(--knob) - var(--pad) * 2);

	/* Physical, and the same in both languages.

	   Every other direction in this theme answers the reading direction; this
	   one does not, and that is deliberate. The switch is لمبة's own artwork
	   and their knob rests at the left and is pushed right — on an Arabic page
	   too, which is where it has always been on lampaah.com. Same call as the
	   work arriving from the left: the object is the object, whatever language
	   the page is in. */
	--dir: 1;

	margin-block-start: clamp(0.4rem, 1.6vh, 1.2rem);
}

.slide__track {
	position: relative;
	inline-size: var(--rail);
	block-size: calc(var(--knob) + var(--pad) * 2);
	border-radius: var(--l-radius-pill);
	background: var(--l-yellow);
	/* No overflow rule on purpose. The knob's spill is meant to fall on the
	   black room around the pill as it nears home, and a channel that clipped
	   it would keep the one piece of light this switch actually gives off. */
	touch-action: none;
}

.slide__knob {
	position: absolute;
	inset-block: var(--pad);
	/* left, not inset-inline-start: it rests at the same end in both
	   languages, so the logical property would be the wrong tool. */
	left: var(--pad);
	inline-size: var(--knob);
	block-size: var(--knob);
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--l-black);
	cursor: grab;
	touch-action: none;
	translate: calc(var(--slide) * var(--travel) * var(--dir)) 0;
	/* Nothing at rest, and more of it the further it gets: the light is the
	   thing the hand is carrying, not a plane the screen puts on. */
	box-shadow: 0 0 calc(var(--slide) * 46px) rgb(246 208 13 / calc(var(--slide) * 0.55));
}

.slide__knob.is-held {
	cursor: grabbing;
}

/* Home. The instant the circuit closes and a beat before the room answers. */
.slide.is-home .slide__knob {
	box-shadow:
		0 0 0 2px rgb(255 249 224 / 0.85),
		0 0 80px rgb(246 208 13 / 0.8);
}

/* ------------------------------------------------------------------- the exit

   Not a fade. A fade is the gate politely getting out of the way; this is the
   room being flooded from the switch that was just thrown, which is the same
   sentence the whole site is built on told once more at the door.

   Three things at once, all of them starting at the knob: a bloom born at
   --fx/--fy and scaled about that same point, the words blowing out of focus,
   and the black itself opening slightly as it goes. The bloom is near-white at
   its core and only warm at its edge — a translucent yellow plane over black
   is the olive sludge this theme learned about the hard way, and a real bulb
   blows a camera out to white before it reads as yellow anyway. */

.gate--slide::after {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(
		circle 30vmax at var(--fx) var(--fy),
		rgb(255 250 232 / 0.95) 0%,
		rgb(255 233 140 / 0.55) 22%,
		rgb(246 208 13 / 0.18) 44%,
		rgb(246 208 13 / 0) 66%
	);
	transform-origin: var(--fx) var(--fy);
	opacity: 0;
	pointer-events: none;
}

.gate--slide.is-out::after {
	animation: lamba-slide-flood 640ms var(--l-ease-io);
}

@keyframes lamba-slide-flood {
	0%   { opacity: 0; scale: 0.08; }
	14%  { opacity: 1; }
	100% { opacity: 0; scale: 2.1; }
}

.gate--slide.is-out {
	animation: lamba-slide-part var(--l-dur-3) var(--l-ease) forwards;
}

@keyframes lamba-slide-part {
	0%   { opacity: 1; scale: 1; }
	26%  { opacity: 1; }
	100% { opacity: 0; scale: 1.09; }
}

.gate--slide.is-out .gate__stage {
	animation: lamba-slide-lift 560ms var(--l-ease) forwards;
}

@keyframes lamba-slide-lift {
	to {
		opacity: 0;
		scale: 1.07;
		filter: blur(7px);
	}
}

/* Everything above is the journey being *watched*. Asked for less of it, the
   switch still works and still says what it did — lamp.js puts the knob home
   in one step — and none of the watching happens. */
@media (prefers-reduced-motion: reduce) {
	.gate--slide .gate__orb,
	.gate--slide .gate__slogan,
	.gate--slide .gate__sub,
	.gate--slide .slide,
	.gate--slide .gate__hint,
	.gate--slide .gate__skip,
	.gate--slide.is-out,
	.gate--slide.is-out::after,
	.gate--slide.is-out .gate__stage {
		animation: none;
	}
}

/* --------------------------------------------------------- plug and socket

   «من أول ما نشبك الفيش». The plug is dragged along the line into the socket
   at the end of it, and the lead between them shortens as it goes.
   ======================================================================= */

.plug {
	--push: 0;
	position: relative;
	inline-size: min(20rem, 70vw);
	block-size: 3.5rem;
}

/* The plug starts at the reading start and travels to the socket at the end,
   which is why every offset here is logical: the end of the line moves with
	   the language, and a physical translate would send it the wrong way in
   one of the two. */
.plug__socket {
	position: absolute;
	inset-inline-end: 0;
	inset-block-start: 50%;
	margin-block-start: -1.6rem;
	inline-size: 2.6rem;
	block-size: 3.2rem;
	border: 1px solid var(--l-rule);
	border-radius: var(--l-radius-s);
	background: var(--l-raise);
}

/* Two holes, which is what tells a small dark rectangle that it is a socket. */
.plug__socket::before,
.plug__socket::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inline-size: 3px;
	block-size: 0.9rem;
	margin-block-start: -0.45rem;
	border-radius: 2px;
	background: var(--l-black);
}

.plug__socket::before { inset-inline-start: 0.7rem; }
.plug__socket::after  { inset-inline-end: 0.7rem; }

/* The lead pays out behind the plug as it goes. */
.plug__lead {
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 50%;
	block-size: 1px;
	inline-size: calc(var(--push) * (100% - 6.4rem));
	background: var(--l-rule);
}

.plug__body {
	position: absolute;
	inset-block-start: 50%;
	margin-block-start: -1.45rem;
	inset-inline-start: calc(var(--push) * (100% - 6.4rem));
	/* 44×44 is the floor for a thing a finger has to catch, and this was
	   51×38 — wide enough and a hand short. */
	inline-size: 3.8rem;
	block-size: 2.9rem;
	padding: 0;
	border: 1px solid var(--l-rule);
	border-radius: var(--l-radius-s);
	background: var(--l-raise-2);
	cursor: grab;
	/* Or the browser takes the drag for a scroll and it never moves. */
	touch-action: none;
	transition: background var(--l-dur-1) var(--l-ease);
}

/* The prongs, on the side facing the socket. */
.plug__body::before,
.plug__body::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-end: -0.55rem;
	inline-size: 0.6rem;
	block-size: 3px;
	border-radius: 2px;
	background: var(--l-faint);
}

.plug__body::before { margin-block-start: -0.45rem; }
.plug__body::after  { margin-block-start: 0.15rem; }

.plug__body.is-held {
	cursor: grabbing;
	background: var(--l-raise);
}

.plug.is-home .plug__body {
	border-color: rgb(246 208 13 / 0.6);
}

/* -------------------------------------------------------------- the switch */

.flip {
	inline-size: 5.5rem;
	padding: 0.5rem;
	border: 1px solid var(--l-rule);
	border-radius: var(--l-radius);
	background: var(--l-raise);
}

.flip__rocker {
	display: block;
	inline-size: 100%;
	block-size: 4.5rem;
	padding: 0;
	border: 0;
	border-radius: var(--l-radius-s);
	background: linear-gradient(to bottom, var(--l-raise-2) 0 52%, var(--l-ink) 52% 100%);
	cursor: pointer;
	transition: background var(--l-dur-2) var(--l-ease);
}

/* The throw: the lit half swaps ends. */
.flip.is-up .flip__rocker {
	background: linear-gradient(to bottom, var(--l-ink) 0 48%, var(--l-raise-2) 48% 100%);
}

.flip__rocker:hover {
	filter: brightness(1.15);
}

/* ------------------------------------------------------------ the filament

   Their mark, used as the control rather than shown as a picture: rub along
   the filament and it heats, and the drawn stroke follows the hand.
   ======================================================================= */

.trace {
	--heat: 0;
	display: grid;
	place-items: center;
}

.trace__pad {
	display: block;
	padding: 1rem;
	border: 0;
	background: none;
	cursor: crosshair;
	touch-action: none;
}

.trace__art {
	inline-size: clamp(7rem, 22vw, 11rem);
}

.trace__art .lamba-mark {
	inline-size: 100%;
}

/* The heat is drawn on the same path the filament is, so what lights is the
   shape of the thing that lights. */
.trace__line {
	fill: none;
	stroke: var(--l-yellow);
	stroke-width: 5;
	stroke-linecap: round;
	stroke-linejoin: round;
	filter: drop-shadow(0 0 6px rgb(246 208 13 / 0.8));
}

/* ------------------------------------------------------------- the spark */

.spark {
	--near: 0;
	position: relative;
	inline-size: min(20rem, 70vw);
	block-size: 3rem;
}

/* The wire is three pixels; the thing you grab is not. A hairline is a
   hairline to look at and a miss to reach for, so the ends are 2.5rem of
   invisible box with the wire drawn across the middle of them. */
.spark__dead,
.spark__live {
	position: absolute;
	inset-block-start: 50%;
	margin-block-start: -1.25rem;
	inline-size: 3.5rem;
	block-size: 2.5rem;
	padding: 0;
	border: 0;
	background: none;
}

.spark__dead::before,
.spark__live::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-start: 50%;
	margin-block-start: -1.5px;
	block-size: 3px;
	border-radius: 2px;
	background: var(--l-faint);
}

.spark__live::before {
	background: var(--l-quiet);
}

.spark__dead {
	inset-inline-end: 0;
}

/* The live end travels toward the dead one, and stops just short of it: the
   last of the gap is crossed by the arc, not by the hand. */
.spark__live {
	inset-inline-start: calc(var(--near) * (100% - 7.6rem));
	cursor: grab;
	touch-action: none;
}

.spark__live.is-held {
	cursor: grabbing;
}

/* What is about to cross the gap. */
.spark__arc {
	position: absolute;
	inset-block-start: 50%;
	margin-block-start: -1.5px;
	inset-inline-start: calc(var(--near) * (100% - 7.6rem) + 3.5rem);
	inset-inline-end: 3.5rem;
	block-size: 3px;
	border-radius: 2px;
	background: var(--l-yellow);
	opacity: 0;
}

.spark.is-close .spark__arc {
	opacity: calc((var(--near) - 0.72) * 2.6);
	box-shadow: 0 0 16px rgb(246 208 13 / 0.9);
	animation: lamba-arc 120ms steps(2, jump-none) infinite;
}

.spark.is-arced .spark__arc {
	opacity: 1;
	animation: none;
}

@keyframes lamba-arc {
	0%, 100% { filter: brightness(1); }
	50% { filter: brightness(1.8); }
}

/* ============================================================ Athar: rhythm

   The price of `add_theme_support( 'athar-css-layer' )`, and Athar's readme
   says so plainly: a layered rule loses to *every* unlayered one, including
   WordPress's own. Core ships `:where(figure) { margin: 0 0 1em }`, which has
   zero specificity but is unlayered, so it beat Athar's section rhythm on
   every section whose root is a <figure> — quote, image, gallery, video and
   before/after. Those five sat flush against the section above them while
   every other type kept its air, which reads as a design mistake rather than
   a cascade one.

   Athar's own three declarations, restated unlayered. The custom properties
   are kept, not resolved: the studio's per-section spacing controls write
   --athar-s-mt and --athar-s-mb, and hardcoding the rhythm here would
   silently disable them.
   ======================================================================= */

.athar-scope > .athar-section {
	margin-block-start: var(--athar-s-mt, var(--athar-rhythm));
	margin-block-end: var(--athar-s-mb, 0px);
}

.athar-scope > .athar-section:first-child,
.athar-scope > .athar-langs + .athar-section {
	margin-block-start: var(--athar-s-mt, 0px);
}

/* ============================================================ Athar: widths

   Three widths, and this site's reading of them: normal is a measure, wide is
   the whole column, full bleeds to the viewport edge.

   Athar's own align-wide is a fraction of the viewport (--athar-wide), which
   is the right default for a theme with no column of its own. This one has
   one, and a work grid that is wider than the header above it looks like a
   mistake rather than a decision. Full bleed is left exactly as the plugin
   computes it.

   No !important and no specificity arithmetic: functions.php puts Athar in a
   cascade layer, and an unlayered rule outranks every layered one.
   ======================================================================= */

.athar-scope .athar-section.athar-align-wide {
	margin-inline: 0;
	inline-size: 100%;
	max-inline-size: 100%;
}

/* =========================================================== Athar: stats

   The results block, and the thing their own case-study layout leads with:
   a small yellow label over a very large yellow number.
   ======================================================================= */

/* The opener. A short stroke of filament and a quiet word — this is what
   replaced the rules that used to separate the sections, and it is the one
   device the whole page below the opening now shares. */
.athar-scope .athar-stats__intro {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	margin: 0 0 var(--l-rhythm-tight);
	max-inline-size: none;
	color: var(--l-quiet);
	font-size: var(--l-t-meta);
	letter-spacing: var(--l-track-meta);
	text-transform: uppercase;
}

.athar-scope .athar-stats__intro::before {
	content: "";
	inline-size: clamp(1.5rem, 4vw, 3rem);
	block-size: 1px;
	background: var(--l-yellow);
	opacity: calc(0.3 + var(--lit) * 0.7);
}

/* auto-fit made three figures share a full-width row, so each one floated in
   the middle of a 389px cell with its label adrift under it. They sit together
   now and the row ends where they do. */
.athar-scope .athar-stats__grid {
	display: grid;
	gap: clamp(2rem, 6vw, 5rem);
	grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), max-content));
	justify-content: start;
	margin: 0;
	/* Athar rules the top of this grid off its own hairline token, which this
	   site feeds. Removing the item's rule was not enough; this is the other
	   half of the same line. */
	padding-block-start: 0;
	border-block-start: 0;
}

/* No rule over each figure. A number this size does not need a line to say
   where it starts, and the line was the only thing making three of these look
   like a table. */
/* The number first and the label under it, which is the order they are read
   in. It used to be reversed, on a reading of their case-study layout, and
   what that produced was a figure you met before you knew what it counted. */
.athar-scope .athar-stats__item {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.athar-scope .athar-stats__value {
	font-family: var(--l-display);
	/* Down from the metric scale. It was the largest thing on the page and it
	   is not the most important one. */
	font-size: clamp(2.1rem, 4.6vw, 3.6rem);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-hero);
	line-height: 1;
	color: var(--l-yellow);
	/* Latin figures, and tabular, so three of them line up as a row rather
	   than as three separate widths. */
	font-variant-numeric: tabular-nums lining-nums;
	/* The numbers are the light. They come up with it and never fully leave. */
	opacity: calc(0.4 + var(--lit) * 0.6);
}

/* Up from a caption. It is the half of the pair that carries the meaning. */
.athar-scope .athar-stats__label {
	margin: 0;
	max-inline-size: 18ch;
	color: var(--l-text);
	font-size: var(--l-t-body);
	line-height: var(--l-lh-head);
	text-wrap: pretty;
}

/* ======================================================== Athar: features

   The three pillars: الإنتاج, الإبداع, التواصل. Numbered, because the
   client's chosen homepage reference numbers its services and it reads as
   confidence rather than decoration.
   ======================================================================= */

/* The heading beside the pillars rather than over them. It used to sit in a
   24ch box at the start of a full-width row with a thousand pixels of nothing
   next to it — which is the void, and no amount of spacing was going to fix a
   thing that was structural. */
@media (min-width: 62rem) {
	.athar-scope .athar-features {
		display: grid;
		grid-template-columns: minmax(15rem, 21rem) 1fr;
		column-gap: clamp(2.5rem, 6vw, 6rem);
		align-items: start;
	}

	/* It holds while the three read past it. */
	.athar-scope .athar-features__head {
		position: sticky;
		inset-block-start: clamp(7rem, 18vh, 11rem);
	}
}

.athar-scope .athar-features__head {
	margin-block-end: var(--l-rhythm-tight);
	margin-inline: 0;
	max-inline-size: 22ch;
}

.athar-scope .athar-features__heading {
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--athar-h-l);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
}

.athar-scope .athar-features__intro {
	margin-block: var(--athar-gap-tight) 0;
	color: var(--l-quiet);
	text-wrap: pretty;
}

/* The grid used to be drawn by its own gaps: a one-pixel background showing
   through between cells. It read as a table of contents. Then it was three
   thin columns, which read as a table of contents in a different font. It is
   a list now, and a list of three things is what this actually is. */
.athar-scope .athar-features__grid {
	display: grid;
	/* Declared, not left out. Athar sets its own columns in the layer, and a
	   property this file never names is a property this file never wins — so
	   removing the count rules above changed nothing until this line existed. */
	grid-template-columns: minmax(0, 1fr);
	gap: clamp(2rem, 4vh, 3.25rem);
	margin-block-end: 0;
}

/* The column counts are gone on purpose. Whatever number the editor picks in
   the studio, the pillars read down this site as a list: two or four of them
   side by side is the same thin-column layout that put a paragraph on a 225px
   line. The setting still means something to any other site on Athar; here it
   means nothing, and saying so once is better than a rule per count. */

/* The number beside the words, on the title's own line, rather than stacked
   above them: in a row that wide a number on its own line is a heading nobody
   asked for. */
.athar-scope .athar-features__item {
	counter-increment: pillar;
	position: relative;
	padding: 0;
	display: grid;
	grid-template-columns: auto 1fr;
	column-gap: clamp(1rem, 2.5vw, 2rem);
	align-items: baseline;
}

.athar-scope .athar-features__title,
.athar-scope .athar-features__body,
.athar-scope .athar-features__figure {
	grid-column: 2;
}

/* The number is an index, not a headline. It was briefly set at heading size
   to replace the cell walls that used to divide these, and it ended up louder
   than the titles it was numbering. Small, tracked, and out of the way — the
   titles do the ordering now, because they are the largest thing here. */
.athar-scope .athar-features__item::before {
	content: counter(pillar, decimal-leading-zero);
	grid-column: 1;
	grid-row: 1 / span 3;
	display: block;
	font-size: var(--l-t-meta);
	font-weight: var(--l-w-mid);
	letter-spacing: var(--l-track-meta);
	line-height: 1;
	color: var(--l-yellow);
	font-variant-numeric: tabular-nums lining-nums;
	opacity: calc(0.35 + var(--lit) * 0.45);
	transition: opacity var(--l-dur-1) var(--l-ease);
}

/* Lit, not filled. A background on hover was the cell answering; this is the
   light coming up on the thing being read. */
.athar-scope .athar-features__item:hover::before {
	opacity: 1;
}

.athar-scope .athar-features__title {
	margin: 0 0 0.7em;
	font-family: var(--l-display);
	font-size: var(--l-t-h2);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
	text-wrap: balance;
}

.athar-scope .athar-features__body {
	margin: 0;
	/* A measure, not a column width. It was 34ch inside a 413px cell, which is
	   neither. */
	max-inline-size: 54ch;
	color: var(--l-quiet);
	font-size: var(--l-t-body);
	line-height: var(--l-lh-body);
	text-wrap: pretty;
}

.athar-scope .athar-features__figure {
	margin: 0 0 var(--athar-gap);
	max-inline-size: 2.5rem;
}

/* The grid counts the items, so the counter has to be reset on the section. */
.athar-scope .athar-features {
	counter-reset: pillar;
}

/* ===================================================================== rail

   The work, travelling sideways while the page scrolls down.

   Three boxes and one number. The section is tall — one screen plus however
   far the track has to travel — so there is scroll to spend. The stage inside
   it pins to the top for exactly that distance. The track slides across it.
   When the section runs out, the stage unpins and the page carries on, which
   is the part that has to feel like nothing happened.

   The travel is set in physical pixels with a sign taken from the page's
   direction, not with a logical property: `translate` is physical, and this
   site is read right to left, where the work arrives from the left.

   Everything below only applies once lamp.js has measured the overflow and
   added .is-railed. Before that — and forever, with no script — the stage is
   a strip you push sideways with a finger or a trackpad. That is a real way
   to read a row of work, so there is nothing to apologise for and nothing to
   wait for.
   ======================================================================= */

.athar-scope .lamba-rail {
	padding-block: 0;
}

.lamba-rail__stage {
	display: grid;
	grid-template-rows: auto 1fr;
	gap: clamp(0.9rem, 2vh, 1.6rem);
	padding-block: var(--l-rhythm-tight);
}

.lamba-rail__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--athar-gap);
}

/* Before the measure, and with no script at all: a sideways strip. */
.lamba-rail__window {
	/* One cell, so the track stretches to the stage's row instead of standing
	   at the height of its own content. There used to be a min-block-size on
	   the track doing that job by hand; it was removed as a cap it never was,
	   and the cards immediately collapsed to the height of a title. */
	display: grid;

	/* A grid item's automatic minimum size is its content, so without this the
	   track's full width becomes the stage's column width — and the heading
	   above, which centres in that column, drifts off the screen's centre. */
	min-inline-size: 0;
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
	padding-inline: var(--l-gutter);
}

.lamba-rail__window::-webkit-scrollbar {
	display: none;
}

/* Masonry, in the only direction that has room for it: two rows deep, and
   every third card taking both. The columns are one width, so the rhythm
   comes from the heights and not from a ragged grid. */
.lamba-rail__track {
	display: grid;
	grid-auto-flow: column dense;
	grid-template-rows: repeat(2, minmax(0, 1fr));
	/* Wider. They were reading as thumbnails on a wall rather than as work,
	   and a rail exists to give each piece room the page cannot. */
	grid-auto-columns: clamp(17rem, 30vw, 30rem);
	gap: clamp(0.75rem, 1.6vw, 1.5rem);
	margin: 0;
	padding: 0;
	list-style: none;
	inline-size: max-content;
	/* A floor for the state before any measuring — and for a reader with no
	   script, where the stage never pins and nothing stretches. */
	min-block-size: min(58svh, 32rem);
}

/* Which cards take both rows.
 *
 * This was `:nth-child(3n + 1)` — every third card, whatever was in it, on no
 * basis but where it fell. It is a **class printed by PHP** now, because the
 * shape is a project's own setting with `auto` falling back to exactly that
 * old rule (lamba_rail_shape()). Counting here as well would have meant two
 * answers to one question, and the selector cannot see the setting, so it
 * would have won the arguments it should lose. */
.lamba-rail__track > .athar-pcard--tall {
	grid-row: span 2;
}

/* In the rail a card is as tall as the row it was dealt, so the 4:3 the card
   states for a grid steps aside. A card that owns both rows then shows more of
   its still and one that shares gets a letterbox — which is the whole point of
   masonry, and the thing a single ratio everywhere quietly cancels. */
.athar-scope .lamba-rail .athar-pcard {
	aspect-ratio: auto;
	block-size: 100%;
}

/* ------------------------------------------------------------- once measured */

.lamba-rail.is-railed {
	/* One screen to pin for, plus the scroll the cards are dealt over, plus
	   the distance the track then has to cover. The deal has to be *in this
	   height* or there is no scrolling for it to happen over: it is spent
	   while the stage is already pinned, so the work arrives with the room
	   held still, and only then does the track start moving sideways.
	   lamp.js writes both numbers; see rail() and deal(). */
	min-block-size: calc(100svh + var(--deal-run, 0px) + var(--rail-scroll, 0px));
}

.lamba-rail.is-railed .lamba-rail__stage {
	position: sticky;
	inset-block-start: 0;
	block-size: 100svh;
	align-content: center;
	/* Clip, not hidden: hidden would make this a scroll container and a scroll
	   container cannot be sticky in its own scroller. */
	overflow: clip;
	/* The floor blurs the bottom of the window and the capsule floats over the
	   top, so the stage clears both — and no more than both. Every rem of
	   padding here comes straight off the height of the work. */
	padding-block: clamp(4.5rem, 10vh, 6.5rem) clamp(6rem, 15vh, 12rem);
}

.lamba-rail.is-railed .lamba-rail__window {
	overflow: visible;
	/* Held to the stage. Left to itself a visible box grows to its content,
	   and a window as wide as the track is not a window. The stage clips what
	   hangs out of it. */
	inline-size: 100%;
	padding-inline: var(--l-gutter);
}

.lamba-rail.is-railed .lamba-rail__track {
	translate: var(--rail-x, 0px) 0;
	will-change: transform;
}

/* ============================================================ Athar: work */

.athar-scope .athar-work__head {
	display: flex;
	flex-wrap: wrap;
	gap: var(--athar-gap);
	align-items: baseline;
	justify-content: space-between;
	margin-block-end: var(--athar-gap-loose);
}

.athar-scope .athar-work__heading {
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--athar-h-l);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
}

/* The yellow underline on the first word, which is how their own case-study
   layout sets this heading. Applied to the whole heading's last line would be
   wrong, so it is a span the template writes. */
.athar-scope .athar-work__heading b,
.athar-scope .athar-work__heading strong {
	font-weight: inherit;
	box-shadow: inset 0 -0.18em 0 var(--l-yellow);
}

.athar-scope .athar-work__all {
	font-size: var(--l-t-small);
	color: var(--l-quiet);
	text-decoration: none;
	border-block-end: 1px solid var(--l-rule);
	padding-block-end: 0.25em;
	transition: color var(--l-dur-1) var(--l-ease);
}

.athar-scope .athar-work__all:hover {
	color: var(--l-yellow);
	border-block-end-color: var(--l-yellow);
}

/* ====================================================== Athar: project card

   A picture with a name written on it.

   It was two boxes: a picture box on top, a lighter panel under it, two greys
   a shade apart, so every card read as two rectangles glued together — and on
   a project with no still the top rectangle was most of the card and empty.
   Now the picture is the whole card and the words lie on it under a gradient,
   which is the arrangement the opening uses: a card is a small version of the
   page it sits on.

   The markup it has to do that with is the plugin's, and the shape of it is
   the reason everything below is positioned rather than stacked:

       li.athar-pcard
         a.athar-pcard__link          the whole card is this link's target
           span.athar-pcard__media    the still
           span.athar-pcard__body     the client and the title
         ul.athar-pcard__pills        the services — a SIBLING of the link

   The pills sit outside the link, so no amount of layout inside the link can
   put them under the title. Percentage heights cannot help either: the card
   was taking its height from a grid row and handing nothing definite down, so
   the link resolved 100% against something 44px shorter than itself and left
   a strip of ink under every picture.

   So: the still is taken out of flow and pinned to the card, the card's height
   is stated outright, and everything that is words stacks at the bottom in
   normal flow above it. Nothing here asks a question that needs a number from
   anything else.
   ======================================================================= */

.athar-scope .athar-portfolio__grid {
	display: grid;
	gap: var(--athar-gap);
	grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr));
}

.athar-scope .athar-pcard {
	position: relative;
	display: flex;
	flex-direction: column;
	/* The words sit on the floor of the card and the picture fills it. */
	justify-content: flex-end;
	/* Stated, not inherited: the still is out of flow and cannot give the card
	   a height, so the card says what it is. The rail overrides this with the
	   row it was dealt. */
	aspect-ratio: 4 / 3;
	border-radius: var(--l-radius);
	background: var(--l-ink);
	overflow: hidden;
	isolation: isolate;
	/* translate is deliberately not in this list, and nothing adds it back.
	   It is written on every frame of a scroll by the arrival above, and a
	   520ms ease laid over that is a card that spends the whole scroll
	   catching up with itself. Since the hover no longer moves the card,
	   the arrival is the only thing that owns the property at all. */
	transition: box-shadow var(--l-dur-2) var(--l-ease);
}

/* ----------------------------------------------------------- dealing them in

   The work arrives from the left, one card after another, and it walks with
   the scroll.

   Two earlier versions were cut on the way here, and both are worth keeping in
   mind. The first animated **each card as it crossed the edge of the screen**:
   in the rail, which travels sideways while the page scrolls down, a card
   crosses an edge over and over, so it never stopped running. The second fired
   a timed stagger once when the group was reached — better, but a timer runs
   at its own speed and pays no attention to the hand on the wheel.

   This one has no timer at all. lamp.js writes **one number per group**,
   --deal, out of where that group sits against the window, and the stagger is
   folded into the number rather than into a delay: each card takes its slice
   of the range, starting a little later than the card before it. Scroll and
   they come; scroll back and they go. Nothing animates on its own.

   The arithmetic has to close: the last card of a group starts at
   11 × 0.045 = 0.495 and spends 0.5 getting home, which lands on 0.995. Widen
   either number and the tail of a full group would never arrive.

   **From the left in both languages**, by request. Every other arrival here
   answers the reading direction — the sections come from the inline start and
   flip with the language. This one does not, so the translate below is
   physical and there is no [dir] rule to go with it.

   Gated on .lamp-js, and --deal defaults to 1: no script, less motion asked
   for, or a number never written, and the work is simply there. The failure
   direction is always *visible*.
   ======================================================================= */

.lamp-js .athar-scope .athar-pcard {
	--p: clamp(0, (var(--deal, 1) - var(--n, 0) * 0.045) / 0.5, 1);

	opacity: var(--p);
	translate: calc((1 - var(--p)) * -4rem) 0;
}

/* ------------------------------------------------------------- the still

   The card is off until you turn it on. Greyscale and dimmed at rest; a
   pointer over it, or a finger held on it, and the colour comes up with a
   short catch, the way a lamp strikes rather than fades. This is the site's
   whole idea repeated at card scale. lamp.js sets .is-on for both input
   kinds. */

.athar-scope .athar-pcard__media {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	overflow: hidden;
	background: var(--l-ink);
	filter: grayscale(1) brightness(0.52) contrast(1.15);
	transition: filter var(--l-dur-2) var(--l-ease);
}

.athar-scope .athar-pcard.is-on .athar-pcard__media {
	filter: none;
	animation: lamba-strike 460ms var(--l-ease);
}

/* A lamp catches before it holds: up, dip, then steady. Short enough to read
   as physical rather than as an effect. */
@keyframes lamba-strike {
	0%   { filter: grayscale(1) brightness(0.52) contrast(1.15); }
	22%  { filter: grayscale(0.15) brightness(1.28) contrast(1.05); }
	34%  { filter: grayscale(0.5) brightness(0.78) contrast(1.1); }
	60%  { filter: grayscale(0) brightness(1.1) contrast(1); }
	100% { filter: none; }
}

.athar-scope .athar-pcard__media img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	filter: var(--l-photo);
}

/* A project with no still yet.

   There used to be a circle drawn in the middle of it, on the reasoning that
   a mark reads better than a void. It does not: at card size it reads as a
   broken image, and in the rail, where a card can be two rows tall, it was a
   large empty rectangle with a target in it. A still-less card is simply a
   panel with its name on it, which is a card and not a gap. */
.athar-scope .athar-pcard__media--empty {
	background: var(--l-raise);
	filter: none;
}

.athar-scope .athar-pcard.is-on .athar-pcard__media--empty {
	background: var(--l-raise-2);
	filter: none;
	animation: none;
}

/* ------------------------------------------------------------- the words

   One gradient for both of them, on the card rather than on either, because
   they are in different subtrees and a gradient each would seam. */

.athar-scope .athar-pcard::before {
	content: "";
	position: absolute;
	z-index: 1;
	inset-inline: 0;
	inset-block-end: 0;
	block-size: 72%;
	background: linear-gradient(
		to top,
		rgb(0 0 0 / 0.9) 0%,
		rgb(0 0 0 / 0.62) 34%,
		rgb(0 0 0 / 0.22) 66%,
		rgb(0 0 0 / 0) 100%
	);
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--l-dur-1) var(--l-ease);
}

.athar-scope .athar-pcard.is-on::before {
	opacity: 1;
}

/* Nothing to light on a card with no still, so less dark is needed to read
   the name on it. */
.athar-scope .athar-pcard:has(.athar-pcard__media--empty)::before {
	block-size: 100%;
	background: linear-gradient(to top, rgb(0 0 0 / 0.35) 0%, rgb(0 0 0 / 0) 70%);
}

/* Deliberately not positioned. The still is pinned with inset: 0 and has to
   measure that against the card; give the link a position and the link becomes
   the containing block instead, and the picture collapses to the height of the
   title. As a flex item the link takes a z-index without one. */
.athar-scope .athar-pcard__link {
	z-index: 2;
	color: inherit;
	text-decoration: none;
}

/* The whole card is the target, but only the title is the accessible link. */
.athar-scope .athar-pcard__link::after {
	content: "";
	position: absolute;
	inset: 0;
}

.athar-scope .athar-pcard__body,
.athar-scope .athar-pcard__pills {
	opacity: 0;
	translate: 0 0.5rem;
	transition:
		opacity var(--l-dur-1) var(--l-ease),
		translate var(--l-dur-1) var(--l-ease);
}

.athar-scope .athar-pcard.is-on .athar-pcard__body,
.athar-scope .athar-pcard.is-on .athar-pcard__pills {
	opacity: 1;
	translate: 0 0;
}

/* No pointer, no reveal to wait for. The tap that would have shown the name
   is the same tap that opens the project, so on a touch screen the card keeps
   saying what it is. */
@media (hover: none) {
	.athar-scope .athar-pcard::before,
	.athar-scope .athar-pcard__body,
	.athar-scope .athar-pcard__pills {
		opacity: 1;
		translate: 0 0;
	}
}

/* Padded on all four sides now, where it used to sit flush against the bottom
   edge with the client's name filling the space under the title. The name came
   off — one word on a card, and on their own work usually the same word as the
   title — and a title left where the second line used to start reads as having
   fallen down the card. So the words are lifted, and the air under them is the
   air the name was taking. */
.athar-scope .athar-pcard__body {
	display: block;
	padding: var(--athar-gap) var(--athar-gap) calc(var(--athar-gap) * 1.5);
	text-align: start;
}

.athar-scope .athar-pcard__title {
	display: block;
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--athar-h-s);
	font-weight: var(--l-w-mid);
	line-height: var(--l-lh-head);
	text-wrap: balance;
}

.athar-scope .athar-pcard__pills {
	position: relative;
	z-index: 2;
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem;
	margin: 0;
	padding: 0.5rem var(--athar-gap) var(--athar-gap);
	list-style: none;
}

/* Small. They are a footnote on a picture, not a second heading — and now
   that they only appear when the card is lit, they can afford to be quiet. */
.athar-scope .athar-pcard__pill {
	padding: 0.22em 0.6em;
	border: 1px solid rgb(237 237 233 / 0.24);
	border-radius: var(--l-radius-pill);
	font-size: 0.6rem;
	letter-spacing: 0.05em;
	line-height: 1.5;
	color: var(--l-quiet);
}

/* Lighting a card lights it, and does nothing else to it.

   It used to lift 3px and its still used to swell 3%, and both are gone at
   Saad's asking: «الhover لا يصير تحريك للكارد خله بس تأثير اللمبة». He is
   right on the site's own terms — a lamp coming on does not move the thing it
   is inside. What is left is light and only light: the greyscale falls away
   with the strike, the words come up out of the dark, and the warm spill
   belongs to the card so it travels with it and never becomes a plane of its
   own. Nothing here changes where anything is.

   The card's own geometry is the arrival's now, and only the arrival's. */
.athar-scope .athar-pcard.is-on {
	box-shadow: 0 18px 60px -18px rgb(246 208 13 / 0.4);
}

/* ============================================================= Athar: cta */

.athar-scope .lamba-cta {
	padding-block: var(--l-rhythm);
	text-align: center;
}

.athar-scope .lamba-cta__inner {
	max-inline-size: var(--athar-measure);
	margin-inline: auto;
}

.athar-scope .lamba-cta__heading {
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--l-t-display);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-display);
	text-wrap: balance;
}

.athar-scope .lamba-cta__text {
	margin-block: var(--athar-gap-tight) 0;
	color: var(--l-quiet);
	text-wrap: pretty;
}

/* The pill button, exactly as their own case-study layout draws it: solid
   brand yellow, black type, and an arrow that follows the reading direction.
   .athar-button is the plugin's own button, used by the cover and the shipped
   call to action; it is dressed here rather than in a second rule so the two
   cannot drift apart. */
.athar-scope .lamba-cta__go,
.athar-scope .athar-button {
	display: inline-flex;
	align-items: center;
	gap: 0.6em;
	margin-block-start: var(--athar-gap);
	padding: 0.75em 1.5em;
	border-radius: var(--l-radius-pill);
	background: var(--l-yellow);
	color: var(--l-black);
	font-weight: var(--l-w-mid);
	text-decoration: none;
	transition:
		gap var(--l-dur-1) var(--l-ease),
		box-shadow var(--l-dur-2) var(--l-ease);
	box-shadow: 0 0 0 rgb(246 208 13 / 0);
}

.athar-scope .lamba-cta__go:hover,
.athar-scope .lamba-cta__go:focus-visible,
.athar-scope .athar-button:hover,
.athar-scope .athar-button:focus-visible {
	gap: 1em;
	box-shadow: 0 0 34px -4px rgb(246 208 13 / 0.55);
}

/* The arrow points the way the text runs, and the text runs both ways. */
.athar-scope .lamba-cta__go [aria-hidden] {
	display: inline-block;
	scale: -1 1;
}

[dir="ltr"] .athar-scope .lamba-cta__go [aria-hidden] {
	scale: 1 1;
}

/* --------------------------------------------------- the ask, and the room

   «عندكم فكرة؟» with the work standing all the way around it.

   A pile of stills in the middle of the screen, and the page's own scrolling
   is what takes it apart: the section is a screen taller than it looks, its
   stage is pinned for that extra screen, and one number — --spread, 0 to 1 —
   is spent on eight resting places. By the end the reader is standing in the
   middle of the work with the sentence that asks for the next piece of it.

   The same architecture as the rail below, and for the same reason: vertical
   scrolling is the only input. There is no second gesture to discover, and a
   wheel, a trackpad, a finger and the space bar all drive it identically.

   Three states, and all three have to be a finished page:

     * **No stills.** No .lamba-cta--scatter, so none of this applies and the
       section is exactly the centred ask it has always been.
     * **No script.** --spread stays at its declared 1 and .is-spread is never
       added, so nothing pins and the scatter is a still composition. A fine
       thing for a last section to be, and what a crawler is served.
     * **Less motion asked for.** lamp.js does not drive it at all, which
       lands on the state above.

   The stills are greyscale while they are piled and come to colour as they
   part, because that is this site's one idea said once more: it is all off
   until somebody turns it on, and here the scrolling is the hand.
   ======================================================================= */

.lamba-cta--scatter {
	/* How much scrolling the coming-apart is given. lamp.js writes it; the
	   declared 0 means an unpinned section is exactly its own height. */
	--cta-run: 0px;
	padding-block: 0;
}

.lamba-cta--scatter .lamba-cta__stage {
	display: grid;
	place-items: center;
	min-block-size: 100svh;
	padding-inline: var(--l-gutter);
	/* clip and not hidden: hidden would make the stage a scroll container, and
	   a scroll container cannot be sticky inside its own scroller. The rail
	   learned this two sections down. */
	overflow: clip;

	/* How far through the coming-apart the words are. Held here rather than on
	   the words themselves because the scrim behind them reads it too, and two
	   copies of one curve is two things to keep in step by hand. */
	--say: clamp(0, (var(--spread, 1) - 0.28) / 0.34, 1);
}

.lamba-cta--scatter.is-spread {
	min-block-size: calc(100svh + var(--cta-run));
}

.lamba-cta--scatter.is-spread .lamba-cta__stage {
	position: sticky;
	inset-block-start: 0;
	block-size: 100svh;
}

/* All three layers in one cell, stacked by z-index rather than by order, so
   the scrim can sit between the pictures and the words.

   place-self: stretch on the two full-bleed layers because a place-items:
   center grid shrinks a child to its content — which for a layer whose own
   children are absolutely positioned is nothing at all. */
.lamba-cta--scatter .lamba-cta__scatter,
.lamba-cta--scatter .lamba-cta__stage::before,
.lamba-cta--scatter .lamba-cta__inner {
	grid-area: 1 / 1;
}

.lamba-cta--scatter .lamba-cta__scatter,
.lamba-cta--scatter .lamba-cta__stage::before {
	place-self: stretch;
}

.lamba-cta--scatter .lamba-cta__scatter {
	position: relative;
	z-index: 0;
	/* The stills' own z-indexes are about each other and nothing else. */
	isolation: isolate;
}

/* The room's own dark, gathered under the words. Not a panel and not a card:
   a vignette of the ground the page is already made of, which is why it can
   sit over photographs without reading as a box that has been put there. It
   arrives with the words and is not there before them. */
.lamba-cta--scatter .lamba-cta__stage::before {
	content: "";
	z-index: 1;
	background: radial-gradient(
		ellipse 48% 42% at 50% 50%,
		var(--l-ground) 0%,
		color-mix(in oklab, var(--l-ground) 72%, transparent) 52%,
		transparent 76%
	);
	opacity: var(--say);
	pointer-events: none;
}

.lamba-cta--scatter .lamba-cta__inner {
	position: relative;
	z-index: 2;
	opacity: var(--say);
	translate: 0 calc((1 - var(--say)) * 1.75rem);
	filter: blur(calc((1 - var(--say)) * 9px));
}

/* Invisible and unreachable are the same thing, and a contact button that can
   be pressed through a pile of photographs is neither. .is-said arrives from
   lamp.js at the halfway mark, which is well before the words are readable. */
.lamba-cta--scatter.is-spread .lamba-cta__inner {
	pointer-events: none;
}

.lamba-cta--scatter.is-said .lamba-cta__inner {
	pointer-events: auto;
}

/* ------------------------------------------------------------- one still

   inset: 0 with margin: auto centres a box of known size without naming a
   side, which is the whole reason the size is declared here: it keeps the
   composition identical in both directions without a single mirrored rule.

   --r0 is where it lies in the pile and --r is where it comes to rest, so the
   rotation is read between the two rather than starting from square. A pile of
   perfectly aligned rectangles is a stack of paper; a few degrees each way is
   a pile of photographs. */

.lamba-cta__still {
	position: absolute;
	inset: 0;
	margin: auto;
	inline-size: var(--w);
	block-size: var(--h);
	border-radius: var(--l-radius);
	overflow: hidden;
	background: var(--l-raise);
	box-shadow: 0 26px 70px -24px rgb(0 0 0 / 0.85);

	translate:
		calc(var(--x) * var(--spread, 1))
		calc(var(--y) * var(--spread, 1));
	rotate: calc(var(--r0) * (1 - var(--spread, 1)) + var(--r) * var(--spread, 1));
	scale: calc(0.74 + 0.26 * var(--spread, 1));
}

.lamba-cta__shot {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	/* Off until it is turned on. A colour matrix and not a blur: this runs on
	   eight elements on every frame of a scroll, and blur at that rate is the
	   one filter this theme has already watched hang a renderer. */
	filter: grayscale(calc((1 - var(--spread, 1)) * 0.9)) brightness(calc(0.6 + var(--spread, 1) * 0.4));
}

/* The eight resting places. Sizes alternate between upright and lying down so
   the ring reads as photographs rather than as a grid that has been exploded. */
.lamba-cta__still:nth-child(1) { --w: clamp(8rem, 17vw, 15rem);   --h: clamp(10rem, 21vw, 19rem);   --x: -32vw; --y: -19vh; --r: -7deg; --r0: -6deg; z-index: 5; }
.lamba-cta__still:nth-child(2) { --w: clamp(9rem, 19vw, 17rem);   --h: clamp(7rem, 14vw, 12.5rem);  --x:  30vw; --y: -24vh; --r:  6deg; --r0:  4deg; z-index: 4; }
.lamba-cta__still:nth-child(3) { --w: clamp(8rem, 16vw, 14rem);   --h: clamp(10rem, 20vw, 18rem);   --x: -37vw; --y:  11vh; --r:  5deg; --r0: -3deg; z-index: 7; }
.lamba-cta__still:nth-child(4) { --w: clamp(9rem, 18vw, 16rem);   --h: clamp(7rem, 13vw, 12rem);    --x:  36vw; --y:   9vh; --r: -5deg; --r0:  7deg; z-index: 3; }
.lamba-cta__still:nth-child(5) { --w: clamp(8rem, 15vw, 13rem);   --h: clamp(9rem, 18vw, 16rem);    --x: -21vw; --y:  30vh; --r:  6deg; --r0: -5deg; z-index: 6; }
.lamba-cta__still:nth-child(6) { --w: clamp(9rem, 17vw, 15rem);   --h: clamp(7rem, 13vw, 12rem);    --x:  24vw; --y:  31vh; --r: -7deg; --r0:  2deg; z-index: 8; }
.lamba-cta__still:nth-child(7) { --w: clamp(7rem, 14vw, 12rem);   --h: clamp(9rem, 17vw, 15rem);    --x:  -5vw; --y: -33vh; --r:  4deg; --r0: -8deg; z-index: 2; }
.lamba-cta__still:nth-child(8) { --w: clamp(9rem, 16vw, 14rem);   --h: clamp(7rem, 12vw, 11rem);    --x:   6vw; --y:  34vh; --r: -4deg; --r0:  5deg; z-index: 1; }

/* A phone is not a small room, it is a narrow one. The stills go smaller and
   further out, and the scrim above does the rest of the work — which is why
   there is a scrim at all rather than a set of positions that only just clear
   the words at one width. */
@media (max-width: 48rem) {
	.lamba-cta__still {
		--w: clamp(5.5rem, 34vw, 10rem);
		--h: clamp(6.5rem, 40vw, 12rem);
	}

	.lamba-cta__still:nth-child(1) { --x: -27vw; --y: -25vh; }
	.lamba-cta__still:nth-child(2) { --x:  27vw; --y: -29vh; }
	.lamba-cta__still:nth-child(3) { --x: -31vw; --y:  -2vh; }
	.lamba-cta__still:nth-child(4) { --x:  31vw; --y:   1vh; }
	.lamba-cta__still:nth-child(5) { --x: -25vw; --y:  28vh; }
	.lamba-cta__still:nth-child(6) { --x:  26vw; --y:  31vh; }
	.lamba-cta__still:nth-child(7) { --x:  -2vw; --y: -38vh; }
	.lamba-cta__still:nth-child(8) { --x:   3vw; --y:  38vh; }
}

/* ===================================================================== wire

   The quote, expressing itself.

   «من أول ما نشبك الفيش لين نشغل اللمبة». A cord runs under the line from the
   edge of the screen — the current arrives from outside the page, which is why
   nothing draws a plug: the plug is the edge — and as the section climbs the
   screen the light travels the cord, through the words in the order they are
   read, and reaches the lamp at the end.

   All of it hangs off one number, --p, from 0 to 1. It defaults to 1, so with
   no script the line is lit, the cord is drawn and the lamp is on: the served
   state is the finished state.

   The words are lit by a gradient clipped to the glyphs, not by a box sliding
   over them: a box would have a moving edge across the letterforms, and Arabic
   joins — an edge across a joined word cuts a letter in half rather than
   revealing it. Clipped to the text, the light is inside the strokes.
   ======================================================================= */

.athar-scope .lamba-wire {
	--p: 1;
	/* Physical, because gradients and transform-origin are. This site is read
	   right to left, so the current enters from the right. */
	--wire-from: to left;
	--wire-root: right;

	position: relative;
	max-inline-size: none;
	margin-inline: 0;
	padding-block: var(--l-rhythm);
	padding-inline: var(--l-gutter);
	/* Athar rules a quote off with a bar down its side, from a token this site
	   feeds. A wire does not need a margin note. */
	border-inline-start: 0;
	padding-inline-start: var(--l-gutter);
}

[dir="ltr"] .athar-scope .lamba-wire {
	--wire-from: to right;
	--wire-root: left;
}

.athar-scope .lamba-wire__line {
	margin: 0;
	max-inline-size: 22ch;
	font-family: var(--l-display);
	font-size: var(--l-t-display);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	/* Looser than the display leading. Two lines of this size set at 1.14 sit
	   on top of each other, and this is a sentence to be walked through, not a
	   headline to be taken in at once. */
	line-height: 1.34;
	text-wrap: balance;

	/* Three stops that move together: what the light has passed, the point it
	   is at, and what it has not reached. */
	background-image: linear-gradient(
		var(--wire-from),
		var(--l-text) 0%,
		var(--l-text) calc(var(--p) * 100% - 5%),
		var(--l-yellow) calc(var(--p) * 100%),
		var(--l-quiet) calc(var(--p) * 100% + 6%),
		var(--l-quiet) 100%
	);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}

/* Safari once needed the prefixed pair to keep the text visible at all; if a
   browser ever fails the clip, this keeps the words readable rather than
   invisible. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
	.athar-scope .lamba-wire__line {
		background-image: none;
		color: var(--l-text);
	}
}

.lamba-wire__run {
	position: relative;
	display: flex;
	align-items: center;
	/* Out to the screen's edges from inside whatever column holds it, the same
	   arithmetic Athar's own full-bleed uses. */
	margin-inline: calc(50% - var(--athar-vw, 100vw) / 2);
	inline-size: var(--athar-vw, 100vw);
	margin-block-start: clamp(1.75rem, 5vh, 3.25rem);
}

/* Half the screen, not all of it. The lamp sits at the end of the cord, and
   the end of the cord is now the middle of the page — so the whole run lands
   under the words above it instead of trailing the lamp off to the far edge,
   where it read as something that had come loose rather than as the thing the
   sentence arrives at. */
.lamba-wire__cord {
	position: relative;
	flex: 0 1 auto;
	inline-size: calc(50% - clamp(1.6rem, 3.5vw, 3rem));
	block-size: 1px;
	background: var(--l-rule);
}

/* The live length of it. A scale rather than a width: it stays on the
   compositor, and a hairline that animates its width shimmers. */
.lamba-wire__cord::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--l-yellow);
	box-shadow: 0 0 14px rgb(246 208 13 / 0.55);
	transform: scaleX(var(--p));
	transform-origin: var(--wire-root);
}

.lamba-wire__lamp {
	flex: 0 0 auto;
	display: block;
	padding-inline-start: clamp(0.6rem, 2vw, 1.25rem);
	/* It comes on at the end of the run, not gradually along it: a lamp is on
	   or it is off. */
	opacity: calc(0.18 + clamp(0, (var(--p) - 0.82) * 5.6, 1) * 0.82);
	transition: opacity var(--l-dur-1) var(--l-ease);
}

.lamba-wire__lamp .lamba-mark {
	inline-size: clamp(2.6rem, 5vw, 4rem);
}

/* The attribution, when there is one, sits under the words and not under the
   wire — the wire is the end of the section. */
.athar-scope .lamba-wire .athar-quote__by {
	order: -1;
	margin-block-start: 1.1em;
	color: var(--l-faint);
}

/* ===================================================================== sign

   The slogan, switching on.

   «بس شغّلها» — just turn it on. It was set as a large centred line, which is
   the one thing the sentence asks it not to be. Now it strikes: dark until the
   section arrives, then the catch a tube light has before it holds — up, dip,
   up, steady. The same shape as the card strike and the same shape as a real
   lamp, which is why it reads as switching on rather than as fading in.

   Gated on .lamp-js, because a sign that never receives its class must not be
   left dark: with no script the line is simply lit.
   ======================================================================= */

.lamp-js .athar-scope .lamba-marquee:not(.is-in) .lamba-marquee__line {
	color: rgb(237 237 233 / 0.14);
	text-shadow: none;
}

.lamp-js .athar-scope .lamba-marquee.is-in .lamba-marquee__line {
	animation: lamba-sign 1.1s var(--l-ease) both;
}

@keyframes lamba-sign {
	0%   { color: rgb(237 237 233 / 0.14); text-shadow: none; }
	9%   { color: var(--l-text); text-shadow: 0 0 28px rgb(246 208 13 / 0.55); }
	14%  { color: rgb(237 237 233 / 0.22); text-shadow: none; }
	21%  { color: var(--l-text); text-shadow: 0 0 34px rgb(246 208 13 / 0.6); }
	27%  { color: rgb(237 237 233 / 0.4); text-shadow: none; }
	38%  { color: var(--l-text); text-shadow: 0 0 30px rgb(246 208 13 / 0.5); }
	100% { color: var(--l-text); text-shadow: 0 0 20px rgb(246 208 13 / 0.3); }
}

/* ==================================================== Athar: quiet the rest

   Types this site does not redraw still have to belong to it. */

.athar-scope .athar-text h2,
.athar-scope .athar-text h3,
.athar-scope .athar-split__heading {
	font-family: var(--l-display);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
}

.athar-scope .athar-quote {
	max-inline-size: var(--athar-measure-wide);
	font-family: var(--l-display);
	font-size: var(--l-t-h2);
	font-weight: var(--l-w-body);
	line-height: var(--l-lh-display);
	text-wrap: pretty;
}

.athar-scope .athar-image img,
.athar-scope .athar-split img,
.athar-scope .athar-gallery img {
	border-radius: var(--l-radius);
	filter: var(--l-photo);
}

/* ============================================================= case study

   The still first and edge to edge, then the name against a row of facts.
   Everything below is composed in the studio, so this file stops here.
   ======================================================================= */

/* The cover starts at the top of the page, and the header floats on it.
 *
 * The header is `position: sticky`, which means it is still *in flow*: its lift,
 * its own height and the gap it leaves under itself added up to about 137px of
 * page above the picture — a dark band on every project, with the cover
 * beginning below it. Saad: «دايم فيه مساحة فوق ضايعة، أحتاج الغلاف يبدأ من
 * بداية الصفحة».
 *
 * Fixed instead of sticky, on this template only. It behaves the same on the
 * screen — pinned to the top through the whole scroll — and occupies no flow, so
 * `main` starts at zero and the picture starts with it. The veil across the top
 * of the hero is already dark enough to carry the capsule, which is what it was
 * drawn for.
 *
 * Scoped with `:has()` so a project with no cover keeps the header in flow. Take
 * it out of flow there and the title slides underneath it — nothing to overlap
 * is not an overlap, it is a collision. */
body.single-lamba_project:has( .case-hero ) .site-head,
body.page:has( .case-hero ) .site-head {
	position: fixed;
	inset-inline: 0;
	margin-block-end: 0;
}

.case-hero {
	position: relative;
	/* Out to the viewport edges from inside whatever column holds it, the same
	   arithmetic Athar's own full-bleed uses. --athar-vw is the viewport minus
	   its scrollbar; 100vw includes the scrollbar and overflows by ~15px. */
	margin-inline: calc(50% - var(--athar-vw, 100vw) / 2);
	inline-size: var(--athar-vw, 100vw);
	block-size: min(72vh, 44rem);
	overflow: hidden;
	background: var(--l-black);
}

.case-hero__img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	filter: var(--l-photo);
}

/* The type below has to survive whatever the still happens to be. */
.case-hero__veil {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to bottom,
		rgb(28 28 26 / 0.45) 0%,
		rgb(28 28 26 / 0.1) 40%,
		rgb(28 28 26 / 0.92) 100%
	);
}

.case-head {
	position: relative;
	z-index: 1;
	margin-block-start: var(--l-rhythm-tight);
}

/* Only a head that actually has a still above it climbs into it. Without the
   guard a project with no thumbnail pulled its own title up under the sticky
   header, which is not a hero overlap, it is a collision. */
.case-head--under {
	margin-block-start: calc(var(--l-rhythm) * -0.35);
}

/* The project title when the story opens with its own cover: still the page's
   one <h1> for a screen reader and for search, just not drawn twice. */
.case-title--quiet {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.case-title {
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--l-t-display);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-hero);
	line-height: var(--l-lh-display);
	text-wrap: balance;
}

/* The line under the name.
 *
 * Bigger than the body and quieter than the title, held to a reading measure
 * and aligned with everything else in the header — it is the sentence that says
 * what this project was, not the first paragraph of what was done. That one is
 * «الفكرة», and it starts below. */
.case-deck {
	max-inline-size: 46ch;
	margin-block: 0.7em 0;
	font-size: var(--l-t-h3);
	line-height: var(--l-lh-body);
	color: var(--l-quiet);
	text-wrap: pretty;
}

.case-facts {
	display: grid;
	gap: var(--l-rhythm-tight);
	grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
	margin-block: var(--l-rhythm-tight) 0;
	padding-block-start: var(--l-rhythm-tight);
}

.case-fact__label {
	font-size: var(--l-t-meta);
	letter-spacing: var(--l-track-meta);
	text-transform: uppercase;
	color: var(--l-yellow);
}

.case-fact__value {
	margin: 0.5em 0 0;
	font-size: var(--l-t-small);
	color: var(--l-quiet);
}

/* ============================================== this site's own sections */

/* One sentence, edge to edge, and the light passing across it. */
.athar-scope .lamba-marquee {
	padding-block: var(--l-rhythm);
	padding-inline: var(--l-gutter);
	text-align: center;
}

.athar-scope .lamba-marquee__line {
	max-inline-size: 20ch;
	margin-inline: auto;
	margin-block: 0;
	font-family: var(--l-display);
	font-size: var(--l-t-display);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-display);
	text-wrap: balance;
}

/* The client wall. 38 white-on-transparent logos: they need no treatment on
   this ground beyond being held back until they are looked at. */
.athar-scope .lamba-clients {
	padding-block: var(--l-rhythm);
}

/* Held to the column even when the section is set to bleed.
 *
 * Athar lets each section pick its own width, and this one at full bleed puts
 * the marks past both edges of the screen while «شركاء النجاح» above them stays
 * on the column — so the heading reads as belonging to a different page than
 * the wall under it. Saad: «خلّه يأخذ نفس الأبعاد اللي فوق في من نحن».
 *
 * Same override, and the same reasoning, as athar-align-wide gets further up
 * this file: the width of a block is Athar's setting to offer, and how this
 * site's own blocks sit on this site's own column is the theme's to decide. */
.athar-scope .lamba-clients.athar-align-full {
	margin-inline: 0;
	inline-size: 100%;
	max-inline-size: 100%;
}

/* Closer together, at Saad's asking. The old air was a quarter of the row's
   height between one mark and the next, which reads as thirty-seven separate
   things rather than one wall of them — and a wall is the point: no single
   logo here is being shown, the length of the list is. */
.athar-scope .lamba-clients__grid {
	display: grid;
	gap: clamp(1rem, 2vw, 1.75rem) clamp(0.75rem, 1.5vw, 1.25rem);
	grid-template-columns: repeat(auto-fill, minmax(min(8rem, 40%), 1fr));
}

/* No cell. The wall used to be boxes on a one-pixel grid, which is a table
   of logos; thirty-seven marks with air around them is a wall.

   A tile was tried here on 2026-08-29 and taken straight back out: it is the
   same table of boxes by another name, and the air is what makes this a wall.
   The dark ground that was wanted belongs on the settings screen, where white
   logos on a near-white surface really are invisible — assets/css/admin.css
   has it. */
.athar-scope .lamba-clients__cell {
	display: grid;
	place-items: center;
	block-size: clamp(2.6rem, 5vw, 3.6rem);
}

/* Their logos arrive white on transparent, so they need no treatment at all
   beyond being held back until they are looked at — which is the same thing
   the project cards do, and the same thing the whole site is about. A logo
   sitting at half strength on this ground is not dim, it is waiting. */
.athar-scope .lamba-clients__cell img {
	max-block-size: 100%;
	max-inline-size: 100%;
	inline-size: auto;
	block-size: auto;
	object-fit: contain;
	opacity: calc(0.24 + var(--lit) * 0.24);
	transition:
		opacity var(--l-dur-1) var(--l-ease),
		filter var(--l-dur-1) var(--l-ease);
}

.athar-scope .lamba-clients__cell:hover img {
	opacity: 1;
	/* The catch a lamp has before it holds, at logo scale. */
	filter: drop-shadow(0 0 12px rgb(246 208 13 / 0.35));
}

/* On a phone the wall was the longest thing on the page. Two columns of 8rem
   cells with 3.5rem of air stacked their thirty-seven logos into eighteen rows
   — over a thousand pixels of scrolling to get past a list of names.

   Three columns and a third of the air. The air still separates one logo from
   the next, because nothing else does; it is only no longer set by a scale
   built for a screen four times as wide. */
@media (max-width: 40rem) {
	.athar-scope .lamba-clients__grid {
		grid-template-columns: repeat(3, 1fr);
		gap: 1.1rem 0.9rem;
	}

	.athar-scope .lamba-clients__cell {
		block-size: 2.1rem;
	}
}

/* ===================================================================== reach

   The way in: بياناتهم in the footer, the window over the page, and صفحة
   التواصل. Three places, one set of facts, one markup — `lamba-facts` — so a
   visitor who meets them twice does not have to read them twice.

   The design decision under all of it: this is the quietest part of the site.
   Everything above it lights up, moves or travels; the end of a page states an
   address and a number and stops. The only warm thing down here is a link with
   the cursor on it.
   ======================================================================= */

/* ------------------------------------------------------------- the facts */

.lamba-facts {
	display: grid;
	gap: var(--l-rhythm-tight);
	margin: 0;
	padding: 0;
	list-style: none;
}

.lamba-facts__item {
	display: grid;
	gap: 0.35em;
	align-content: start;
}

/* The label is not a heading. It is the smallest thing on the page, tracked
   wide and held back, because «البريد» is not the information — the address
   after it is. */
.lamba-facts__key {
	font-size: var(--l-t-meta);
	font-weight: var(--l-w-mid);
	letter-spacing: var(--l-track-meta);
	text-transform: uppercase;
	color: var(--l-faint);
}

.lamba-facts__value {
	color: var(--l-text);
	text-decoration: none;
	text-wrap: pretty;
	border-block-end: 1px solid transparent;
	transition:
		color var(--l-dur-1) var(--l-ease),
		border-color var(--l-dur-1) var(--l-ease);
}

/* An address is prose and follows the page; a number and an email address are
   strings and do not. `dir` is printed on the value itself in PHP, and it is
   what stops a string opening with «+» from being dragged back into the
   paragraph's own direction.

   `justify-self` is the other half of that, and without it the fix looks like
   the bug: a grid item fills its track, and a full-width box carrying dir="ltr"
   sets its own text to the left — so on an Arabic page the label sat on the
   right and the number under it sat on the left, a column apart. Shrunk to its
   own text, the box lands at the start of the line and the number sits under
   the word that names it. */
.lamba-facts__value[dir="ltr"] {
	justify-self: start;
	font-variant-numeric: tabular-nums;
}

a.lamba-facts__value:hover,
a.lamba-facts__value:focus-visible {
	color: var(--l-yellow);
	border-block-end-color: var(--l-yellow);
}

/* Side by side wherever there is room, and there is room in the footer and on
   صفحة التواصل — both of them the full column. Four short facts stacked down a
   wide page is a list of loose ends.

   Not in the window. The panel is 42rem, the address is three times the length
   of the number beside it, and three columns in that space leaves one fact
   dropped onto a second row on its own. Stacked, they read as a list, which is
   what they are. */
@media (min-width: 46rem) {
	.lamba-facts--foot,
	.lamba-contact--page .lamba-facts--panel {
		grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
		gap: var(--l-gutter);
	}
}

.lamba-modal .lamba-facts {
	gap: 1.1rem;
}

/* --------------------------------------------------------- their accounts */

.lamba-social {
	display: flex;
	flex-wrap: wrap;
	gap: clamp(0.9rem, 2.2vw, 1.8rem);
	margin: var(--l-rhythm-tight) 0 0;
	padding: 0;
	list-style: none;
	font-size: var(--l-t-small);
}

.lamba-social__link {
	color: var(--l-quiet);
	text-decoration: none;
	border-block-end: 1px solid var(--l-rule);
	transition:
		color var(--l-dur-1) var(--l-ease),
		border-color var(--l-dur-1) var(--l-ease);
}

.lamba-social__link:hover,
.lamba-social__link:focus-visible {
	color: var(--l-text);
	border-block-end-color: var(--l-yellow);
}

/* ------------------------------------------------------------- the footer */

.site-foot__contact {
	display: grid;
	gap: var(--l-rhythm-tight);
	padding-block-end: var(--l-rhythm-tight);
	margin-block-end: var(--l-rhythm-tight);
	border-block-end: 1px solid var(--l-rule-soft);
}

@media (min-width: 60rem) {
	.site-foot__contact {
		grid-template-columns: auto 1fr;
		gap: var(--l-gutter);
		align-items: start;
	}
}

.site-foot__sign {
	display: flex;
	align-items: center;
	gap: 0.7em;
	color: var(--l-text);
}

/* Small. The circle is their prime identifier and it is already the first
   thing at the top of the page; down here it is a signature, not a mark. */
.site-foot__mark {
	inline-size: 1.9rem;
	block-size: 1.9rem;
	flex: none;
}

.site-foot__name {
	font-family: var(--l-display);
	font-weight: var(--l-w-display);
	font-size: var(--l-t-h3);
	letter-spacing: var(--l-track-display);
}

.site-foot__note {
	margin-block: var(--l-rhythm-tight) 0;
	font-size: var(--l-t-meta);
	letter-spacing: 0.04em;
	color: var(--l-faint);
}

/* ==================================================================== window

   The contact window.

   A real <dialog>, so the backdrop, Escape, the focus trap and the inert page
   behind it are the browser's job and not lamp.js's. Three things have to be
   undone before it can be styled at all: a dialog ships with a border, a
   background and a max-height, and all three fight a full-screen shell.

   The panel is a lifted surface in a dark room — the same one the cards sit on
   — and it carries its own grain, because the top layer is above the page's
   grain sheet and «قرينت فوق كل شيء» is not a preference.
   ======================================================================= */

.lamba-modal {
	inline-size: 100%;
	max-inline-size: 100%;
	block-size: 100%;
	max-block-size: 100%;
	margin: 0;
	padding: var(--l-gutter);
	border: 0;
	background: transparent;
	color: var(--l-text);
	overflow: auto;
	overscroll-behavior: contain;
}

.lamba-modal:not([open]) {
	display: none;
}

.lamba-modal[open] {
	display: grid;
	place-items: center;
}

/* True black, like the gate. The room is #1c1c1a, and a backdrop that only
   matches the room does not read as being behind anything. */
.lamba-modal::backdrop {
	background: rgb(0 0 0 / 0.72);
	backdrop-filter: blur(6px);
}

.lamba-modal__panel {
	position: relative;
	inline-size: min(100%, 42rem);
	padding: clamp(1.6rem, 4vw, 2.8rem);
	border: 1px solid var(--l-rule);
	border-radius: var(--l-radius);
	background: var(--l-raise);
	box-shadow: 0 40px 120px -30px rgb(0 0 0 / 0.9);
	overflow: hidden;
}

/* Focus lands here when the window opens, so the reader walks in at the top.
   It is a container and not a control, so it says so only to the keyboard. */
.lamba-modal__panel:focus {
	outline: none;
}

.lamba-modal__panel:focus-visible {
	outline: 2px solid var(--l-yellow);
	outline-offset: 3px;
}

/* The grain, inside the panel, at the page's own strength. Inert, and above
   the words exactly as the page-wide sheet is above the page. */
.lamba-modal__grain {
	position: absolute;
	inset: 0;
	z-index: 2;
	pointer-events: none;
	opacity: var(--l-grain-opacity);
	mix-blend-mode: screen;
	background-image: var(--l-grain-image);
	background-size: var(--l-grain-size) var(--l-grain-size);
}

.lamba-modal__body {
	position: relative;
	z-index: 1;
}

.lamba-modal__x {
	position: absolute;
	z-index: 3;
	inset-block-start: 0.6rem;
	inset-inline-end: 0.6rem;
	display: grid;
	place-items: center;
	inline-size: 2.4rem;
	block-size: 2.4rem;
	padding: 0;
	border: 0;
	border-radius: var(--l-radius-pill);
	background: transparent;
	color: var(--l-quiet);
	font-size: 1.5rem;
	line-height: 1;
	cursor: pointer;
	transition:
		color var(--l-dur-1) var(--l-ease),
		background var(--l-dur-1) var(--l-ease);
}

.lamba-modal__x:hover,
.lamba-modal__x:focus-visible {
	background: var(--l-raise-2);
	color: var(--l-text);
}

/* It arrives. Under reduced motion it is simply there — a window that
   assembles itself in front of somebody who asked for less motion is the one
   place the request matters most. */
@media (prefers-reduced-motion: no-preference) {
	.lamba-modal[open] .lamba-modal__panel {
		animation: lamba-modal-in var(--l-dur-2) var(--l-ease) both;
	}

	.lamba-modal[open]::backdrop {
		animation: lamba-fade-in var(--l-dur-2) var(--l-ease) both;
	}
}

@keyframes lamba-modal-in {
	from {
		opacity: 0;
		translate: 0 12px;
		scale: 0.985;
	}
}

@keyframes lamba-fade-in {
	from {
		opacity: 0;
	}
}

/* -------------------------------------------------- what is inside either */

.lamba-contact__head {
	/* The close button's corner. Without this the heading runs under it on a
	   narrow window, and the two overlap at exactly the width nobody tests. */
	padding-inline-end: 2.4rem;
}

.lamba-contact__heading {
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--l-t-h1);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
	text-wrap: balance;
}

.lamba-contact__text {
	margin-block: 0.75rem 0;
	color: var(--l-quiet);
	text-wrap: pretty;
}

.lamba-contact__form {
	margin-block-start: var(--l-rhythm-tight);
}

/* The facts under a form are a footnote to it, not a second offer. */
.lamba-contact__form ~ .lamba-facts {
	margin-block-start: var(--l-rhythm-tight);
	padding-block-start: var(--l-rhythm-tight);
	border-block-start: 1px solid var(--l-rule-soft);
	font-size: var(--l-t-small);
}

.lamba-contact__head + .lamba-facts,
.lamba-contact__head + .lamba-social {
	margin-block-start: var(--l-rhythm-tight);
}

/* --------------------------------------------------------------- the page */

.athar-scope .lamba-contact--page {
	padding-block: var(--l-rhythm);
}

.athar-scope .lamba-contact--page .lamba-contact__inner {
	max-inline-size: var(--l-col-narrow);
	margin-inline: auto;
}

/* No close button on the page, so nothing to clear. */
.athar-scope .lamba-contact--page .lamba-contact__head {
	padding-inline-end: 0;
}

.athar-scope .lamba-contact--page .lamba-contact__heading {
	font-size: var(--l-t-display);
	line-height: var(--l-lh-display);
}

.lamba-contact-page__intro {
	padding-block-start: var(--l-rhythm-tight);
}

/* ==================================================== somebody else's form

   Everything below is in the athar layer, and that is the entire point.

   The form belongs to a plugin. Its markup is unknown, its class names are
   unknown, and whether it brings a stylesheet at all is unknown. Unlayered
   rules beat layered ones whatever the source order, so a plugin that dresses
   its own fields wins every rule here without knowing they exist — and a
   plugin that offers to inherit the site's type gets it, because with nothing
   of its own to win with, these are what is left standing.

   So this is a floor, not a design: readable fields in the site's face, on the
   site's ground, at the site's corner radius. Anything more opinionated would
   be this theme styling somebody else's component.
   ======================================================================= */

@layer athar {
	.lamba-contact__form :is(input, textarea, select, button) {
		font: inherit;
		font-family: var(--l-font);
		color: inherit;
	}

	.lamba-contact__form :is(
		input[type="text"],
		input[type="email"],
		input[type="tel"],
		input[type="url"],
		input[type="number"],
		input[type="search"],
		input[type="date"],
		textarea,
		select
	) {
		inline-size: 100%;
		padding: 0.7em 0.9em;
		border: 1px solid var(--l-rule);
		border-radius: var(--l-radius-s);
		background: var(--l-ground);
		color: var(--l-text);
		transition:
			border-color var(--l-dur-1) var(--l-ease),
			box-shadow var(--l-dur-1) var(--l-ease);
	}

	.lamba-contact__form :is(input, textarea, select):focus {
		outline: none;
		border-color: var(--l-yellow);
		box-shadow: 0 0 0 3px rgb(246 208 13 / 0.18);
	}

	.lamba-contact__form textarea {
		min-block-size: 7rem;
		resize: vertical;
	}

	.lamba-contact__form label {
		display: block;
		margin-block-end: 0.35em;
		font-size: var(--l-t-small);
		color: var(--l-quiet);
	}

	.lamba-contact__form :is(p, .form-row, .field) {
		margin-block: 0 var(--l-rhythm-tight);
	}

	/* Their button, the same pill the call to action uses, because a form
	   inside this site should end the way everything else in it ends. */
	.lamba-contact__form :is(button, input[type="submit"]) {
		padding: 0.75em 1.5em;
		border: 0;
		border-radius: var(--l-radius-pill);
		background: var(--l-yellow);
		color: var(--l-black);
		font-weight: var(--l-w-mid);
		cursor: pointer;
		transition: box-shadow var(--l-dur-2) var(--l-ease);
	}

	.lamba-contact__form :is(button, input[type="submit"]):hover {
		box-shadow: 0 0 34px -4px rgb(246 208 13 / 0.55);
	}
}

/* ================================================================ the case

   دراسة الحالة: the six blocks a project's body is written in.

   Everything here is laid out on the site's own rhythm rather than on a grid
   of its own, so a case study reads as the same site as the page that linked
   to it. The blocks differ in what they hold and not in how they sit.
   ======================================================================= */

.lamba-case {
	display: flex;
	flex-direction: column;
	gap: var(--l-rhythm);
	margin-block: var(--l-rhythm);
}

.lamba-block {
	margin: 0;
	max-inline-size: var(--l-col-narrow);
	margin-inline: auto;
	inline-size: 100%;
}

/* Wide and full are the two ways out of the reading column, and they are the
   same arithmetic the sections on the front page use: half the column minus
   half the target, mirrored. `--athar-vw` is the viewport minus the scrollbar,
   measured once; without it a full-bleed block overhangs the page by the width
   of the scrollbar. */
.lamba-block--wide {
	max-inline-size: var(--l-col);
}

.lamba-block--full {
	max-inline-size: none;
	inline-size: var(--athar-vw, 100vw);
	margin-inline: calc(50% - var(--athar-vw, 100vw) / 2);
}

.lamba-block__img {
	display: block;
	inline-size: 100%;
	block-size: auto;
	border-radius: var(--l-radius);
	filter: var(--l-photo);
}

.lamba-block--full .lamba-block__img {
	border-radius: 0;
}

/* A caption is a footnote to the thing above it, not a second heading. */
.lamba-block__cap {
	margin-block-start: 0.9rem;
	font-size: var(--l-t-small);
	color: var(--l-quiet);
	text-wrap: pretty;
}

.lamba-block--full .lamba-block__cap {
	max-inline-size: var(--l-col-narrow);
	margin-inline: auto;
	padding-inline: var(--l-gutter);
}

.lamba-block__heading {
	margin: 0 0 var(--l-rhythm-tight);
	font-family: var(--l-display);
	font-size: var(--l-t-h2);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
	text-wrap: balance;
}

.lamba-block__prose > :first-child {
	margin-block-start: 0;
}

.lamba-block__prose > :last-child {
	margin-block-end: 0;
}

.lamba-block__prose p {
	margin-block: 0 1em;
	color: var(--l-quiet);
	text-wrap: pretty;
}

/* The opening paragraph, once per case study. Bigger and in the page's own ink
   rather than the quiet grey: it is the sentence the reader arrives on. */
.lamba-block--lead .lamba-block__prose p {
	font-size: var(--l-t-h3);
	line-height: var(--l-lh-head);
	color: var(--l-text);
}

/* ------------------------------------------------------ beside each other

   One rule lays out both the picture-and-words block and the film-and-words
   block, because they are the same layout and only the media differs. The
   sides are logical, so `start` is the reading start and the whole thing
   mirrors in English with nothing to override. */

.lamba-block--split {
	display: grid;
	gap: var(--l-rhythm-tight) var(--l-gutter);
	align-items: center;
}

@media (min-width: 52rem) {
	.lamba-block--split {
		grid-template-columns: 1fr 1fr;
	}

	.lamba-split--end .lamba-split__media {
		order: 2;
	}
}

.lamba-split__media .lamba-block__img {
	border-radius: var(--l-radius);
}

/* --------------------------------------------------------------- the film

   The frame holds the aspect, and whatever is inside it — a provider's iframe
   or the site's own <video> — fills it. Stating the ratio on the frame rather
   than on the media is what lets one rule cover both: an oEmbed iframe arrives
   with its own width and height attributes, and a <video> arrives with none.
   ==================================================================== */

.lamba-film__frame {
	position: relative;
	inline-size: 100%;
	overflow: hidden;
	border-radius: var(--l-radius);
	background: var(--l-black);
}

.lamba-film--16-9 {
	aspect-ratio: 16 / 9;
}

.lamba-film--vertical {
	aspect-ratio: 9 / 16;
	max-inline-size: 26rem;
	margin-inline: auto;
}

.lamba-film--square {
	aspect-ratio: 1 / 1;
}

.lamba-film__frame > iframe,
.lamba-film__frame > video,
.lamba-film__frame .lamba-film {
	position: absolute;
	inset: 0;
	inline-size: 100%;
	block-size: 100%;
	border: 0;
	object-fit: cover;
}

.lamba-block--full .lamba-film__frame {
	border-radius: 0;
}

/* -------------------------------------------------------------- the album */

.lamba-album__grid {
	display: grid;
	gap: clamp(0.5rem, 1.4vw, 1rem);
	grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 46rem) {
	.lamba-album--of-3 .lamba-album__grid {
		grid-template-columns: repeat(3, 1fr);
	}

	.lamba-album--of-4 .lamba-album__grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

.lamba-album__cell {
	display: block;
	overflow: hidden;
	border-radius: var(--l-radius-s);
}

.lamba-album__img {
	display: block;
	inline-size: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	filter: var(--l-photo);
	transition: scale var(--l-dur-2) var(--l-ease);
}

/* An album cell still comes forward when it is looked at. The project cards
   no longer do — lighting one lights it and moves nothing — but these are a
   different thing: a contact sheet inside a case study, where the swell is how
   one frame is picked out of a wall of them rather than a lamp coming on. */
.lamba-album__cell:hover .lamba-album__img {
	scale: 1.03;
}

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

   أعمدة: two to four things side by side, each with a badge, a name and a
   line. لمة لمبة — إبداع، شغل، مجتمع — is three of these, and it is why the
   block exists. A page's block, never a project's.

   Two grounds. On the room it is a list on the dark, like everything else
   here. On the yellow band it is a section that is *on*: solid brand yellow
   from edge to edge, the type turned black, and the badges astride the
   band's top edge — half on the dark, half on the yellow — which is the one
   detail of their own layout worth keeping exactly. The band is a surface
   and not a glow, so it is the one warm plane this site allows itself:
   nothing translucent, nothing stacked, the same rule that took the bloom
   out of the gate. */

.lamba-cols {
	--cols-badge: clamp(5.5rem, 9vw, 7.5rem);
}

/* The heading and its line stay on the dark above the band either way, held
   to the reading column, so the band holds the things and nothing else. */
.lamba-cols__head {
	max-inline-size: var(--l-col-narrow);
	margin-block-end: var(--l-rhythm-tight);
}

.lamba-block--full .lamba-cols__head {
	margin-inline: auto;
	padding-inline: var(--l-gutter);
}

.lamba-cols__intro {
	max-inline-size: 46ch;
	font-size: var(--l-t-h3);
	line-height: var(--l-lh-body);
	text-wrap: pretty;
}

.lamba-cols__intro p {
	margin-block: 0 1em;
	color: var(--l-quiet);
}

.lamba-cols__intro > :last-child {
	margin-block-end: 0;
}

.lamba-cols__grid {
	display: grid;
	gap: var(--l-rhythm-tight) var(--l-gutter);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 40rem) {
	.lamba-cols__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 60rem) {
	.lamba-cols--of-3 .lamba-cols__grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.lamba-cols--of-4 .lamba-cols__grid {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

.lamba-cols__item {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1rem;
	min-inline-size: 0;
}

/* The badge, with the artwork held inside it and air around, because what goes
   in here is a mark and a mark needs its clear space.

   Four shapes, and the editor picks (2026-09-07). The size, the padding and
   the ring are one set of rules; only the corner changes, so a badge cannot
   become a different object by being square. `--cols-badge-bg` is the
   editor's colour when there is one, and the two automatic answers below are
   the fallback in the same declaration — white on a band, the room's own
   raised grey on the dark. */
.lamba-cols__badge {
	display: grid;
	place-items: center;
	inline-size: var(--cols-badge);
	block-size: var(--cols-badge);
	padding: calc(var(--cols-badge) * 0.17);
	border-radius: 50%;
	background: var(--cols-badge-bg, var(--l-raise));
	box-shadow: 0 0 0 1px var(--l-rule);
	overflow: hidden;
}

.lamba-cols--square .lamba-cols__badge {
	border-radius: 0;
}

.lamba-cols--soft .lamba-cols__badge {
	border-radius: calc(var(--cols-badge) * 0.22);
}

/* The slanted corners. clip-path rather than four gradients, so the shape is
   stated once and the artwork inside is clipped by it too.

   It clips the element's own paint, which takes the ring and the drop shadow
   with it — so this shape draws neither as a box-shadow. The shadow comes
   back as a filter on the row below, because a filter follows the clip
   instead of being cut by it. */
.lamba-cols--cut .lamba-cols__badge {
	border-radius: 0;
	box-shadow: none;
	--cut: calc(var(--cols-badge) * 0.24);
	clip-path: polygon(
		var(--cut) 0, calc(100% - var(--cut)) 0,
		100% var(--cut), 100% calc(100% - var(--cut)),
		calc(100% - var(--cut)) 100%, var(--cut) 100%,
		0 calc(100% - var(--cut)), 0 var(--cut)
	);
}

.lamba-cols__mark {
	inline-size: 100%;
	block-size: 100%;
	object-fit: contain;
}

/* The name, and the rule that runs from it to the end of the column: the
   line their own layout draws beside every heading, drawn once here. It is
   the yellow on the dark and the black on the yellow — the one colour the
   ground is not. */
.lamba-cols__title {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	inline-size: 100%;
	margin: 0;
	font-family: var(--l-display);
	font-size: var(--l-t-h3);
	font-weight: var(--l-w-display);
	letter-spacing: var(--l-track-display);
	line-height: var(--l-lh-head);
}

.lamba-cols__title > span {
	flex: 0 1 auto;
	min-inline-size: 0;
}

.lamba-cols__title::after {
	content: "";
	flex: 1 1 0;
	min-inline-size: 1.5rem;
	block-size: 2px;
	background: var(--l-yellow);
	opacity: calc(0.4 + var(--lit) * 0.6);
}

.lamba-cols__body {
	max-inline-size: 36ch;
}

.lamba-cols__body p {
	font-size: var(--l-t-body);
}

/* The bold runs in their own copy — «تجمع المبدعين من كل المجالات» — are the
   half of the sentence that carries it, so they come up to the page's ink. */
.lamba-cols__body strong {
	color: var(--l-text);
	font-weight: var(--l-w-mid);
}

/* ------------------------------------------------------- the yellow band

   The badges stand astride the band's top edge — half on the dark, half on
   the yellow — and that only means anything **while all of them are in one
   row**. Stacked, the same pull drags every badge but the first up into the
   paragraph above it, which is what it did: measured on a 375px screen, the
   second badge overlapped the first column's text by 88 pixels.

   So `--astride` is 0 or 1 and the three measurements below are written in
   terms of it: the band's top margin opens the room, its top padding puts the
   content back where it belongs, and the badge's negative margin lifts it by
   the padding plus half of itself. At 0 all three collapse to nothing and the
   band is an ordinary band with the badges inside it, which is the honest
   shape for a column stack. The media queries only ever flip the number, and
   they flip it exactly where the grid stops wrapping. */

.lamba-cols--lit {
	--astride: 0;
	--band-pad: clamp(2.5rem, 5vw, 4rem);
}

@media (min-width: 40rem) {
	.lamba-cols--lit.lamba-cols--of-2 {
		--astride: 1;
	}
}

@media (min-width: 60rem) {
	.lamba-cols--lit.lamba-cols--of-3,
	.lamba-cols--lit.lamba-cols--of-4 {
		--astride: 1;
	}
}

.lamba-cols--lit .lamba-cols__band {
	margin-block-start: calc(var(--astride) * var(--cols-badge) / 2);
	padding-block: calc(var(--band-pad) + var(--astride) * var(--cols-badge) / 2) var(--band-pad);
	background: var(--cols-ground, var(--l-yellow));
	color: var(--cols-ink);
}

/* The ink the band carries, worked out from the band itself in PHP — see
   lamba_is_pale(). A pale band takes black type; a deep one keeps the page's
   own. Two classes rather than one so the rule reads as the choice it is. */
.lamba-cols--pale {
	--cols-ink: var(--l-black);
	--cols-rule: var(--l-black);
	--cols-quiet: rgb(0 0 0 / 0.78);
}

.lamba-cols--deep {
	--cols-ink: var(--l-text);
	--cols-rule: var(--l-yellow);
	--cols-quiet: var(--l-quiet);
}

.lamba-cols--lit .lamba-cols__grid {
	max-inline-size: var(--l-col);
	margin-inline: auto;
	padding-inline: var(--l-gutter);
}

.lamba-cols--lit .lamba-cols__badge {
	margin-block-start: calc(var(--astride) * -1 * (var(--band-pad) + var(--cols-badge)));
	background: var(--cols-badge-bg, var(--l-white));
	box-shadow: 0 12px 32px -14px rgb(0 0 0 / 0.45);
}

/* Clipped, so the shadow has to be a filter or it is cut off with the
   corners. Same shadow, drawn where clip-path cannot reach it. */
.lamba-cols--lit.lamba-cols--cut .lamba-cols__badge {
	box-shadow: none;
	filter: drop-shadow(0 10px 14px rgb(0 0 0 / 0.35));
}

.lamba-cols--lit .lamba-cols__title::after {
	background: var(--cols-rule);
	opacity: 1;
}

.lamba-cols--lit .lamba-cols__body p {
	color: var(--cols-quiet);
}

.lamba-cols--lit .lamba-cols__body strong {
	color: var(--cols-ink);
}

/* --------------------------------------------- the numbers and the ask

   Both print the front page's own markup under an `athar-scope` of their
   own, so the rules that draw them there draw them here. What changes is
   only what the case's rhythm already supplies: the ask's padding, which in
   the run of blocks would be a rhythm on top of a rhythm. */

.lamba-block--cta .lamba-cta {
	padding-block: 0;
}

/* ------------------------------------------------- the facts, and the head */

.case-fact__value a {
	color: inherit;
	text-decoration: none;
	border-block-end: 1px solid var(--l-rule);
	transition:
		color var(--l-dur-1) var(--l-ease),
		border-color var(--l-dur-1) var(--l-ease);
}

.case-fact__value a:hover,
.case-fact__value a:focus-visible {
	color: var(--l-yellow);
	border-block-end-color: var(--l-yellow);
}

.case-fact__sep {
	color: var(--l-faint);
}

.lamba-archive__kind {
	margin: 0 0 0.4rem;
	font-size: var(--l-t-meta);
	font-weight: var(--l-w-mid);
	letter-spacing: var(--l-track-meta);
	text-transform: uppercase;
	color: var(--l-faint);
}

.lamba-archive__desc {
	margin-block-start: var(--l-rhythm-tight);
	max-inline-size: var(--l-col-narrow);
	color: var(--l-quiet);
}

/* ---------------------------------------------------------- the English

   Capitals on the lines the brand sets in capitals — the slogan, the
   headings, the buttons — and sentence case for everything a reader has to
   read at length. The four `[dir="ltr"]` rules above already answer the
   direction; these only answer the dress.

   The gate swaps its two lines in English: the big line is the English and
   the small line under it is the Arabic «بس شغّلها», so the small line's
   Latin dress — capitals, tracking — comes off it there and it is set a size
   up, because Arabic at meta size is a squint. */

html:lang(en) .athar-cover__heading,
html:lang(en) .lamba-marquee__line,
html:lang(en) .athar-text__heading,
html:lang(en) .athar-work__heading,
html:lang(en) .athar-features__heading,
html:lang(en) .lamba-cta__heading,
html:lang(en) .case-title,
html:lang(en) .lamba-block__heading,
html:lang(en) .gate__slogan {
	text-transform: uppercase;
}

html:lang(en) .athar-cover__heading,
html:lang(en) .athar-text__heading,
html:lang(en) .athar-work__heading,
html:lang(en) .athar-features__heading,
html:lang(en) .lamba-cta__heading,
html:lang(en) .case-title,
html:lang(en) .lamba-block__heading {
	text-wrap: balance;
}

html:lang(en) .athar-cover__button,
html:lang(en) .lamba-cta__go,
html:lang(en) .athar-work__all,
html:lang(en) .site-burger__label {
	text-transform: uppercase;
	letter-spacing: var(--l-track-meta);
}

html:lang(en) .gate__sub {
	font-size: var(--l-t-small);
	letter-spacing: 0;
	text-transform: none;
	direction: rtl;
}
