/*
 * Announcement bar.
 *
 * Motion is CSS-driven, never <marquee>. Everything degrades to a plain list:
 * no CSS, no JS, reduced-motion or a narrow screen all yield readable static
 * content rather than a broken strip.
 */

.jmns-ticker {
	display: flex;
	align-items: stretch;
	gap: var(--wp--preset--spacing--20, 0.5rem);
	/*
	 * Room at the end for whatever the corner stack has pinned to this corner.
	 *
	 * The strip is full-bleed and its step buttons sit flush against the
	 * inline-end edge — the same place the chat launcher is pinned. On a
	 * 900px-tall desktop the strip lands at the foot of the viewport on load, so
	 * the two met at the one scroll position every visitor starts from.
	 *
	 * This was `--jmns-bot-clearance-inline`, a 184px figure written in the
	 * launcher's stylesheet from the pill as it looked that day, while the same
	 * file allowed the pill to grow to 240px. Nothing held the two together, and
	 * the reservation was already 9px short of "Tanya Mualimin" — one of the
	 * three names §16 says the department is choosing between. The stack's token
	 * is the bound the launcher is actually held to, so a reservation that is
	 * too small is no longer expressible.
	 *
	 * Falls back to zero, so a site with the bot switched off reserves nothing —
	 * the stack multiplies the corner's reservation by whether anything is in
	 * it, and the theme is not required to have this plugin at all.
	 */
	padding-inline-end: var(--jmns-stack-clear-inline-end, 0px);
	background-color: var(--wp--preset--color--background, #FAF8F2);
	border-block-end: 1px solid rgb(var(--jmns-hairline-rgb, 38 51 42) / var(--jmns-a-rule, 0.15));
	font-size: var(--wp--preset--font-size--small, 0.875rem);
}

.jmns-ticker__label {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	margin: 0;
	padding: 0.5rem 0.9rem;
	background-color: var(--wp--preset--color--interactive, #245746);
	color: var(--jmns-on-primary, #FFFFFF);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	white-space: nowrap;
}

.jmns-ticker__viewport {
	flex: 1 1 auto;
	display: flex;
	overflow: hidden;
	min-inline-size: 0;
	/*
	 * Height reserved for the stepper before the stepper exists.
	 *
	 * The prev/next controls are rendered server-side but `hidden`, and the
	 * script decides whether the row actually needs them — it cannot know until
	 * it can measure whether the announcements overflow. So the strip painted
	 * 44px tall, the script un-hid a 44px control a quarter-second later, and
	 * the strip grew to 52 and pushed the whole services grid down 7px.
	 *
	 * Measured as an intermittent desktop CLS of 0.016-0.023: intermittent
	 * because it is a race between that script and first paint, which is
	 * exactly the kind of shift that is invisible on a fast local machine and
	 * routine on a phone.
	 *
	 * Reserving the taller state costs 8px of empty strip in the rare case the
	 * stepper is not needed, and costs nothing when it is.
	 */
	min-block-size: 52px;
	align-items: center;
}

.jmns-ticker__list {
	display: flex;
	flex: 0 0 auto;
	gap: var(--wp--preset--spacing--50, 2rem);
	margin: 0;
	padding: 0 var(--wp--preset--spacing--30, 1rem);
	list-style: none;
	align-items: center;
	white-space: nowrap;
	/*
	 * No continuous scroll, per client brief §13: "do not continuously scroll
	 * text". A marquee moves the reader's target while they are reading it,
	 * which is why the pattern needed a pause button, a hover pause and a focus
	 * pause to be usable at all — three mitigations for a problem the strip did
	 * not have to have.
	 *
	 * The strip keeps its machinery: this is the `is-static` presentation the
	 * component already used on focus, now the only presentation. Announcements
	 * are stepped with the arrows, which the script already drives.
	 */
	animation: none;
}

/*
 * The pause control and the duplicate list both go with the animation. Nothing
 * moves on its own now, so SC 2.2.2 has nothing to ask for, and a button that
 * pauses nothing is worse than no button.
 */
.jmns-ticker__toggle,
.jmns-ticker__list--clone {
	display: none;
}

.jmns-ticker__viewport {
	overflow-x: auto;
	scrollbar-width: none;
}

/*
 * One announcement at a time, at every width (§13).
 *
 * The items used to size to their own text and sit in a row, which is why the
 * strip needed to scroll to show the second one. Giving each the full viewport
 * width means only one is ever readable, the stepper has something to step
 * through, and the script's own "hide the nav when nothing overflows" check
 * now resolves the right way round on desktop.
 */
.jmns-ticker__item {
	flex: 0 0 100%;
	min-inline-size: 100%;
	scroll-snap-align: start;
	overflow: hidden;
	text-overflow: ellipsis;
	/*
	 * The inset belongs to the announcement, not to the list around it.
	 *
	 * The list kept the `padding-inline` it had as a marquee, and once it
	 * became the scroll container that padding started shrinking what `100%`
	 * resolves against: each item measured 1167 inside a 1191px container, so
	 * the first 24px of the next announcement sat in the strip beside the
	 * current one — "Tawaran Sebuth…" showing under the stepper while
	 * "Panggilan Sumbangan…" was the one being read. One at a time was the
	 * whole point of stepping.
	 */
	padding-inline: var(--wp--preset--spacing--30, 1rem);
}

/*
 * The list is the scroll container, not the viewport around it. The script
 * steps by setting `scrollLeft` on `[data-jmns-ticker-list]`, so the overflow
 * has to live on the same element or the arrows move nothing.
 */
/*
 * A definite width, or the items' `100%` resolves against a content-sized flex
 * box and each announcement becomes several thousand pixels wide. It still
 * works — the viewport clips it and one shows at a time — but only by accident,
 * and an accident is not a layout.
 */
.jmns-ticker__list {
	flex: 1 1 auto;
	min-inline-size: 0;
	gap: 0;
	/* Zeroed here; the announcements carry it themselves. See the item rule. */
	padding-inline: 0;
	overflow-x: auto;
	scrollbar-width: none;
	scroll-behavior: smooth;
	scroll-snap-type: x mandatory;
}

.jmns-ticker__list::-webkit-scrollbar {
	display: none;
}

/*
 * The step controls used to be a phone-only affordance: on a wide screen the
 * marquee moved the announcements along by itself and there was nothing to
 * press. With the scrolling gone they are the only way through the list, so
 * they exist at every width.
 */
.jmns-ticker__step {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	min-inline-size: 44px;
	min-block-size: 44px;
	padding: 0;
	border: 1px solid var(--wp--preset--color--border, #DCE4DF);
	border-radius: 50%;
	background: transparent;
	color: var(--wp--preset--color--interactive, #245746);
	font-size: 1.1rem;
	line-height: 1;
	cursor: pointer;
	transition: background-color var(--t-fast, 180ms) var(--ease, ease);
}

.jmns-ticker__step:hover {
	background-color: var(--wp--preset--color--surface-tint, #EAF1EC);
}

.jmns-ticker__step[disabled] {
	opacity: 0.35;
	cursor: default;
}

.jmns-ticker__viewport::-webkit-scrollbar {
	display: none;
}

/*
 * 24px of target, not 17.
 *
 * These are standalone links — one announcement each, stacked on a phone — so
 * SC 2.5.8's exception for a link inside a sentence does not cover them, and
 * the line box alone gave them 17px. The extra height is padding, so the text
 * does not move; only the area you can hit does.
 */
/* §28: 15-16px. The strip was a step under, which made the one announcement
   on screen read as secondary to the label beside it. */
.jmns-ticker__item a {
	font-size: 0.9375rem;
	display: inline-flex;
	align-items: center;
	min-block-size: 24px;
	color: var(--wp--preset--color--text-primary, #1F2925);
	font-weight: 600;
	text-decoration: none;
}

.jmns-ticker__item a:hover,
.jmns-ticker__item a:focus-visible {
	text-decoration: underline;
}

/*
 * The bullet separator is gone with the marquee.
 *
 * It divided announcements when they ran past each other in one moving line.
 * Only one is on screen at a time now, so it separated nothing — it just
 * trailed the end of whichever announcement was showing.
 */

.jmns-ticker__toggle {
	flex: 0 0 auto;
	min-inline-size: 44px;
	min-block-size: 44px;
	border: 0;
	background: transparent;
	color: var(--wp--preset--color--text-primary, #1F2925);
	cursor: pointer;
	font-size: 0.75rem;
}

.jmns-ticker__toggle:hover {
	background-color: rgb(var(--jmns-shade-rgb, 38 51 42) / 0.06);
}

.jmns-ticker :focus-visible {
	outline: 3px solid var(--wp--preset--color--interactive, #245746);
	outline-offset: -3px;
}

/*
 * Keyboard focus stops the marquee moving *and* puts it back where it started.
 *
 * :focus-within alone only pauses the animation, and pausing a transform leaves
 * it wherever it happened to be. The links are displaced by translateX inside an
 * overflow:hidden strip, so a link can sit thousands of pixels outside the
 * viewport with no scroll position that reaches it — the browser's own
 * scroll-into-view only goes to scrollLeft >= 0. Measured while tabbing: links
 * focused at -3874, -3232, -2743, -2127, -1281 and -892px, entirely off screen,
 * and whether that happened at all depended on the animation's phase when focus
 * arrived. SC 2.4.7 and SC 2.4.11.
 *
 * Dropping the transform makes the strip an ordinary horizontal scroller, so
 * scroll-into-view works and the focused link is always reachable. The row keeps
 * its height, which matters — expanding it into the wrapped layout the
 * reduced-motion fallback uses would reflow the page under someone who has just
 * pressed Tab.
 *
 * The duplicate goes with it: it exists only to make the loop seamless, and
 * while static it is repeated content the scroller would run through twice.
 */
.jmns-ticker.is-static .jmns-ticker__list {
	animation: none;
	transform: none;
}

.jmns-ticker.is-static .jmns-ticker__viewport {
	/* Instant, not smooth: rapid tabbing outruns a smooth scroll and the ring
	   arrives before the link does. */
	overflow-x: auto;
}

.jmns-ticker.is-static .jmns-ticker__list--clone {
	display: none;
}

/* ------------------------------------------------------- static fallbacks -- */

/*
 * Reduced motion: no scrolling at all. The strip becomes a wrapped list, the
 * duplicate is removed from layout, and the pause control is pointless so it
 * goes too.
 */
@media (prefers-reduced-motion: reduce) {
	.jmns-ticker__list {
		animation: none;
		flex-wrap: wrap;
		white-space: normal;
		/*
		 * flex:0 0 auto sizes this to max-content, so permitting wrapping is
		 * not enough on its own — the list still reserved the full unwrapped
		 * width and widened the document. It has to be allowed to shrink.
		 */
		flex: 1 1 auto;
		inline-size: 100%;
		min-inline-size: 0;
	}

	.jmns-ticker__list--clone,
	.jmns-ticker__toggle {
		display: none;
	}

	.jmns-ticker__viewport {
		overflow: visible;
	}
}

/*
 * Phones: a horizontally scrolling strip is unreadable on a small screen, so
 * it becomes a plain vertical list (§5.5).
 */
@media (max-width: 48rem) {
	/*
	 * The paging controls and the archive link share the last row.
	 *
	 * Stacked, they were two rows of one short thing apiece — a pair of arrows
	 * with "1 / 3" between them, then "Semua pengumuman" underneath — and
	 * together they cost more height than the announcement they belong to.
	 * Side by side they cost one row and read as one set of controls.
	 *
	 * A wrapping flex row, not the two-column grid this started as. The grid
	 * sized the link's column `minmax(0, 1fr)` and the stepper's `auto`, so the
	 * stepper took its max-content width — 173.5px — and the link got whatever
	 * was left: 24.5px at 390px, 0px at 320px. `minmax(0, …)` also removes the
	 * automatic min-content floor, so the track never grew back and the link
	 * just overflowed its cell. Grid does not move a sibling aside for an
	 * overflowing item, so the two painted on top of each other: measured at
	 * 390px, the link's box ran 16→112px and the disabled "previous" button sat
	 * at 32.5→76.5px, entirely inside it — the chevron drawn over the words,
	 * 44x44px of overlap. It failed the same way from 320px up to about 493px.
	 *
	 * A flex line cannot do that. Items sharing a line never overlap, and when
	 * they no longer fit the line breaks and the stepper drops below the link
	 * instead — which is worse than one row but is still readable, and is the
	 * behaviour the grid had no way to fall back to.
	 */
	.jmns-ticker {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		/*
		 * The last row's own breathing room. It used to be a `padding-block-end`
		 * on the stepper and a different one on the link, which left the two
		 * optically off each other by the difference once they were centred in a
		 * shared row.
		 */
		padding-block-end: 0.5rem;
	}

	/*
	 * The label and the announcement take a row each; the stepper and the
	 * archive link share the last one. `order` puts the link first there while
	 * the markup keeps the stepper next to the viewport it drives.
	 */
	.jmns-ticker__label    { order: 1; flex: 0 0 100%; }
	.jmns-ticker__viewport { order: 2; flex: 0 0 100%; }
	.jmns-ticker__more     { order: 3; flex: 0 1 auto; text-align: start; }

	/*
	 * Pushed to the end of whichever row it lands on — beside the link when
	 * both fit, alone when they do not. An auto margin rather than
	 * `justify-content: space-between`, which would strand the stepper at the
	 * start of the row once it wrapped onto one of its own.
	 */
	.jmns-ticker__nav {
		order: 4;
		flex: 0 0 auto;
		margin-inline-start: auto;
	}

	/*
	 * A line, not a band.
	 *
	 * Centred and full width, the label was a 56px slab of solid green directly
	 * under a 94px banner — two horizontal bars in a row, the louder of which
	 * says only what kind of thing follows. Tightened to a single line it still
	 * labels the section and gives most of its height back.
	 */
	.jmns-ticker__label {
		justify-content: center;
		padding-block: 0.3rem;
		font-size: 0.75rem;
		letter-spacing: 0.08em;
	}

	/*
	 * There was a second `.jmns-ticker__step` here setting a 40x40 target, and a
	 * second `.jmns-ticker__nav` and `.jmns-ticker__more` besides. All three lost
	 * to identical selectors further down this same media query on source order
	 * alone, so the 40px never reached the page — but it is how a control ends up
	 * under SC 2.5.5's 44px without anyone editing the rule that looks
	 * authoritative. Each of the three now has one rule and one place to change.
	 */

	.jmns-ticker__viewport {
		overflow: visible;
	}

	/*
	 * One announcement at a time, swipeable.
	 *
	 * Three stacked was already better than eight, but the brief asks for one
	 * readable line rather than a short list — and a stack of three still mixes
	 * headline lengths so the eye has nowhere to rest. A snap row gives each
	 * announcement the full width, makes the thumb gesture the primary control,
	 * and costs no height at all: the section is as tall as its longest single
	 * item rather than as tall as three.
	 *
	 * Native scrolling does the work, so the prev/next buttons only set
	 * scrollLeft and a failed script leaves a row that still swipes.
	 */
	.jmns-ticker__list {
		animation: none;
		flex-direction: row;
		align-items: stretch;
		gap: 0;
		padding-block: 0.6rem;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scroll-behavior: smooth;
		scrollbar-width: none;
		/*
		 * No inline padding on the scroll port itself. The base rule's 12px made
		 * each 100%-wide item 351px inside a 375px port, so the next
		 * announcement peeked 12px past the edge on every step. The gutter is on
		 * the item instead.
		 */
		padding-inline: 0;
		/*
		 * The scrolling layout needs nowrap; the stacked one must undo it.
		 * Left set, each announcement became a single unbreakable line, and
		 * flex:0 0 auto then sized the list to that max-content width — 1215px
		 * inside a 477px viewport, which cropped every band on the page.
		 * Wrapping and shrinking are both required; either alone does nothing.
		 */
		white-space: normal;
		flex: 1 1 auto;
		inline-size: 100%;
		min-inline-size: 0;
	}

	.jmns-ticker__list::-webkit-scrollbar {
		display: none;
	}

	.jmns-ticker__item {
		flex: 0 0 100%;
		inline-size: 100%;
		min-inline-size: 0;
		scroll-snap-align: start;
		/*
		 * The gutter lives on the item, not the row. On the row it would inset
		 * the scroll port and leave the next announcement peeking in at the
		 * edge — which reads as "swipe me" beside a stepper that already says
		 * which one of three this is, and the two affordances disagree.
		 */
		padding-inline: var(--wp--preset--spacing--40, 1rem);
		box-sizing: border-box;
		/* A containing block for the hidden text inside, so an absolutely
		   positioned span cannot escape the scroller and widen the page — the
		   same trap the prayer row fell into. */
		position: relative;
	}

	.jmns-ticker__item + .jmns-ticker__item::before {
		content: none;
	}

	.jmns-ticker__list--clone,
	.jmns-ticker__toggle {
		display: none;
	}

	/*
	 * Three, then a link. All eight stacked measured 421px on a 390px phone —
	 * more vertical space than the prayer bar and the masthead together, sitting
	 * above the service tiles that are the most-used element on the site.
	 *
	 * display:none rather than a visual clip, so assistive technology and the tab
	 * order agree with what is on screen; the archive link carries the rest. Kept
	 * in step with Render::PHONE_ITEMS.
	 */
	.jmns-ticker__item:nth-child(n + 4) {
		display: none;
	}

	/* ------------------------------------------------------------ nav -- */

	/*
	 * The gutter is carried by each child in the phone layout, not by the
	 * container, so the stepper needs its own or the "next" button ends up half
	 * off the screen once the auto margin pushes it to the end of the row.
	 */
	.jmns-ticker__nav {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: var(--wp--preset--spacing--30, 0.75rem);
		padding-inline-end: var(--wp--preset--spacing--40, 1rem);
	}

	/*
	 * A bigger glyph on a phone, and nothing else. The 44x44 target, the ring,
	 * the zeroed padding and the disabled treatment all come from the base rule,
	 * which is now the only place the touch-target number lives — restating it
	 * here is what let a 40px copy sit unnoticed earlier in this media query.
	 */
	.jmns-ticker__step {
		font-size: 1.25rem;
	}

	.jmns-ticker__count {
		margin: 0;
		min-inline-size: 3.5em;
		color: var(--wp--preset--color--text-secondary, #5E6D63);
		font-size: 0.8125rem;
		font-variant-numeric: tabular-nums;
		text-align: center;
	}

	/*
	 * Gutter at the start only. The matching one at the end was 16px of nothing
	 * between the link and a stepper that already carries its own, and it was
	 * 16px the shared row could not spare: with it the row's content measures
	 * 360.5px and breaks in two on a 360px phone, without it 344.5px and stays
	 * on one.
	 */
	.jmns-ticker__more {
		margin: 0;
		padding-inline-start: var(--wp--preset--spacing--40, 1rem);
		padding-inline-end: 0;
		font-weight: 600;
	}

	/*
	 * Standalone link, and the only way out of a capped list — 44px, the touch
	 * minimum the mobile brief sets. It was 24px, matching the announcements
	 * above it, which is the right relationship and the wrong number.
	 */
	.jmns-ticker__more a {
		display: inline-flex;
		align-items: center;
		min-block-size: 44px;
	}
}

/*
 * No launcher clearance on a phone, because there is no launcher that wide to
 * clear.
 *
 * `--jmns-stack-clear-inline-end` is 224px — the bound the pill is held to plus
 * the stack's own offset and gap — and the base rule reserves it across the
 * whole strip. On a 390px phone that is more than half the row: at the 184px
 * this reserved before, the strip's content box came out 206px, which squeezed
 * the announcement into five lines and left the last row 24.5px for a link
 * whose shortest unbreakable word is 96px. It is the other half of the overlap
 * above, and it is reserved against a control that is not there — bot.css
 * collapses the launcher to a 48px circle at this same 30rem, its own
 * breakpoint, which is why this one matches it rather than the 48rem the phone
 * layout uses.
 *
 * Above 30rem the reservation stays. It is not decorative there: at 768x900 the
 * strip lands at the foot of the viewport on load, and without the padding the
 * "next" button sits at 708→752px directly under a launcher occupying
 * 601→752px. That collision is deterministic, so it keeps being paid for. The
 * cost is a stepper that drops onto its own row between about 481 and 570px,
 * where the reservation and the row's 344.5px of content no longer both fit —
 * two rows, still no overlap.
 *
 * That band was 481-532px while this reserved 184px, and the 40px it grew by is
 * the price of the reservation being right rather than approximately right. The
 * strip is measurably worse over 38 widths and cannot be wrong at any of them,
 * which is the trade: the old figure fit the pill on the day it was written and
 * had no way of noticing when the pill changed.
 *
 * Below 30rem the launcher is a fixed 48px circle in the corner of the
 * viewport, not a neighbour of this row: it meets the strip only at whichever
 * scroll position happens to put the two together, exactly as the accessibility
 * launcher already does with every element on the opposite side. That is not
 * worth half the width of the announcement.
 */
@media (max-width: 30rem) {
	.jmns-ticker {
		padding-inline-end: 0;
	}

	/*
	 * What the reservation was actually buying, bought the cheap way.
	 *
	 * The case that mattered was a *focused* control under the launcher — SC
	 * 2.4.11 — and that only happens because the browser scrolls a newly
	 * focused element to the very edge of the viewport, which is the one place
	 * the stack is pinned. Extending the scroll box downwards by the height the
	 * stack occupies lands the button clear of it instead, and costs no layout
	 * at all. A tap that happens to arrive while the strip is sitting in that
	 * band is still the launcher's, exactly as it is for every other control the
	 * visitor scrolls under it.
	 *
	 * The stack's token rather than the launcher's, because the bottom edge now
	 * holds a column and not a single control: the reading-preferences launcher
	 * and the scroll-to-top button above it reach 120px up the opposite side,
	 * and a step button scrolled to the very bottom of a narrow screen is under
	 * whichever of them happens to be there.
	 */
	.jmns-ticker__step,
	.jmns-ticker__more a {
		scroll-margin-block-end: var(--jmns-stack-clear-block, 0px);
	}
}

/* Complete list, no cap: the link would point at what is already on screen. */
@media (min-width: 48.0625rem) {
	.jmns-ticker__more {
		display: none;
	}
}

/*
 * The stepper is no longer phone-only.
 *
 * It used to be hidden above 48rem because the marquee moved the row along by
 * itself — there was nothing for a desktop visitor to press. §13 removed the
 * scrolling, so the arrows are now the only way to reach the second
 * announcement at any width, and hiding them would strand it.
 */
@media (min-width: 48.0625rem) {
	.jmns-ticker__nav {
		display: flex;
		align-items: center;
		gap: var(--wp--preset--spacing--20, 0.5rem);
		flex: 0 0 auto;
		padding-inline-end: var(--wp--preset--spacing--30, 1rem);
	}
}
