/**
 * pyq.css — /pyq/ archive + single-paper inline viewer styling (PYQ-01,
 * quick 260810-nx3; archive block rewritten in quick 260810-pf2 to the approved
 * .planning/quick/260810-nx3-pyq-previous-year-papers/UI-SPEC.md).
 *
 * A NEW file rather than a PYQ block appended to syllabus.css: that stylesheet is
 * documented as syllabus-scoped and half of it styles the .llb-modal-* overlay/panel
 * chrome that PYQ has no modal for (each card navigates to the paper's own page,
 * D-nx3-03). Enqueued only on the two PYQ surfaces (functions.php), never site-wide.
 *
 * CORRECTION to this file's own shipped header, which was factually wrong. It claimed
 * to reuse "the shared .llb-empty-state / .llb-empty-state--inline chrome from
 * brand.css". The base .llb-empty-state IS in brand.css — but the --inline modifier
 * lives in syllabus.css:76, and functions.php enqueues llb-pyq with an llb-brand
 * dependency, NOT llb-syllabus. So on /pyq/ that modifier matched nothing and every
 * per-group box inherited brand.css's base padding: 3rem 1rem — six 96px-padded boxes,
 * roughly 600px of centred grey apology and the tallest thing on the page.
 *
 * The fix was to delete the USAGE, not to port the class: quick 260810-pf2 removed
 * per-group empty states entirely (a semester with no papers now renders no section at
 * all), so .llb-empty-state--inline is not referenced here at all. Do NOT copy it into
 * this file, and do NOT change the llb-brand dependency — with the per-group boxes gone
 * nothing here depends on a syllabus class, so llb-brand is now genuinely correct.
 * The class itself stays in syllabus.css, for syllabus.
 *
 * This file reuses the brand tokens (crimson --primary #B5261E, gold --secondary
 * #F5C518, off-white surfaces) and adds only the Program -> Semester heading ramp, the
 * card grid, the card itself (an anchor), and the tall PDF viewport on the single page.
 * No new custom property, no new hex literal — the only literals are the pre-existing
 * rgba( 181, 38, 30, ... ) shadow tint and rgba( 26, 26, 26, .7 ) muted text already
 * used site-wide. Spacing on the 4px scale. Brand palette only, crimson/gold, cool
 * tones are a hard no (FND-02).
 *
 * HARD RULE, stated once for both PYQ surfaces: every focus ring uses var( --ring )
 * (crimson, 6.1:1 on both page surfaces). Gold on a light surface measures 1.6:1 and
 * fails WCAG 1.4.11, so gold is NEVER a focus indicator and never a state-carrying
 * border on this feature (UI-SPEC 6.2).
 *
 * @package LLB_Child
 */

/* ---- Archive: content-driven Program -> Semester ramp ----------------------- */
.llb-archive--pyq .llb-pyq-program {
	margin: 2rem 0 2.5rem;
}
.llb-pyq-program__title {
	font-size: clamp( 1.4rem, 3vw, 1.9rem );
	font-weight: 700;
	margin: 0 0 1rem;
	padding-bottom: .5rem;
	color: var( --primary );
	border-bottom: 2px solid var( --secondary );
	/* A long or space-less owner term name must not overflow at 360px (State D). */
	overflow-wrap: anywhere;
}
.llb-pyq-semester {
	margin: 0 0 1.5rem;
}
/* 1.125rem/700, up from the shipped 1.1rem/600: with the year <h4> deleted this is
   now the ONLY in-page landmark a student scans for, so it has to out-weigh the
   600-weight card titles beneath it. On-scale size, one weight step, no new token. */
.llb-pyq-semester__title {
	font-size: 1.125rem;
	font-weight: 700;
	margin: 0 0 .75rem;
	color: var( --foreground );
	overflow-wrap: anywhere;
}

/* Now a <ul> (assistive tech announces "list, N items"), so reset the list chrome.
   Same responsive ramp as the syllabus archive: 1 / 2 / 3 columns. FIXED column
   counts are deliberate — auto-fill/minmax is wrong here, because a lone card must
   occupy ONE column and stay aligned with its neighbours in other groups rather than
   stretching full-bleed. */
.llb-pyq-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: 1fr;
	gap: .75rem;
}
@media ( min-width: 640px ) {
	.llb-pyq-list {
		grid-template-columns: repeat( 2, 1fr );
	}
}
@media ( min-width: 960px ) {
	.llb-pyq-list {
		grid-template-columns: repeat( 3, 1fr );
	}
}

/* The WHOLE card is the link to /pyq/<paper>/ (owner: "user clicks on those boxes").
   flex column + align-items: flex-start is what stacks the title above the gold year
   badge and keeps the badge shrink-wrapped to its text. Padding is 1rem on all sides,
   down from the shipped 1rem 1.1rem: 17.6px is off the 4px scale and the visual delta
   is 1.6px (syllabus.css keeps its own value — not our file, not our change).
   No min-height: one title line + 2x1rem padding + badge is ~74px, already well over
   the 44px tap target. */
.llb-pyq-card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .5rem;
	padding: 1rem;
	background: var( --card );
	border: 1px solid var( --border );
	border-left: 4px solid var( --primary );
	border-radius: 12px;
	text-decoration: none;
	color: var( --foreground );
	transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease;
}
.llb-pyq-card:hover,
.llb-pyq-card:focus-visible {
	border-color: var( --primary );
	box-shadow: 0 4px 14px rgba( 181, 38, 30, .16 );
	transform: translateY( -2px );
}
/* Focus ring is crimson (--ring), never a browser default cool tone, never gold. */
.llb-pyq-card:focus-visible {
	outline: 3px solid var( --ring );
	outline-offset: 2px;
}
/* Inherited 600 / 1.35 left alone on purpose — restyling it would be cosmetic churn
   with no problem behind it. And deliberately NO line-clamp: a truncated paper title
   is worse than a three-line card. */
.llb-pyq-card__title {
	display: block;
	font-weight: 600;
	color: var( --foreground );
	line-height: 1.35;
}
/* .llb-pyq-card__year needs NO declaration of its own: the gold .llb-badge is already
   positioned by its parent's flex-direction: column + align-items: flex-start. The
   hook exists in the markup; a rule here would only duplicate the parent. */

@media ( prefers-reduced-motion: reduce ) {
	.llb-pyq-card {
		transition: none;
	}
	.llb-pyq-card:hover,
	.llb-pyq-card:focus-visible {
		transform: none;
	}
}

/* Coverage note, once, after the last program section. With empty groups no longer
   rendered, a Sem-3 student seeing only "Semester 1" cannot otherwise tell whether the
   site has nothing for them or the page is broken. 6.3:1 on --background. */
.llb-pyq-note {
	margin: .5rem 0 0;
	font-size: .9rem;
	color: rgba( 26, 26, 26, .7 );
	text-align: center;
}

/* The page-level empty state's two cross-links. .llb-empty-state itself is NOT styled
   here: its inherited 3rem 1rem is correct for a whole-page empty state — the bug was
   applying it six times. min-height works on these buttons because brand.css gives
   .btn-primary / .btn-secondary display: inline-flex (22 / 35). */
.llb-pyq-empty-actions {
	display: flex;
	flex-wrap: wrap;
	gap: .75rem;
	justify-content: center;
	margin-top: 1.5rem;
}
.llb-pyq-empty-actions .btn-primary,
.llb-pyq-empty-actions .btn-secondary {
	min-height: 44px;
}

/* ---- Archive: the server-side search + filter bar (quick 260810-qw0) -------- */
/* brand.css (603-652) ALREADY styles every class the bar emits — .llb-library-filter
   card, .llb-filter-form flex row, .llb-filter-field column + label, the white
   select/input, .llb-filter-actions — so this block adds ONLY what brand.css does not
   give: 44px tap targets, deterministic mobile stacking and a wider search field.
   If you find yourself restyling the bar here, stop: brand.css already did.

   FOCUS INDICATORS: nothing is added, on purpose. brand.css's
   .llb-filter-field select:focus / input:focus already paint crimson var( --primary )
   plus an rgba( 181, 38, 30, .25 ) ring, which is what overrides the native <select>'s
   UA accent/focus colour. Gold is NEVER a focus indicator (1.6:1 on white, fails WCAG
   1.4.11 — the hard rule in this file's header), and no cool tone is introduced here.

   Every selector is scoped to .llb-archive--pyq, matching this file's existing
   .llb-single--pyq .llb-breadcrumb__list precedent, so brand.css and the three other
   archives that share these classes are provably untouched. */

/* brand.css's .55rem .7rem padding at .9rem font yields roughly 38px — under the
   44px tap target this project holds itself to. */
.llb-archive--pyq .llb-filter-field select,
.llb-archive--pyq .llb-filter-field input[type="search"] {
	min-height: 44px;
}
/* Same fix, same reason, as .llb-pyq-empty-actions above: min-height bites because
   brand.css gives .btn-primary / .btn-secondary display: inline-flex. */
.llb-archive--pyq .llb-filter-actions .btn-primary,
.llb-archive--pyq .llb-filter-actions .btn-secondary {
	min-height: 44px;
}
/* The owner's sketch shows the search field visually long beside two compact
   dropdowns. One declaration, and it also keeps the search first on its own row at
   mid widths. */
.llb-archive--pyq .llb-pyq-filter__search {
	flex: 2 1 16rem;
}

/* Phone: one control per row, DETERMINISTICALLY. At 360px, .container-custom's
   gutters plus .llb-library-filter's 1rem 1.25rem padding leave roughly 288px of inner
   width, so brand.css's flex: 1 1 12rem (a 192px basis) already wraps to one field per
   row today — this block makes that guaranteed instead of emergent, so a future padding
   change cannot silently produce two 140px controls side by side. Four controls never
   share a row below 640px. */
@media ( max-width: 639px ) {
	.llb-archive--pyq .llb-filter-field {
		flex-basis: 100%;
	}
	.llb-archive--pyq .llb-filter-actions {
		flex: 1 1 100%;
	}
}

/* The filtered result count. NOT folded into .llb-pyq-note: that rule's comment states
   it is deliberately static prose with no live region, and this line is a role="status".
   Two purposes, two selectors, and the note's comment stays true. Same muted tint used
   twice already in this file (6.3:1 on --background) — no new custom property, no new
   hex literal. */
.llb-pyq-results {
	margin: 0 0 1rem;
	font-size: .9rem;
	color: rgba( 26, 26, 26, .7 );
}

/* ---- Single paper: inline, view-only PDF viewport --------------------------- */
/* position: relative is the containing block for the loading placeholder below. */
.llb-pyq-viewer {
	position: relative;
	width: 100%;
	margin: 1.25rem 0;
	background: var( --card );
	border: 1px solid var( --border );
	border-radius: 12px;
	overflow: hidden;
}
/* Sits BEHIND the frame and is covered when PDF.js paints. 6.3:1 on --card. */
.llb-pyq-viewer__loading {
	position: absolute;
	inset: 0;
	margin: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	color: rgba( 26, 26, 26, .7 );
	font-size: .9rem;
}
/* background: transparent, NOT the shipped var( --card ): an opaque frame background
   paints over the loading placeholder instantly and makes it dead markup.
   Height is a two-declaration pair with the fallback FIRST — svh measures the SMALL
   viewport, so the frame stops overflowing when a mobile URL bar is showing, and the
   vh line is the fallback for engines without svh. */
.llb-pyq-frame {
	position: relative;
	z-index: 1;
	display: block;
	width: 100%;
	height: min( 80vh, 900px );
	height: min( 80svh, 900px );
	border: 0;
	background: transparent;
}
/* The inherited .5rem 1rem padding yields only ~40px. */
.llb-single-pyq__back .btn-secondary {
	min-height: 44px;
}

/* Breadcrumb: two overrides SCOPED to .llb-single--pyq so brand.css stays untouched
   (UI-SPEC 6.3). The site-wide .6 alpha measures ~4.5:1 at .82rem — right on the AA
   line — and .82rem text alone is too small a hit area. The site-wide values are
   pre-existing and out of scope for this task. */
.llb-single--pyq .llb-breadcrumb__list {
	color: rgba( 26, 26, 26, .7 );
}
.llb-single--pyq .llb-breadcrumb__list a {
	padding-block: .35rem;
}

/* Phone: a tall, FULL-BLEED PDF viewport (the paper is the whole point of the page).
   At 360px .container-custom's gutters leave PDF.js only 328px, and an A4 page scaled
   to that is near unreadable. margin-inline: calc( 50% - 50vw ) reclaims the gutters
   gutter-agnostically, so it works at both the 1rem (<640) and 1.5rem (640-767)
   gutters with no second breakpoint. */
@media ( max-width: 767px ) {
	.llb-pyq-viewer {
		width: 100vw;
		max-width: 100vw;
		margin-inline: calc( 50% - 50vw );
		margin-top: 1rem;
		margin-bottom: 1rem;
		border-radius: 0;
		border-inline: 0;
	}
	.llb-pyq-frame {
		height: 82vh;
		min-height: 70vh;
	}
	.llb-pyq-frame {
		height: 82svh;
	}
}
