/*
 * Sarem global fixed language rail — an indexed station selector.
 *
 * A pale plate bolted to the right edge of the viewport rather than a card floating
 * near it: a hairline scale running down its inner edge, one station per configured
 * language, each carrying its flag and its code. The language being viewed is marked
 * by a solid indicator on the scale; pointing at another station previews an
 * indicator there and swings its full name out to the left.
 *
 * The device is not decoration — a language switcher IS a discrete selector with
 * exactly one active position, so the scale encodes something true about the content.
 *
 * Colour is spent in exactly one place. The rail is drawn entirely in the site's own
 * paper/ink/hairline values, and the brand yellow appears only as the bar marking the
 * active language — a shape, never text, so the one saturated note in the component
 * never has to carry legibility. Everything else earns its separation from value and
 * spacing instead of from colour.
 *
 * Corners are square throughout and the plate is opaque: it reads as a fixture
 * mounted on the frame, not as a translucent overlay laid on top of the page.
 *
 * The code under each flag is always visible. A flag alone does not name a language,
 * and the rail should be readable without pointing at anything; holding the full name
 * back until hover is what lets the plate stay a strip instead of a panel as wide as
 * the longest language name.
 *
 * Everything is scoped under .slang-* and driven by --slang-* tokens. No script:
 * every entry is a real anchor.
 */

.slang-rail {
	--slang-ink: #0B1520;
	/*
	 * Deeper than the site's own muted grey. This label sits on a translucent
	 * material, so it has to clear AA against the glass at its darkest — over a night
	 * photograph or a dark band, not just against paper. The active station is then
	 * separated by weight and by the brand bar rather than by lightness alone.
	 */
	--slang-muted: #414A54;
	--slang-rule: rgba(11, 21, 32, 0.12);
	--slang-brand: #F9C616;

	/*
	 * The material. Frosted rather than solid: a low-alpha white tint over a blurred,
	 * re-saturated backdrop. The saturation boost is what keeps the page's colour
	 * alive under the glass instead of going to grey mush, and the tint is graded —
	 * denser at the screen edge, thinner at the inner edge — so the plate reads as a
	 * piece of glass catching light rather than as a flat translucent rectangle.
	 */
	--slang-glass: linear-gradient( to left, rgba(255, 255, 255, 0.86), rgba(255, 255, 255, 0.7) );

	/* A 3:2 chip — the native ratio of three of the four flags, so they sit uncropped. */
	--slang-w: 30px;
	--slang-h: 20px;
	--slang-gap: 20px;

	--slang-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	--slang-ease: cubic-bezier(0.2, 0.9, 0.3, 1);

	position: fixed;
	right: 0;
	top: 50%;
	transform: translateY(-50%);
	z-index: 9980;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: var(--slang-gap);
	padding: 20px 14px;
	background: var(--slang-glass);
	-webkit-backdrop-filter: blur(18px) saturate(180%);
	backdrop-filter: blur(18px) saturate(180%);
	/* The lit edge: the one boundary the page actually sees, kept bright so the plate
	 * reads as glass with a machined edge rather than as a panel with a border. */
	border-left: 1px solid rgba(255, 255, 255, 0.85);
	/* Cast softly leftward onto the page — wide and faint, never a drop shadow. */
	box-shadow: -14px 0 34px -14px rgba(11, 21, 32, 0.16);
}

/*
 * Without backdrop-filter there is nothing to frost, and the tint alone over raw page
 * content would be unreadable — so those browsers get a near-solid plate with the
 * same hairline and shadow instead.
 */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
	.slang-rail {
		background: rgba(255, 255, 255, 0.96);
	}
}

/* ---- the scale ---- */
/*
 * One continuous hairline down the inner edge of the plate: the scale the stations
 * are indexed against. It runs the full length of the plate rather than stopping at
 * the outer stations — the indicators have to be read as positions ON something.
 */
.slang-rail::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 14px;
	width: 1px;
	background: var(--slang-rule);
	pointer-events: none;
}

/* ---- one station ---- */
.slang-item {
	position: relative;
	display: block;
	width: var(--slang-w);
	text-decoration: none;
}

/*
 * The indicator on the scale: a short hairline stub at rest, a taller inked one for
 * the station being pointed at, and a full-height brand bar for the language being
 * viewed. Its height is the whole signal — nothing else has to move.
 */
.slang-item::before {
	content: "";
	position: absolute;
	top: 50%;
	right: calc(100% + 10px);
	width: 1px;
	height: 10px;
	background: var(--slang-rule);
	transform: translateY(-50%);
	transition: height 0.26s var(--slang-ease), width 0.26s var(--slang-ease), background-color 0.26s var(--slang-ease);
}

.slang-item:hover::before,
.slang-item:focus-visible::before {
	width: 2px;
	height: 22px;
	background: var(--slang-ink);
}

.slang-item--current::before {
	width: 2px;
	height: 100%;
	background: var(--slang-brand);
}

.slang-item--current {
	cursor: default;
}

.slang-item:focus-visible {
	outline: 2px solid var(--slang-ink);
	outline-offset: 4px;
}

/* ---- the flag ---- */
.slang-face {
	display: block;
	width: var(--slang-w);
	height: var(--slang-h);
	object-fit: cover;
	/*
	 * Recessed by opacity alone. Desaturating a flag makes it read as broken rather
	 * than as inactive, so the colour stays and only its presence drops back — which
	 * on a pale ground reads as airy rather than as greyed out.
	 */
	opacity: 0.55;
	transition: opacity 0.26s var(--slang-ease);
	-webkit-user-select: none;
	user-select: none;
}

.slang-item:hover .slang-face,
.slang-item:focus-visible .slang-face,
.slang-item--current .slang-face {
	opacity: 1;
}

/* A language with no flag file: an empty chip, named by its code like the rest. */
.slang-face--blank {
	border: 1px solid var(--slang-rule);
	opacity: 1;
}

/* ---- the code, always under its flag ---- */
.slang-code {
	display: block;
	margin-top: 6px;
	color: var(--slang-muted);
	font-family: var(--slang-mono);
	font-size: 9px;
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.16em;
	text-align: center;
	/* The tracking is applied to the right of the last glyph too; pull it back so the
	 * two characters stay optically centred under the flag. */
	text-indent: 0.16em;
	transition: color 0.26s var(--slang-ease);
}

.slang-item:hover .slang-code,
.slang-item:focus-visible .slang-code,
.slang-item--current .slang-code {
	color: var(--slang-ink);
}

/*
 * The active station also gains weight. Applied to the current language only, never
 * to hover: this state is fixed at page load, so the heavier face cannot cause a
 * glyph-width shift under the pointer.
 */
.slang-item--current .slang-code {
	font-weight: 600;
}

/* ---- the full name, swinging out on demand ---- */
/*
 * Set the way the loader captions its photographs — uppercase mono behind a brand
 * hairline — so the site's pieces of chrome quote each other across light and dark.
 */
.slang-name {
	position: absolute;
	top: calc(var(--slang-h) / 2);
	right: calc(100% + 22px);
	padding: 7px 10px 7px 9px;
	border-left: 2px solid var(--slang-brand);
	/* The same material as the plate, so the name reads as a piece of it swinging out. */
	background: var(--slang-glass);
	-webkit-backdrop-filter: blur(18px) saturate(180%);
	backdrop-filter: blur(18px) saturate(180%);
	box-shadow: 0 6px 24px -6px rgba(11, 21, 32, 0.22);
	color: var(--slang-ink);
	font-family: var(--slang-mono);
	font-size: 10px;
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	white-space: nowrap;
	pointer-events: none;
	opacity: 0;
	transform: translateY(-50%) translateX(8px);
	transition: opacity 0.26s var(--slang-ease), transform 0.26s var(--slang-ease);
}

.slang-item:hover .slang-name,
.slang-item:focus-visible .slang-name {
	opacity: 1;
	transform: translateY(-50%) translateX(0);
}

/* ---- mobile ---- */
/*
 * The rail stays on small screens (the header's own switcher is out of view once the
 * visitor has scrolled), stepping down to a 24x16 chip — still an exact 3:2 frame.
 * The swing-out name is dropped: there is no hover to summon it, and at this width it
 * would cover the page rather than sit beside it. The code still names every station.
 */
@media (max-width: 900px) {
	.slang-rail {
		--slang-w: 24px;
		--slang-h: 16px;
		--slang-gap: 16px;

		padding: 16px 10px;
	}

	.slang-rail::before {
		left: 10px;
	}

	.slang-item::before {
		right: calc(100% + 7px);
	}

	.slang-name {
		display: none;
	}
}

/*
 * Short viewports (landscape phones): the vertical centre is close enough to the
 * floating contact button that its open fan would sit on top of the rail. Lifting the
 * rail clear keeps both usable.
 */
@media (max-height: 560px) {
	.slang-rail {
		top: 40%;
	}
}

/* ---- reduced motion ---- */
/*
 * The indicator still changes height — that is the state itself, not an embellishment
 * — but it snaps rather than travels, and the name fades in place.
 */
@media (prefers-reduced-motion: reduce) {
	.slang-item::before,
	.slang-face,
	.slang-code {
		transition: none;
	}

	.slang-name {
		transform: translateY(-50%);
		transition: opacity 0.2s ease;
	}

	.slang-item:hover .slang-name,
	.slang-item:focus-visible .slang-name {
		transform: translateY(-50%);
	}
}
