/**
 * پادکست Bonjour Monjour — /podcast/ and the panel card.
 *
 * PURPLE IS AN ACCENT HERE, NOT A GROUND, and that is the whole design of this
 * file.
 *
 * The podcast's artwork is purple, so the owner asked for a purple page. The
 * first attempt read that as permission to paint the page purple: a dark
 * violet slab for the hero, a dark four-cell strip under it, purple headings,
 * purple body copy and a lilac band behind the prices. The owner's verdict was
 * that it looked horrible, and it did — but the cause is not the shade. It is
 * that this repo has already run the experiment. The course pages once had
 * their own cream-and-red world and the verdict on 30 July 2026 was that
 * opening a course «felt like leaving for a different website». They were
 * folded back into one palette.
 *
 * So the rule here is the one the site already uses for red: **red is only ever
 * the dot**. Purple is only ever the accent — the eyebrow badge, the track
 * numbers, the chapter counts, a hairline, a hover. The page's ground, its
 * headings and its body copy are the site's navy, exactly as on a course page.
 *
 * The loudest purple on the screen is the owner's own artwork, which is where
 * the colour should be coming from in the first place.
 *
 * The tokens are also retuned. The old scale ran to #4c1d6b, a red-purple far
 * enough round the wheel from #1B365D to read as a second brand sitting next to
 * the first. These sit at a violet hue that bridges the two, so an accent
 * beside a navy heading looks related rather than borrowed.
 *
 * The panel card at the end of this file is deliberately NOT purple. It sits on
 * /panel/ among navy cards, and one purple card in that column would read as a
 * rendering fault rather than as branding.
 *
 * Direction: logical properties only, so the layout mirrors itself and rtl.css
 * needs no additions.
 */

/*
 * SAMPLED FROM THE COVER, not chosen. The owner sent the artwork so the page
 * could take its colour from it: #46195C is the ground the microphone sits on
 * and #EBF465 is the lettering. The scale below is that purple lightened, so
 * every accent on the page is the same hue as the image at the top of it.
 *
 * The lime is used in exactly one place — the «اول گوش بده» button — and it is
 * used the way the cover uses it, as the light half of a pair with the purple
 * as its text. That pairing measures 11.4:1, which is why a colour this bright
 * can carry a control at all.
 */
.podcast-page {
	--pod-50: #f8f4fb;
	--pod-100: #eee5f5;
	--pod-200: #dcc9ea;
	--pod-300: #b995d2;
	--pod-500: #7a3fa5;
	--pod-600: #633187;
	--pod-700: #52286f;
	--pod-800: #46195c;

	/* The two colours straight off the artwork. */
	--pod-cover: #46195c;
	--pod-lime: #ebf465;
	--pod-lime-deep: #dbe649;
}

/* ==========================================================================
   0. Rhythm

   The site's sections are 7rem of padding top and bottom above 1024px, which
   is right on a homepage where every other band changes colour. Here two white
   sections meet — the playlist and the syllabus — and 7rem + 7rem is 224px of
   nothing between two lists, which is most of what made the owner call the page
   too long.

   Tighter throughout, and the join between two same-ground sections collapses
   to one gap instead of two. The plans band keeps its full padding: it changes
   colour, so the space is doing something.
   ========================================================================== */

.podcast-page .section {
	padding-block: 3rem;
}

@media (min-width: 640px) {
	.podcast-page .section {
		padding-block: 3.5rem;
	}
}

@media (min-width: 1024px) {
	.podcast-page .section {
		padding-block: 4.5rem;
	}

	.podcast-page .podcast-plans {
		padding-block: 5.5rem;
	}
}

/*
 * Two white bands in a row pay for one gap, not two. Written as a sibling
 * selector rather than a class because the syllabus is also the first section
 * on the page when no free episode has been uploaded yet, and there it needs
 * its full padding back.
 */
.podcast-episodes + .podcast-syllabus {
	padding-block-start: 0;
}

/* ==========================================================================
   1. The hero

   Built on the site's own .page-hero — a light wash into white — with the
   faintest violet tint instead of navy-50, and a single soft bloom behind the
   artwork. That tint is the entire difference between this page and a course
   page, which is the amount of difference a second colour has earned.
   ========================================================================== */

.podcast-page .page-hero {
	background: linear-gradient(to bottom, var(--pod-50), #fff 72%);
}

.podcast-page .page-hero::after {
	content: '';
	position: absolute;
	inset-block-start: -18rem;
	inset-inline-start: -12rem;
	inline-size: 42rem;
	block-size: 42rem;
	background: radial-gradient(circle, rgba(107, 75, 171, 0.1), transparent 62%);
	pointer-events: none;
}

/*
 * The eyebrow badge — the one place on the page where purple is a fill. It is
 * the size the site's red dot is, which is the point.
 */
.podcast-page .badge--pod {
	background: var(--pod-100);
	color: var(--pod-700);
	box-shadow: inset 0 0 0 1px var(--pod-200);
}

/*
 * Three boxes, two arrangements.
 *
 * On a phone the cover is a small square with the title beside it, which is
 * what a podcast looks like in every app anybody has used — and it saves the
 * ~300px that a full-width cover was spending before a visitor reached a single
 * word. On a laptop it becomes a poster in the second column, spanning both
 * rows of copy.
 *
 * Named areas rather than source order, so one <img> serves both.
 */
.podcast-hero__grid {
	display: grid;
	position: relative;
	z-index: 1;
	/*
	 * 5.5rem, not 6.5. At 390px the wider square left «پادکست Bonjour Monjour»
	 * about 230px, which breaks it mid-name — the Latin half wrapping away from
	 * the Persian half is the one break this title cannot take.
	 */
	grid-template-columns: 5.5rem minmax(0, 1fr);
	grid-template-areas:
		'cover head'
		'rest  rest';
	gap: 1rem 1rem;
	align-items: center;
	margin-block-start: 1.5rem;
}

.podcast-hero__grid--nocover {
	grid-template-columns: minmax(0, 1fr);
	grid-template-areas:
		'head'
		'rest';
}

.podcast-hero__cover {
	grid-area: cover;
}

.podcast-hero__head {
	grid-area: head;
}

.podcast-hero__rest {
	grid-area: rest;
}

.podcast-hero__cover img {
	display: block;
	inline-size: 100%;
	block-size: auto;
	/*
	 * The owner's artwork, uncropped — she frames her images and the layout
	 * adapts, not the other way round.
	 */
	border-radius: var(--radius-soft);
	box-shadow: 0 10px 30px -12px rgba(55, 36, 89, 0.45);
}

.podcast-hero__title {
	margin-block-start: 0.6rem;
	text-wrap: balance;
}

/*
 * «Bonjour Monjour» is one name and must break as one thing. Beside a cover on
 * a 390px screen the line broke between the two words, leaving «Bonjour» tucked
 * under «پادکست» and «Monjour» alone on the next line — which reads as two
 * different titles. zandi_bidi() already wraps every Latin run in .latin-run
 * for the direction fix, so the hook to hold it together is there.
 */
.podcast-hero__title .latin-run {
	white-space: nowrap;
}

.podcast-hero__lead {
	margin-block-start: 0.9rem;
}

.podcast-hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem 1.25rem;
	margin-block-start: 1.5rem;
}

.podcast-hero__from {
	margin: 0;
	font-size: 0.95rem;
	color: var(--navy-500);
}

.podcast-hero__from-amount {
	font-weight: 700;
	color: var(--navy-700);
	font-variant-numeric: tabular-nums;
}

.podcast-hero__listen {
	margin: 0;
}

/*
 * The lime button, and the only place this colour appears.
 *
 * It was an underlined link under the navy button, which is the weakest
 * possible treatment for the one thing on the page somebody can do for free —
 * and «listen before you pay» is the easiest yes on offer. As a button in the
 * cover's own lime beside the navy «خرید اشتراک» it reads as a second, lighter
 * choice rather than as fine print.
 *
 * Purple text on lime, exactly as the cover sets its own lettering: 11.4:1,
 * which is well past AA and most of the way to AAA. The dark text is what makes
 * a colour this bright usable on a control instead of merely loud.
 */
.podcast-page .btn--lime {
	background: var(--pod-lime);
	color: var(--pod-cover);
	box-shadow: inset 0 0 0 1px rgba(70, 25, 92, 0.14);
}

.podcast-page .btn--lime:hover {
	background: var(--pod-lime-deep);
	color: var(--pod-cover);
}

/*
 * The focus ring has to be visible against lime, and the site's default navy
 * ring on a yellow-green field is not. The cover's purple is.
 */
.podcast-page .btn--lime:focus-visible {
	outline: 3px solid var(--pod-cover);
	outline-offset: 2px;
}

/*
 * Filled, not stroked, and smaller than the site's 1.5rem default.
 *
 * zandi_get_icon() writes fill="none" stroke="currentColor" as presentation
 * attributes, which is right for the line icons the registry is built for and
 * wrong for this one: a 13px outlined triangle reads as a stray arrowhead
 * rather than as play. A CSS property beats a presentation attribute, so the
 * fill is swapped here rather than by giving the button its own markup.
 *
 * Not mirrored in RTL, deliberately — a play triangle points the way media
 * runs, not the way text does, and every player the student already uses
 * points it this way.
 */
.podcast-page .btn--lime .btn__icon {
	inline-size: 0.8rem;
	block-size: 0.8rem;
	fill: currentColor;
	stroke: none;
}

@media (min-width: 48em) {
	.podcast-hero__grid {
		grid-template-columns: minmax(0, 1fr) minmax(0, 19rem);
		grid-template-areas:
			'head rest'
			'head rest';
		gap: 1rem 3rem;
	}

	/*
	 * Two rows of copy on the inline-start, the poster spanning both opposite
	 * it. Written as its own rule rather than in the shorthand above because
	 * the areas only make sense once the cover is known to exist.
	 */
	.podcast-hero__grid:not(.podcast-hero__grid--nocover) {
		grid-template-columns: minmax(0, 1fr) minmax(0, 17rem);
		grid-template-areas:
			'head cover'
			'rest cover';
		align-items: start;
	}

	.podcast-hero__grid--nocover {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			'head'
			'rest';
	}

	.podcast-hero__cover {
		align-self: center;
	}

	.podcast-hero__title {
		margin-block-start: 0.75rem;
	}
}

/* ==========================================================================
   2. The facts

   Four things a buyer wants before a price: how many, how long, is there a
   transcript, who teaches it.

   This was a dark purple four-cell strip with 1px gutters, which reads as a
   database table rather than as a promise. It is now light, on the site's own
   hairline, and on a phone it is two columns rather than four cramped ones.
   ========================================================================== */

.podcast-facts {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 0.75rem;
	margin: 2rem 0 0;
	padding: 0;
}

/*
 * Four cards, not four cells.
 *
 * They were one bordered box divided by 1px gutters, which is the shape of a
 * table — and a table is what a spreadsheet uses to list values, not what a
 * page uses to make four promises. Separating them costs a little height and
 * buys each fact its own object: its own ground, its own edge, its own shadow.
 *
 * The shadow is the site's own --shadow-soft, so these sit at the same depth as
 * every other card on the site rather than inventing a second elevation.
 */
.podcast-facts__item {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	padding: 1rem 1.1rem;
	border-radius: var(--radius-soft);
	background: #fff;
	box-shadow: inset 0 0 0 1px var(--hairline-strong), var(--shadow-soft);
}

/*
 * The glyph is what turns four cells of text into a strip somebody scans. It
 * is purple — one of the four places on this page that colour appears at all —
 * and it is small, because a 24px icon over a 12px label inverts the hierarchy.
 */
.podcast-facts__icon {
	display: grid;
	place-items: center;
	inline-size: 2.25rem;
	block-size: 2.25rem;
	margin-block-end: 0.7rem;
	border-radius: var(--radius-soft);
	background: var(--pod-50);
	color: var(--pod-600);
	box-shadow: inset 0 0 0 1px var(--pod-100);
}

.podcast-facts__icon svg {
	inline-size: 1.15rem;
	block-size: 1.15rem;
}

/*
 * --navy-500, not --navy-400. The lighter token measures 4.33:1 on white, which
 * is under AA for anything smaller than 24px — and every one of these is 12px
 * or 13px. Caught by the contrast harness, not by eye; it looks fine and is not.
 */
.podcast-facts__label {
	margin: 0;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.01em;
	color: var(--navy-500);
}

.podcast-facts__value {
	margin: 0.3rem 0 0;
	font-size: 1.05rem;
	font-weight: 700;
	line-height: 1.4;
	color: var(--navy-700);
}

.podcast-facts__note {
	display: block;
	margin-block-start: 0.1rem;
	font-size: 0.78rem;
	font-weight: 500;
	line-height: 1.6;
	color: var(--navy-500);
}

@media (min-width: 48em) {
	.podcast-facts {
		grid-template-columns: repeat(4, minmax(0, 1fr));
		gap: 1rem;
		margin-block-start: 2.5rem;
	}

	.podcast-facts__item {
		padding: 1.25rem 1.35rem;
	}

	.podcast-facts__value {
		font-size: 1.15rem;
	}
}

/* ==========================================================================
   3. The free episodes, as a playlist

   One card holding rows, not three cards holding one player each. Three cards
   on a laptop were three near-empty rectangles; on a phone they were three
   screens of scrolling for ninety seconds of audio.
   ========================================================================== */

.podcast-playlist {
	max-width: 48rem;
	margin-inline: auto;
	margin-block-end: 0;
	/*
	 * NO margin-block-start here, and that is load-bearing rather than an
	 * omission. style.css gives `.section-heading + *` a 3rem top margin, and
	 * this element is that sibling. Setting the block axis at all — even to 0
	 * through a `margin: 0 auto …` shorthand — wins on source order and takes
	 * that margin away, which puts the card flush under the heading. It reads
	 * as merely tight at rest and as broken on the way down: `.reveal` holds
	 * the heading at translateY(20px) until theme.js releases it, so mid-scroll
	 * the heading is sitting on top of the card. That is the overlap the owner
	 * photographed on 11 September 2026.
	 */
	padding: 0.35rem 0.25rem;
	list-style: none;
}

/*
 * A track is a card now, not a row.
 *
 * It was a three-column grid — number, title, player — which was right when the
 * player was a 40px browser bar and nothing else. It carries three things now:
 * the title row, a designed player, and a transcript that opens to two thousand
 * characters. Those stack; forcing them into columns squeezed the title into a
 * thin vertical strip, which is what the first render of this looked like.
 */
.podcast-track {
	padding: 1rem 1.1rem;
}

.podcast-track + .podcast-track {
	margin-block-start: 0.75rem;
}

.podcast-track__row {
	display: flex;
	align-items: center;
	gap: 0.75rem;
}

.podcast-track__num {
	display: grid;
	place-items: center;
	flex: none;
	inline-size: 2rem;
	block-size: 2rem;
	border-radius: var(--radius-pill);
	background: var(--pod-100);
	color: var(--pod-700);
	font-size: 0.85rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.podcast-track__text {
	min-inline-size: 0;
}

.podcast-track__title {
	margin: 0;
	font-size: 0.975rem;
	font-weight: 700;
	line-height: 1.5;
	color: var(--navy-700);
}

.podcast-track__summary {
	margin: 0.2rem 0 0;
	font-size: 0.85rem;
	line-height: 1.7;
	color: var(--navy-500);
}

@media (min-width: 48em) {
	.podcast-track {
		padding: 1.15rem 1.35rem;
	}
}

/* --------------------------------------------------------------------------
   The player

   A designed control instead of the browser's own bar, which is a different
   shape in every browser and belongs to none of them.

   The native <audio> is still in the markup and still carries `controls` until
   theme.js takes them off — so the rule below hides the custom UI until the
   script that drives it says otherwise. It needs an author `display: none`
   rather than leaning on `hidden`: `[hidden]` is a user-agent rule and any
   author `display` beats it, which is the trap placement.css already documents.
   Scoped to this one control, never `.podcast-page [hidden]`.
   -------------------------------------------------------------------------- */

.podcast-player__ui[hidden] {
	display: none !important;
}

.podcast-player__audio {
	inline-size: 100%;
	block-size: 2.5rem;
}

/* Once the script is driving, the native element has nothing left to show. */
.podcast-player__ui:not([hidden]) + .podcast-player__audio,
.podcast-player:has(.podcast-player__ui:not([hidden])) .podcast-player__audio {
	display: none;
}

.podcast-player__ui {
	/*
	 * A grid, not a flex row, and that is the fix for the thing the owner
	 * circled: the dot did not line up with the play button.
	 *
	 * As a flex row the button was centred against the whole right-hand block —
	 * scrubber AND times stacked — so the scrubber's own centre sat 17px above
	 * the button's. Measured, not guessed. Here the button and the scrubber
	 * share row 1 and both centre in it, so the two centres are the same line
	 * by construction; the times drop into row 2 under the scrubber, where they
	 * cannot pull anything off-axis.
	 */
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: center;
	column-gap: 0.9rem;
	row-gap: 0.15rem;
	margin-block-start: 0.9rem;
	padding: 0.75rem 0.85rem;
	border-radius: var(--radius-soft);
	background: var(--pod-50);
	box-shadow: inset 0 0 0 1px var(--pod-100);
}

/*
 * 3.5rem, up from 2.75. The old button cleared a 44px target and still looked
 * like an afterthought next to a full-width scrubber — the owner's first note
 * was that the play icon is too small, and the glyph inside it was 15px in a
 * 44px circle, about a third of its own button.
 */
.podcast-player__toggle {
	grid-row: 1;
	display: grid;
	place-items: center;
	flex: none;
	inline-size: 3.5rem;
	block-size: 3.5rem;
	padding: 0;
	border: 0;
	border-radius: var(--radius-pill);
	background: var(--pod-cover);
	color: var(--pod-lime);
	cursor: pointer;
	transition: background-color 0.2s var(--ease-premium), transform 0.2s var(--ease-premium);
}

.podcast-player__toggle:hover {
	background: var(--pod-700);
}

.podcast-player__toggle:active {
	transform: scale(0.94);
}

.podcast-player__toggle:focus-visible {
	outline: 3px solid var(--pod-500);
	outline-offset: 2px;
}

.podcast-player__icon {
	display: grid;
	place-items: center;
}

.podcast-player__icon svg {
	/*
	 * 1.6rem in a 3.5rem button — the glyph is 46% of its circle, which is
	 * where a play button stops reading as a dot in a disc. It was 15px in a
	 * 44px one, about a third, and that is what «too small» meant.
	 */
	inline-size: 1.6rem;
	block-size: 1.6rem;
	fill: currentColor;
	stroke: none;
}

/* The triangle reads as centred only when it is nudged off centre. */
.podcast-player__icon--play svg {
	margin-inline-start: 0.1rem;
}

/*
 * Two glyphs stacked in the markup, one hidden — the same trick the licence
 * copy button uses. Swapping them in the script would put the state in two
 * places; this keeps it in one class on the wrapper.
 */
.podcast-player__icon--pause,
.podcast-player.is-playing .podcast-player__icon--play {
	display: none;
}

.podcast-player.is-playing .podcast-player__icon--pause {
	display: grid;
}

/*
 * The scrubber. A real <input type="range"> — keyboard-operable, announces its
 * own position, and needs no ARIA. Both track pseudo-elements have to be
 * written out: -webkit- and -moz- do not accept each other's selectors, and one
 * invalid selector in a list voids the whole rule.
 *
 * --played is set by the script and paints the elapsed half. It is a gradient
 * on the track rather than a second element, so there is nothing to keep in
 * sync when the box resizes.
 */
.podcast-player__seek {
	--played: 0%;

	grid-row: 1;
	grid-column: 2;
	align-self: center;
	inline-size: 100%;
	block-size: 1.25rem;
	margin: 0;
	padding: 0;
	background: transparent;
	-webkit-appearance: none;
	appearance: none;
	cursor: pointer;
}

.podcast-player__seek::-webkit-slider-runnable-track {
	block-size: 0.35rem;
	border-radius: var(--radius-pill);
	/*
	 * `to left`, not `to right`. The page is RTL and the elapsed part of a
	 * track has to grow from the side playback starts on, or the bar fills
	 * backwards.
	 */
	background: linear-gradient(to left, var(--pod-500) var(--played), var(--pod-200) var(--played));
}

.podcast-player__seek::-moz-range-track {
	block-size: 0.35rem;
	border-radius: var(--radius-pill);
	background: linear-gradient(to left, var(--pod-500) var(--played), var(--pod-200) var(--played));
}

.podcast-player__seek::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	inline-size: 1.05rem;
	block-size: 1.05rem;
	margin-block-start: -0.35rem;
	border: 2px solid #fff;
	border-radius: var(--radius-pill);
	background: var(--pod-cover);
	box-shadow: 0 1px 4px rgba(70, 25, 92, 0.4);
}

.podcast-player__seek::-moz-range-thumb {
	inline-size: 1.05rem;
	block-size: 1.05rem;
	border: 2px solid #fff;
	border-radius: var(--radius-pill);
	background: var(--pod-cover);
	box-shadow: 0 1px 4px rgba(70, 25, 92, 0.4);
}

.podcast-player__seek:focus-visible {
	outline: 3px solid var(--pod-500);
	outline-offset: 3px;
	border-radius: var(--radius-pill);
}

.podcast-player__times {
	grid-row: 2;
	grid-column: 2;
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	margin: 0.1rem 0 0;
	font-size: 0.75rem;
	font-variant-numeric: tabular-nums;
	color: var(--navy-500);
}

/* --------------------------------------------------------------------------
   متن پادکست

   A <details>, which is the one disclosure that needs no script: closed by
   default, keyboard-operable, and announced as a disclosure everywhere.
   -------------------------------------------------------------------------- */

.podcast-transcript {
	margin-block-start: 0.85rem;
	border-block-start: 1px solid var(--hairline);
}

.podcast-transcript__toggle {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-block-size: 2.75rem;
	padding-block: 0.5rem;
	font-size: 0.875rem;
	font-weight: 700;
	color: var(--pod-600);
	cursor: pointer;
	list-style: none;
}

/* Safari draws its own triangle through a pseudo-element the standard one misses. */
.podcast-transcript__toggle::-webkit-details-marker {
	display: none;
}

.podcast-transcript__toggle:hover {
	color: var(--pod-700);
}

.podcast-transcript__toggle:focus-visible {
	outline: 3px solid var(--pod-300);
	outline-offset: 2px;
	border-radius: var(--radius-soft);
}

.podcast-transcript__icon svg,
.podcast-transcript__chevron svg {
	inline-size: 1.05rem;
	block-size: 1.05rem;
}

.podcast-transcript__chevron {
	margin-inline-start: auto;
	display: grid;
	place-items: center;
	transition: transform 0.2s var(--ease-premium);
}

.podcast-transcript[open] .podcast-transcript__chevron {
	transform: rotate(180deg);
}

/*
 * The reveal.
 *
 * <details> has no transition of its own: the content is display:none one frame
 * and laid out the next, which is the «really bad animation» the owner reported
 * — it is not a bad animation, it is none at all, and the jump reads as the
 * page glitching.
 *
 * The wrapper animates `grid-template-rows` from 0fr to 1fr, which is the same
 * mechanism style.css already uses for the accordion panels, so the two
 * disclosures on this page open at the same speed on the same curve. The inner
 * div carries the overflow, because a grid row cannot clip on its own.
 *
 * Opening only. Closing still cuts, because <details> drops the content the
 * instant `open` is removed and no CSS can hold it there — a pop on the way
 * out is far less jarring than one on the way in, and keeping <details> is what
 * lets this work with no JavaScript at all.
 */
.podcast-transcript__wrap {
	display: grid;
	grid-template-rows: 1fr;
}

.podcast-transcript[open] .podcast-transcript__wrap {
	animation: pod-reveal 0.32s var(--ease-premium);
}

@keyframes pod-reveal {
	from {
		grid-template-rows: 0fr;
		opacity: 0;
	}

	to {
		grid-template-rows: 1fr;
		opacity: 1;
	}
}

@media (prefers-reduced-motion: reduce) {
	.podcast-transcript[open] .podcast-transcript__wrap {
		animation: none;
	}
}

/* The row cannot clip; the element inside it has to. */
.podcast-transcript__clip {
	overflow: hidden;
}

/*
 * The text itself. Capped in height with its own scroll, because two thousand
 * characters of French opened inline pushes the next episode off the screen —
 * and the student is reading this WHILE listening, so the player has to stay
 * where it was.
 */
.podcast-transcript__body {
	max-block-size: 26rem;
	overflow-y: auto;
	overscroll-behavior: contain;
	margin-block-end: 0.75rem;
	padding: 1rem 1.1rem;
	border-radius: var(--radius-soft);
	background: var(--mist);
	font-size: 0.875rem;
	line-height: 1.9;
	color: var(--navy-600);
}

.pod-tr__title {
	margin: 0 0 0.5rem;
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--pod-700);
}

.pod-tr__title:not(:first-child) {
	margin-block-start: 1.25rem;
}

.pod-tr__text {
	margin: 0 0 0.35rem;
}

.pod-tr__lead {
	margin: 0.5rem 0 0.35rem;
	font-weight: 700;
	color: var(--navy-700);
}

.pod-tr__list {
	margin: 0 0 0.5rem;
	padding: 0;
	list-style: none;
}

/*
 * The bullet is drawn on the inline-start edge with a logical property, so it
 * sits on the right of a Persian line and on the left of a French one — which
 * is every line here — without rtl.css needing anything.
 */
.pod-tr__item {
	position: relative;
	padding-inline-start: 0.9rem;
	color: var(--pod-700);
}

.pod-tr__item::before {
	content: '';
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 0.75em;
	inline-size: 0.3rem;
	block-size: 0.3rem;
	border-radius: var(--radius-pill);
	background: var(--pod-300);
}

.pod-tr__item--sub {
	padding-inline-start: 1.9rem;
	color: var(--navy-500);
}

.pod-tr__item--sub::before {
	inset-inline-start: 1rem;
	background: transparent;
	box-shadow: inset 0 0 0 1px var(--pod-300);
}

.pod-tr__break {
	margin: 0.85rem 0;
	border: 0;
	border-block-start: 1px solid var(--hairline-strong);
}

/* ==========================================================================
   4. سرفصل — the shared accordion

   The base rules (.accordion, .accordion__item, __trigger, __panel, __chevron)
   live in style.css and are the same ones the course syllabus and the FAQ use.
   Nothing here reimplements them; this is the chapter row's own furniture —
   the number, the title, the topic count — plus a width so ninety-eight topics
   do not stretch to the edge of a 1440 screen.
   ========================================================================== */

.podcast-syllabus__accordion,
.podcast-syllabus__stats {
	max-width: 48rem;
	margin-inline: auto;
}

/*
 * Two counted figures. A list, so a screen reader reads two facts rather than
 * one run-on line, with the separator drawn by CSS instead of typed as text the
 * bidi algorithm would push around.
 */
.podcast-syllabus__stats {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.5rem 1.25rem;
	margin-block-end: 1.5rem;
	padding: 0;
	list-style: none;
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--navy-500);
}

.podcast-syllabus__stats li {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	font-variant-numeric: tabular-nums;
}

.podcast-syllabus__stats li + li::before {
	content: '';
	inline-size: 0.3rem;
	block-size: 0.3rem;
	border-radius: var(--radius-pill);
	background: var(--pod-300);
}

.podcast-chapter__trigger {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	inline-size: 100%;
	text-align: start;
}

/*
 * The chapter number, in the accent. `flex: none` because a two-digit chapter
 * («۱۴») must not make the circle an oval.
 */
.podcast-chapter__num {
	display: grid;
	place-items: center;
	flex: none;
	inline-size: 2rem;
	block-size: 2rem;
	border-radius: var(--radius-pill);
	background: var(--pod-100);
	color: var(--pod-700);
	font-size: 0.8rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.podcast-chapter__title {
	flex: 1 1 auto;
	min-inline-size: 0;
	font-size: 0.975rem;
	font-weight: 700;
	line-height: 1.6;
	color: var(--navy-700);
}

.podcast-chapter__count {
	flex: none;
	padding: 0.15rem 0.55rem;
	border-radius: var(--radius-pill);
	background: var(--pod-50);
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--pod-600);
	font-variant-numeric: tabular-nums;
}

/*
 * The panel's own padding, and it was missing entirely.
 *
 * `.accordion__panel > div` is `overflow: hidden` and nothing else, so an
 * accordion's CONTENT has to pay for its own inset — `.accordion__answer` does
 * exactly this for the FAQ. Without it the tick sat one pixel off the card's
 * right border, which is what the owner circled: not «too far right» by taste,
 * literally touching the edge.
 *
 * Matched to .accordion__trigger's padding above it, so the number in the
 * header and the ticks under it stand on the same line.
 */
.podcast-chapter__list {
	display: grid;
	gap: 0.6rem;
	margin: 0;
	padding: 0 1.25rem 1.5rem;
	list-style: none;
}

@media (min-width: 640px) {
	.podcast-chapter__list {
		padding: 0 1.5rem 1.75rem;
	}
}

.podcast-chapter__item {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	font-size: 0.9rem;
	line-height: 1.8;
	color: var(--navy-600);
	text-wrap: pretty;
}

.podcast-chapter__bullet {
	display: grid;
	place-items: center;
	flex: none;
	inline-size: 1.15rem;
	block-size: 1.15rem;
	margin-block-start: 0.3rem;
	border-radius: var(--radius-pill);
	background: var(--pod-100);
	color: var(--pod-700);
}

.podcast-chapter__bullet svg {
	inline-size: 0.7rem;
	block-size: 0.7rem;
}

@media (max-width: 47.99em) {
	/*
	 * The count moves under the title on a phone. On one line with a chapter
	 * name as long as «فصل چهارده» it squeezed the title to two words and a
	 * wrap, which is worse than a second line nobody has to read.
	 */
	.podcast-chapter__trigger {
		flex-wrap: wrap;
		gap: 0.5rem 0.6rem;
	}

	.podcast-chapter__title {
		flex: 1 1 60%;
	}

	.podcast-chapter__count {
		order: 3;
		margin-inline-start: 2.6rem;
	}

	.podcast-chapter__trigger .accordion__chevron {
		order: 2;
		margin-inline-start: auto;
	}
}

/* ==========================================================================
   5. The buy block — three steps, then three prices

   One band. «چطور کار می‌کند» used to be a section of its own between the
   syllabus and the prices: a heading, three sentences, and a whole section's
   vertical padding, which made the page longer while separating the
   explanation from the thing it explains.
   ========================================================================== */

.podcast-plans {
	background: var(--mist);
}

/*
 * The strip, the three cards and the fine print all share one width, set once
 * below. They did not, and a 46rem strip centred over a full-container row of
 * cards left two visible steps of misalignment down the middle of the band —
 * the kind of thing nobody names but everybody reads as untidy.
 */
.podcast-how {
	margin-block-end: 1.5rem;
	/*
	 * NO margin-block-start here, and that is load-bearing rather than an
	 * omission. style.css gives `.section-heading + *` a 3rem top margin, and
	 * this element is that sibling. Setting the block axis at all — even to 0
	 * through a `margin: 0 auto …` shorthand — wins on source order and takes
	 * that margin away, which puts the card flush under the heading. It reads
	 * as merely tight at rest and as broken on the way down: `.reveal` holds
	 * the heading at translateY(20px) until theme.js releases it, so mid-scroll
	 * the heading is sitting on top of the card. That is the overlap the owner
	 * photographed on 11 September 2026.
	 */
	padding: 1.25rem 1.4rem;
	border-radius: var(--radius-soft);
	background: #fff;
	box-shadow: inset 0 0 0 1px var(--hairline);
}

.podcast-how__title {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	margin: 0 0 0.85rem;
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--navy-700);
}

.podcast-how__title svg {
	inline-size: 1.1rem;
	block-size: 1.1rem;
	color: var(--pod-500);
}

/*
 * Counters rather than list-style, so the number can be a purple chip instead
 * of a bare marker — and still drawn by the browser, which is what keeps the
 * digits Persian. zandi_fa_digits() cannot reach a marker.
 */
.podcast-how__steps {
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: step;
	display: grid;
	gap: 0.7rem;
}

.podcast-how__step {
	counter-increment: step;
	display: grid;
	grid-template-columns: 1.5rem minmax(0, 1fr);
	gap: 0.65rem;
	align-items: start;
	font-size: 0.9rem;
	line-height: 1.8;
	color: var(--navy-600);
}

.podcast-how__step::before {
	content: counter(step, persian);
	display: grid;
	place-items: center;
	inline-size: 1.5rem;
	block-size: 1.5rem;
	margin-block-start: 0.15rem;
	border-radius: var(--radius-pill);
	background: var(--pod-100);
	color: var(--pod-700);
	font-size: 0.78rem;
	font-weight: 700;
}

@media (min-width: 60em) {
	.podcast-how__steps {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 1.25rem;
	}
}

/* --- The three cards ------------------------------------------------------ */

/* One width for the whole buy block. */
.podcast-how,
.podcast-plans__list,
.podcast-plans__fine {
	max-width: 56rem;
	margin-inline: auto;
}

.podcast-plans__list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 1rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The card the page lifts.
 *
 * There was no highlighted plan on purpose — a «محبوب‌ترین» ribbon is a
 * persuasion pattern this site does not use, and the saving is already in the
 * prices. The owner asked for one, so it exists now and it makes a claim that
 * can be checked instead of one that cannot: «به‌صرفه‌ترین» is the lowest cost
 * per month of the three, from the owner's own figures.
 *
 * Lifted with a ring and the cover's purple rather than with scale, so the row
 * of three keeps one baseline and nothing moves when the page loads.
 */
.podcast-plan--featured {
	position: relative;
	border-color: transparent;
	box-shadow: inset 0 0 0 2px var(--pod-500), var(--shadow-card);
}

/*
 * Straddling the top edge, so it reads as attached to the card rather than as
 * the first line inside it. `inset-inline-start: 50%` plus a translate keeps it
 * centred without a physical `left` anywhere — the card mirrors itself.
 */
.podcast-plan__tag {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 50%;
	transform: translate(50%, -50%);
	padding: 0.25rem 0.85rem;
	border-radius: var(--radius-pill);
	background: var(--pod-500);
	color: #fff;
	font-size: 0.72rem;
	font-weight: 700;
	line-height: 1.6;
	white-space: nowrap;
}

/*
 * A grid rather than a flex column, with a named row for each part. Three cards
 * whose notes are different lengths — and one of which has no note at all —
 * still line their prices and their buttons up, because every card has the same
 * four rows whether or not each is filled.
 */
.podcast-plan {
	display: grid;
	grid-template-rows: auto auto 1fr auto;
	gap: 0.5rem;
	padding: 1.5rem 1.35rem;
	text-align: center;
}

/* Room for the tag that sits on the edge. */
.podcast-plan--featured {
	padding-block-start: 1.85rem;
}

.podcast-plan__label {
	margin: 0;
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--navy-500);
}

.podcast-plan__price {
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 0.35rem;
	margin: 0;
}

.podcast-plan__amount {
	font-size: 1.75rem;
	font-weight: 800;
	line-height: 1.1;
	color: var(--navy-700);
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.01em;
}

.podcast-plan__currency {
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--navy-500);
}

/*
 * `min-block-size` and not a non-breaking space in the markup: the one-month
 * plan has no note, and the slot has to hold its height anyway or that card's
 * button sits a line higher than the other two.
 */
.podcast-plan__note {
	margin: 0;
	min-block-size: 2.6rem;
	font-size: 0.82rem;
	line-height: 1.6;
	color: var(--pod-600);
	text-wrap: pretty;
}

.podcast-plan__cta {
	margin-block-start: 0.35rem;
}

/*
 * Shaped like the button it stands in for. As bare text it read as a caption
 * somebody had forgotten to finish, and the card looked broken rather than
 * not-yet-open. Muted and unclickable, but the same size and place, so the
 * card's proportions do not change on the day the product is wired up.
 */
.podcast-plan__soon {
	display: grid;
	place-items: center;
	margin: 0.35rem 0 0;
	min-block-size: 2.75rem;
	padding-inline: 1rem;
	border-radius: var(--radius-pill);
	background: var(--mist);
	box-shadow: inset 0 0 0 1px var(--hairline-strong);
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--navy-500);
}

.podcast-plans__fine {
	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: 0.45rem;
	margin-block: 1.5rem 0;
	font-size: 0.85rem;
	line-height: 1.8;
	color: var(--navy-500);
	text-align: start;
}

.podcast-plans__fine svg {
	flex: none;
	inline-size: 1.05rem;
	block-size: 1.05rem;
	margin-block-start: 0.35rem;
	color: var(--navy-400);
}

@media (max-width: 47.99em) {
	/*
	 * One column, and tighter. auto-fit would give two 15rem cards a 360px
	 * screen cannot hold without shrinking the price to nothing.
	 */
	.podcast-plans__list {
		grid-template-columns: minmax(0, 1fr);
	}

	.podcast-plan {
		grid-template-rows: auto;
		gap: 0.4rem;
		padding: 1.25rem 1.25rem;
	}

	.podcast-plan__note {
		min-block-size: 0;
	}
}
