/* Atfal Portal — application shell.
   Built on tokens.css so it stays on-brand with atfal.ca, but visually its own
   product: no marketing chrome, calmer surfaces, larger touch targets.
   Scoped to .atfal-portal-body / .ap-* so nothing leaks either direction. */

.atfal-portal-body {
	margin: 0;
	font-family: var(--font-body);
	color: var(--color-grey-700);
	background: var(--color-cool-grey);
	-webkit-font-smoothing: antialiased;
}
.atfal-portal-body * { box-sizing: border-box; }
.atfal-portal-body a { color: var(--color-red); text-decoration: none; }
.atfal-portal-body a:hover { text-decoration: underline; }
/* Neutralise element-level typography from the parent theme for anything the
   portal renders. Cheap insurance: inheritance alone is not enough against a
   direct `body h1 { ... }` rule. */
.atfal-portal-body h1,
.atfal-portal-body h2,
.atfal-portal-body h3,
.atfal-portal-body legend,
.atfal-portal-body label,
.atfal-portal-body input,
.atfal-portal-body button {
	font-family: var(--font-body);
}
.ap-shell {
	min-height: 100vh;
	display: flex;
	flex-direction: column;
}
/* Header */
.ap-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
	padding: var(--space-4) var(--space-5);
	background: var(--color-ink);
	color: var(--color-white);
}
.ap-header__brand {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3);
	color: var(--color-white) !important;
	text-decoration: none !important;
}
.ap-header__mark {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--color-red);
	box-shadow: 0 0 0 4px rgba(201,33,39,0.25);
}
.ap-header__title {
	font-weight: var(--weight-bold);
	letter-spacing: 0.01em;
}
.ap-header__user {
	display: inline-flex;
	align-items: center;
	gap: var(--space-4);
	font-size: var(--text-sm);
}
.ap-header__handle {
	color: var(--color-grey-200);
	font-weight: var(--weight-semibold);
}
.ap-header__logout,
.ap-header__back {
	color: var(--color-grey-300) !important;
	font-size: var(--text-sm);
}
.ap-header__logout:hover,
.ap-header__back:hover { color: var(--color-white) !important; }
/* Verse strip — always visible under the header */
.ap-verse-bar {
	background: var(--color-red-tint);
	border-bottom: 1px solid rgba(201,33,39,0.2);
}
.ap-verse-bar__inner {
	max-width: 720px;
	margin: 0 auto;
	padding: var(--space-4) var(--space-5);
	text-align: center;
}
.ap-verse-bar__text {
	margin: 0 0 var(--space-2);
	font-family: var(--font-display);
	font-style: italic;
	font-size: var(--text-base);
	line-height: var(--leading-relaxed);
	color: var(--color-ink);
}
.ap-verse-bar__ref {
	margin: 0;
	font-size: var(--text-xs);
	font-weight: var(--weight-semibold);
	letter-spacing: 0.03em;
	color: var(--color-red-deep);
}
.ap-verse-bar__ref a { color: var(--color-red-deep) !important; }
/* Login splash */
.ap-splash {
	position: fixed;
	inset: 0;
	z-index: 100;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-5);
	background: rgba(23,24,26,0.75);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
}
.ap-splash__card {
	width: 100%;
	max-width: 480px;
	background: var(--color-white);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
	padding: var(--space-7) var(--space-6);
	text-align: center;
}
.ap-splash__eyebrow {
	margin: 0 0 var(--space-5);
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--color-red);
}
.ap-splash__verse {
	margin: 0 0 var(--space-4);
	padding: 0;
	border: 0;
	font-family: var(--font-display);
	font-style: italic;
	font-size: var(--text-h3);
	line-height: var(--leading-relaxed);
	color: var(--color-ink);
}
.ap-splash__ref {
	margin: 0 0 var(--space-6);
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-grey-600);
}
.ap-splash__ref a { color: var(--color-red-deep) !important; }
.ap-splash__btn { width: 100%; }
@media (max-width: 480px) {
	.ap-splash__card { padding: var(--space-6) var(--space-5); }
	.ap-splash__verse { font-size: var(--text-lg); }
}
/* Main */
.ap-main {
	flex: 1;
	display: flex;
	align-items: flex-start;
	justify-content: center;
	padding: var(--space-8) var(--space-5);
}
.ap-card {
	width: 100%;
	max-width: 420px;
	background: var(--color-white);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-md);
	padding: var(--space-7) var(--space-6);
}
.ap-card--wide { max-width: 720px; }
.ap-card__title {
	/* font-family declared explicitly: the parent theme sets
	   `body h1{font-family:'Manrope'}` directly on the element, and a direct
	   element rule beats an inherited value from .atfal-portal-body. */
	font-family: var(--font-body);
	margin: 0 0 var(--space-2);
	font-size: var(--text-h2);
	font-weight: var(--weight-heavy);
	letter-spacing: -0.01em;
	color: var(--color-ink);
}
.ap-card__lead {
	margin: 0 0 var(--space-6);
	font-size: var(--text-base);
	line-height: var(--leading-relaxed);
	color: var(--color-grey-600);
}
.ap-card__foot,
.ap-card__help {
	margin: var(--space-5) 0 0;
	font-size: var(--text-sm);
	color: var(--color-grey-600);
	text-align: center;
}
.ap-card__help {
	margin-top: var(--space-3);
	font-size: var(--text-xs);
}
/* Notices */
.ap-notice {
	margin: 0 0 var(--space-5);
	padding: var(--space-3) var(--space-4);
	border-radius: var(--radius-md);
	font-size: var(--text-sm);
	line-height: var(--leading-normal);
}
.ap-notice--error {
	background: var(--color-red-tint);
	color: var(--color-red-deep);
	border: 1px solid rgba(201,33,39,0.25);
}
.ap-notice--success {
	background: #e8f5ec;
	color: #1f6b3a;
	border: 1px solid rgba(31,107,58,0.25);
}
/* Forms */
.ap-form { display: flex; flex-direction: column; gap: var(--space-5); }
.ap-field { display: block; }
.ap-field__label {
	display: block;
	margin-bottom: var(--space-2);
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-ink);
}
.ap-field__input {
	width: 100%;
	/* 16px minimum: anything smaller makes iOS Safari zoom on focus, which is
	   disorienting on a form a child is filling in. */
	font-size: 16px;
	font-family: inherit;
	color: var(--color-ink);
	background: var(--color-white);
	padding: var(--space-3) var(--space-4);
	border: 1px solid var(--color-grey-300);
	border-radius: var(--radius-md);
	min-height: 48px;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.ap-field__input:focus {
	outline: none;
	border-color: var(--color-red);
	box-shadow: var(--focus-ring);
}
.ap-field__hint {
	display: block;
	margin-top: var(--space-2);
	font-size: var(--text-xs);
	color: var(--color-grey-600);
}
/* Handle picker */
.ap-handles { border: 0; margin: 0; padding: 0; }
.ap-handles__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--space-3);
	margin: var(--space-4) 0 var(--space-4);
}
.ap-handle {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 52px;
	padding: var(--space-3);
	text-align: center;
	background: var(--color-white);
	border: 1.5px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	cursor: pointer;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-handle:hover { border-color: var(--color-grey-300); }
/* The radio itself is visually hidden but still focusable and screen-reader
   reachable — not display:none, which would remove it from the tab order. */
.ap-handle input {
	position: absolute;
	opacity: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	cursor: pointer;
}
.ap-handle__name {
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-ink);
}
.ap-handle input:checked ~ .ap-handle__name { color: var(--color-red-deep); }
.ap-handle:has(input:checked) {
	border-color: var(--color-red);
	background: var(--color-red-tint);
}
.ap-handle:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.ap-handles__refresh { width: 100%; justify-content: center; }
/* Buttons */
.ap-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	min-height: 48px;
	padding: var(--space-3) var(--space-5);
	font-family: inherit;
	font-size: var(--text-button);
	font-weight: var(--weight-semibold);
	border: 1px solid transparent;
	border-radius: var(--radius-md);
	cursor: pointer;
	text-decoration: none !important;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}
.ap-btn--primary {
	background: var(--color-red);
	color: var(--color-white) !important;
}
.ap-btn--primary:hover { background: var(--color-red-deep); }
.ap-btn--ghost {
	background: transparent;
	color: var(--color-grey-700) !important;
	border-color: var(--color-grey-300);
}
.ap-btn--ghost:hover { background: var(--color-grey-100); }
.ap-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* Course + lesson lists */
.ap-crumb { margin: 0 0 var(--space-4); font-size: var(--text-sm); }
.ap-course-list, .ap-lesson-list { list-style: none; margin: 0; padding: 0; }
.ap-course { margin-bottom: var(--space-4); }
.ap-course__link {
	display: block;
	padding: var(--space-5);
	background: var(--color-white);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	text-decoration: none !important;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.ap-course__link:hover, .ap-course__link:focus-visible {
	border-color: var(--color-red);
	box-shadow: var(--shadow-sm);
}
.ap-course__head {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: var(--space-4); margin-bottom: var(--space-3);
}
.ap-course__title { font-weight: var(--weight-bold); color: var(--color-ink); }
.ap-course__count { font-size: var(--text-xs); color: var(--color-grey-600); white-space: nowrap; }
.ap-progress {
	display: block; height: 8px; border-radius: 999px;
	background: var(--color-grey-200); overflow: hidden;
}
.ap-progress--lg { height: 12px; margin-bottom: var(--space-2); }
.ap-progress__bar {
	display: block; height: 100%; border-radius: 999px;
	background: var(--color-red); transition: width 0.3s ease;
}
.ap-progress__label {
	margin: 0 0 var(--space-6);
	font-size: var(--text-sm); color: var(--color-grey-600);
}
.ap-lesson { margin-bottom: var(--space-3); }
.ap-lesson__link {
	display: flex; align-items: center; gap: var(--space-4);
	padding: var(--space-4);
	background: var(--color-white);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	text-decoration: none !important;
	transition: border-color 0.15s ease;
	min-height: 56px;
}
.ap-lesson__link:hover, .ap-lesson__link:focus-visible { border-color: var(--color-red); }
.ap-lesson__marker {
	flex-shrink: 0;
	width: 32px; height: 32px;
	display: flex; align-items: center; justify-content: center;
	border-radius: 50%;
	background: var(--color-grey-100);
	color: var(--color-grey-600);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
}
.ap-lesson--done .ap-lesson__marker { background: var(--color-red); color: var(--color-white); }
.ap-lesson__title { flex: 1; color: var(--color-ink); font-weight: var(--weight-medium); }
.ap-lesson__badge {
	font-size: var(--text-xs); font-weight: var(--weight-bold);
	color: var(--color-red-deep); background: var(--color-red-tint);
	padding: var(--space-1) var(--space-3); border-radius: 999px;
}
.ap-lesson__step {
	margin: 0 0 var(--space-2);
	font-size: var(--text-xs); font-weight: var(--weight-bold);
	text-transform: uppercase; letter-spacing: 0.06em;
	color: var(--color-red);
}
.ap-lesson__body {
	margin: var(--space-5) 0 var(--space-6);
	font-size: var(--text-base); line-height: var(--leading-relaxed);
	color: var(--color-grey-700);
}
.ap-lesson__body p { margin: 0 0 var(--space-4); }
.ap-lesson__body img { max-width: 100%; height: auto; border-radius: var(--radius-md); }
.ap-lesson__actions {
	padding-top: var(--space-5);
	border-top: 1px solid var(--color-grey-200);
}
.ap-lesson__done-note {
	margin: 0 0 var(--space-4);
	font-weight: var(--weight-semibold); color: #1f6b3a;
}
.ap-lesson__nav {
	display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-4);
}
/* Qur'an reference links (out to alislam.org) */
.ap-quran-ref {
	display: inline-flex;
	align-items: baseline;
	gap: 4px;
	padding: 2px 8px;
	background: var(--color-red-tint);
	color: var(--color-red-deep) !important;
	border-radius: var(--radius-sm);
	font-weight: var(--weight-semibold);
	text-decoration: none !important;
	white-space: nowrap;
}
.ap-quran-ref:hover, .ap-quran-ref:focus-visible {
	background: var(--color-red);
	color: var(--color-white) !important;
}
/* Recovery code display */
.ap-recovery {
	margin: 0 0 var(--space-5);
	padding: var(--space-6) var(--space-4);
	text-align: center;
	background: var(--color-grey-100);
	border: 2px dashed var(--color-grey-300);
	border-radius: var(--radius-md);
}
.ap-recovery__code {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 20px;
	font-weight: 700;
	letter-spacing: 0.08em;
	color: var(--color-ink);
	word-break: break-all;
}
.ap-field__input--code {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	letter-spacing: 0.06em;
}
.ap-notice--warn {
	background: #fff4e5;
	color: #8a5300;
	border: 1px solid rgba(138,83,0,0.25);
}
/* Dashboard placeholder */
.ap-placeholder {
	padding: var(--space-6);
	background: var(--color-grey-100);
	border-radius: var(--radius-md);
	font-size: var(--text-sm);
	line-height: var(--leading-relaxed);
	color: var(--color-grey-600);
}
.ap-placeholder p { margin: 0; }
/* Points summary on the dashboard */
.ap-stats {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
	margin: 0 0 var(--space-6);
}
.ap-stat {
	flex: 1 1 auto;
	min-width: 96px;
	/* 44px minimum target, per the project a11y checklist. */
	min-height: 44px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 2px;
	padding: var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	background: var(--color-white);
	text-align: center;
}
.ap-stat__value {
	font-size: var(--text-h3);
	font-weight: var(--weight-heavy);
	font-variant-numeric: tabular-nums;
	color: var(--color-ink);
	line-height: 1;
}
.ap-stat__label {
	font-size: var(--text-xs);
	font-weight: var(--weight-medium);
	color: var(--color-grey-600);
}
.ap-stat--link {
	text-decoration: none;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-stat--link:hover,
.ap-stat--link:focus-visible {
	border-color: var(--color-red);
	background: var(--color-red-tint);
}
.ap-stat--link:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
}
.ap-stat--link .ap-stat__value { color: var(--color-red); }
/* Always-available section links on the dashboard */
.ap-quicknav {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2);
	margin: 0 0 var(--space-6);
}
.ap-quicknav__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: var(--space-2) var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: 999px;
	background: var(--color-white);
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-ink);
	text-decoration: none;
	transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}
.ap-quicknav__link:hover,
.ap-quicknav__link:focus-visible {
	border-color: var(--color-red);
	color: var(--color-red);
	background: var(--color-red-tint);
}
.ap-quicknav__link:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
}
/* Challenge list */
.ap-challenge-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--space-3);
}
.ap-challenge-item__link {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: center;
	gap: var(--space-2) var(--space-4);
	min-height: 56px;
	padding: var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	background: var(--color-white);
	text-decoration: none;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-challenge-item__link:hover,
.ap-challenge-item__link:focus-visible {
	border-color: var(--color-red);
	background: var(--color-red-tint);
}
.ap-challenge-item__link:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
}
.ap-challenge-item__title {
	font-size: var(--text-base);
	font-weight: var(--weight-semibold);
	color: var(--color-ink);
}
.ap-challenge-item__meta {
	grid-column: 1;
	font-size: var(--text-xs);
	color: var(--color-grey-600);
}
.ap-challenge-item__cta {
	grid-row: 1 / span 2;
	grid-column: 2;
	font-size: var(--text-lg);
	color: var(--color-red);
}
.ap-challenge-item__done {
	grid-row: 1 / span 2;
	grid-column: 2;
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-red-deep);
	white-space: nowrap;
}
.ap-challenge-item--done .ap-challenge-item__link {
	background: var(--color-grey-100);
}
.ap-challenge__done-note {
	margin: 0 0 var(--space-5);
	font-size: var(--text-sm);
	color: var(--color-grey-600);
}
/* Ordering challenge */
.ap-steps {
	list-style: none;
	margin: 0 0 var(--space-5);
	padding: 0;
	display: grid;
	gap: var(--space-2);
	/* Counter rather than <ol> markers: the number must reflect the CURRENT
	   position after a move, and list markers on a re-ordered DOM do that
	   correctly while a hardcoded number would not. */
	counter-reset: ap-step;
}
.ap-step {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: var(--space-3);
	min-height: 56px;
	padding: var(--space-3) var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	background: var(--color-white);
	counter-increment: ap-step;
}
.ap-step__handle::before {
	content: counter(ap-step);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
	background: var(--color-ink);
	color: var(--color-white);
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	font-variant-numeric: tabular-nums;
}
.ap-step__text {
	font-size: var(--text-base);
	color: var(--color-ink);
	overflow-wrap: anywhere;
}
.ap-step__controls {
	display: flex;
	gap: var(--space-2);
}
.ap-step__move {
	/* 44px minimum touch target, per the project a11y checklist. */
	width: 44px;
	height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-sm);
	background: var(--color-white);
	color: var(--color-ink);
	font-size: var(--text-base);
	line-height: 1;
	cursor: pointer;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-step__move:hover:not(:disabled) {
	border-color: var(--color-red);
	color: var(--color-red);
}
.ap-step__move:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
	border-color: var(--color-red);
}
.ap-step__move:disabled {
	opacity: 0.35;
	cursor: default;
}
.ap-challenge__status {
	margin: 0 0 var(--space-4);
	font-size: var(--text-sm);
	color: var(--color-grey-600);
	min-height: 1.2em;
}
/* Quiz entry point on a lesson */
.ap-quiz-cta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
	margin-top: var(--space-6);
	padding: var(--space-5);
	border: 1px solid var(--color-grey-200);
	border-left: 3px solid var(--color-red);
	border-radius: var(--radius-md);
	background: var(--color-white);
}
.ap-quiz-cta__title {
	font-family: var(--font-body);
	margin: 0 0 2px;
	font-size: var(--text-h3);
	font-weight: var(--weight-bold);
	color: var(--color-ink);
}
.ap-quiz-cta__meta,
.ap-quiz-cta__closed {
	margin: 0;
	font-size: var(--text-sm);
	color: var(--color-grey-600);
}
/* Quiz runner */
.ap-quiz__progress {
	margin: 0 0 var(--space-2);
	font-size: var(--text-xs);
	font-weight: var(--weight-semibold);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-grey-600);
}
.ap-quiz__question {
	margin-top: var(--space-5);
}
.ap-quiz__desc {
	margin-bottom: var(--space-5);
	font-size: var(--text-base);
	line-height: var(--leading-relaxed);
	color: var(--color-grey-700);
}
.ap-choices {
	border: 0;
	margin: 0 0 var(--space-6);
	padding: 0;
	display: grid;
	gap: var(--space-3);
}
.ap-choices__legend {
	padding: 0;
	margin-bottom: var(--space-3);
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-grey-600);
}
/*
 * Whole row is the label, so the tap target is the full card rather than the
 * 16px control — this is used by seven-year-olds on phones.
 */
.ap-choice {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	min-height: 56px;
	padding: var(--space-3) var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: var(--radius-md);
	background: var(--color-white);
	cursor: pointer;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-choice:hover {
	border-color: var(--color-grey-300);
}
.ap-choice__input {
	flex-shrink: 0;
	width: 20px;
	height: 20px;
	accent-color: var(--color-red);
	margin: 0;
	cursor: pointer;
}
/* Focus lives on the row, not the hidden-ish control, so keyboard users can
   see where they are. :focus-within is what carries it. */
.ap-choice:focus-within {
	border-color: var(--color-red);
	box-shadow: var(--focus-ring);
}
.ap-choice:has(.ap-choice__input:checked) {
	border-color: var(--color-red);
	background: var(--color-red-tint);
}
.ap-choice__body {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	min-width: 0;
}
.ap-choice__text {
	font-size: var(--text-base);
	color: var(--color-ink);
	overflow-wrap: anywhere;
}
.ap-choice__img {
	width: 56px;
	height: 56px;
	object-fit: cover;
	border-radius: var(--radius-sm);
}
/* Result */
.ap-result {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	padding: var(--space-6);
	margin-bottom: var(--space-5);
	border-radius: var(--radius-md);
	text-align: center;
}
.ap-result--pass {
	background: var(--color-red-tint);
	color: var(--color-red-deep);
}
.ap-result--fail {
	background: var(--color-grey-100);
	color: var(--color-grey-700);
}
.ap-result__grade {
	font-size: 2.75rem;
	font-weight: var(--weight-heavy);
	line-height: 1;
	font-variant-numeric: tabular-nums;
}
.ap-result__label {
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	text-transform: uppercase;
	letter-spacing: 0.06em;
}
.ap-result__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
	margin-top: var(--space-5);
}
/* Badges */
.ap-badges {
	margin-top: var(--space-6);
	padding-top: var(--space-5);
	border-top: 1px solid var(--color-grey-200);
}
.ap-badges__title {
	/* Explicit font-family: the parent theme sets `body h2{font-family:'Manrope'}`
	   directly on the element, and a direct element rule beats inheritance. */
	font-family: var(--font-body);
	margin: 0 0 var(--space-4);
	font-size: var(--text-h3);
	font-weight: var(--weight-bold);
	color: var(--color-ink);
}
.ap-badges__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
	gap: var(--space-3);
}
.ap-badge {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: var(--space-3) var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-left: 3px solid var(--color-red);
	border-radius: var(--radius-sm);
	background: var(--color-white);
}
.ap-badge__label {
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--color-ink);
}
.ap-badge__desc {
	font-size: var(--text-xs);
	line-height: var(--leading-normal);
	color: var(--color-grey-600);
}
/* Leaderboard */
.ap-board {
	list-style: none;
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--color-grey-200);
}
.ap-board__row {
	display: grid;
	grid-template-columns: 2.25rem 1fr auto;
	align-items: center;
	gap: var(--space-3);
	min-height: 44px;
	padding: var(--space-3) var(--space-2);
	border-bottom: 1px solid var(--color-grey-200);
}
.ap-board__rank {
	font-variant-numeric: tabular-nums;
	font-weight: var(--weight-bold);
	color: var(--color-grey-300);
	text-align: right;
}
.ap-board__handle {
	font-weight: var(--weight-medium);
	color: var(--color-ink);
	overflow-wrap: anywhere;
}
.ap-board__handle strong,
.ap-board__handle small,
.ap-mini__handle strong,
.ap-mini__handle small { display: block; }
.ap-board__handle small,
.ap-mini__handle small {
	color: var(--ap-text-mute, var(--color-grey-500));
	font-size: var(--text-xs);
	font-weight: var(--weight-medium);
}
.ap-board__points {
	font-variant-numeric: tabular-nums;
	font-weight: var(--weight-semibold);
	color: var(--color-ink);
	white-space: nowrap;
}
/* The member's own row — the one thing on this screen worth marking in red. */
.ap-board__row--me {
	background: var(--color-red-tint);
}
.ap-board__row--me .ap-board__rank,
.ap-board__row--me .ap-board__points {
	color: var(--color-red-deep);
}
.ap-board__you {
	display: inline-block;
	margin-left: var(--space-2);
	padding: 1px 6px;
	border-radius: 999px;
	background: var(--color-red);
	color: var(--color-white);
	font-size: 11px;
	font-weight: var(--weight-bold);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	vertical-align: middle;
}
/*
 * The member's own row when they rank below the published top N. The gap is
 * intentional — it signals "further down the list", not "next place".
 */
.ap-board--own {
	margin-top: var(--space-4);
	border-top: 1px dashed var(--color-grey-200);
}
.ap-board--own .ap-board__row { border-bottom: none; }
.ap-board__note {
	margin: var(--space-5) 0 0;
	font-size: var(--text-xs);
	color: var(--color-grey-600);
}
/* Footer */
.ap-footer {
	padding: var(--space-5);
	text-align: center;
	font-size: var(--text-xs);
	color: var(--color-grey-600);
}
@media (max-width: 480px) {
	.ap-main { padding: var(--space-5) var(--space-4); }
	.ap-card { padding: var(--space-6) var(--space-5); border-radius: var(--radius-md); }
	.ap-handles__grid { grid-template-columns: 1fr; }
	.ap-board__row { grid-template-columns: 2rem 1fr auto; padding: var(--space-3) 0; }
	.ap-stat { padding: var(--space-3); }
	.ap-stat__value { font-size: var(--text-lg); }
	.ap-quiz-cta { flex-direction: column; align-items: stretch; }
	/* Padding and text shrink on small screens; the move buttons deliberately
	   do NOT — they stay at the 44px minimum, since a phone is exactly where a
	   child is tapping them. */
	.ap-step { padding: var(--space-2) var(--space-3); gap: var(--space-2); }
	.ap-step__text { font-size: var(--text-sm); }
	.ap-result__grade { font-size: 2.25rem; }
	.ap-result__actions .ap-btn { flex: 1 1 100%; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
	.ap-field__input, .ap-handle, .ap-btn, .ap-stat--link { transition: none; }
}
/* ===========================================================================
   DASHBOARD
   Modular grid built for 7–15 year olds: generous rounding, a clear icon per
   module, and one accent hue per module so a child can find "my Salat" or
   "games" by colour before reading the label. The accents are muted so the
   brand red still reads as the primary action colour rather than one voice in
   a crowd.
   =========================================================================== */

.ap-dash {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
}
/* Icons — inline SVG, sized by the element that holds them. */
.ap-i { width: 1em; height: 1em; display: block; }
/*
 * WordPress's own class, aliased onto the portal utility.
 *
 * The portal dequeues the theme stylesheet, which is where screen-reader-text
 * is normally defined — so any core- or plugin-generated markup using it would
 * render its hidden text visibly on the page. Aliasing costs one selector and
 * removes a whole class of leak.
 */
.screen-reader-text,
.ap-sr {
	position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
	overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* ---- Greeting ---- */
.ap-hello {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
}
.ap-hello__salam {
	margin: 0 0 2px;
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-grey-600);
}
.ap-hello__dash {
	font-size: var(--text-lg);
	font-weight: var(--weight-medium);
	color: var(--color-grey-300);
	/* Nudged onto the optical centre between two runs of very different size. */
	transform: translateY(-2px);
}
.ap-hello__name {
	font-family: var(--font-body);
	margin: 0;
	font-size: var(--text-h1);
	font-weight: var(--weight-heavy);
	letter-spacing: -0.02em;
	line-height: 1.05;
	color: var(--color-ink);
}
.ap-tally {
	display: flex;
	gap: var(--space-2);
	list-style: none;
	margin: 0;
	padding: 0;
}
.ap-tally li {
	min-width: 84px;
	padding: var(--space-3) var(--space-4);
	border-radius: 14px;
	background: var(--color-white);
	border: 1px solid var(--color-grey-200);
	text-align: center;
}
.ap-tally__n {
	display: block;
	font-size: var(--text-h3);
	font-weight: var(--weight-heavy);
	font-variant-numeric: tabular-nums;
	line-height: 1.1;
	color: var(--color-ink);
}
.ap-tally__l {
	display: block;
	font-size: 11px;
	font-weight: var(--weight-semibold);
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--color-grey-600);
}
/* ---- Verse module ---- */
/*
 * "Heavenly light": a warm golden glow in the upper left falling away into deep
 * emerald and teal. Two layers, no image and no shapes.
 *
 * The gold is a radial falloff rather than a gradient stop across the whole
 * card on purpose — a large flat gold area would drop white text to roughly
 * 2:1 contrast. Keeping the base dark holds the verse well above AA at every
 * point on the card.
 */
.ap-verse {
	position: relative;
	overflow: hidden;
	border-radius: 20px;
	background:
		radial-gradient(125% 105% at 6% -10%, rgba(244, 198, 122, 0.55) 0%, rgba(244, 198, 122, 0.16) 34%, rgba(244, 198, 122, 0) 56%),
		linear-gradient(135deg, #17715c 0%, #0d5348 55%, #0a3b38 100%);
	color: #fff;
}
.ap-verse__inner {
	position: relative;
	padding: var(--space-6) var(--space-6) var(--space-5);
}
.ap-verse__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 var(--space-4);
	font-size: 12px;
	font-weight: var(--weight-bold);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255,255,255,0.78);
}
.ap-verse__eyebrow .ap-i { width: 16px; height: 16px; }
.ap-verse__text {
	font-family: var(--font-display);
	margin: 0 0 var(--space-4);
	font-size: clamp(1.125rem, 1rem + 0.7vw, 1.5rem);
	line-height: 1.5;
	max-width: 54ch;
	color: #fff;
}
.ap-verse__ref {
	margin: 0 0 var(--space-4);
	font-size: var(--text-sm);
	color: rgba(255,255,255,0.78);
}
/* ---- Grid of modules ---- */
/*
 * Twelve-column grid.
 *
 * Regular modules span 6 (two per row) rather than 4, because there are exactly
 * four of them — at span 4 the fourth would sit alone on a second row with two
 * empty columns beside it, which is the ragged edge the redesign was asked to
 * remove. Full-width modules span all 12.
 *
 * align-items is left at its default `stretch`, NOT `start`: that is what gives
 * every card in a row the same height and lines their bottom borders up.
 */
/*
 * BENTO GRID
 *
 * Four columns, with tiles sized by how much attention each earns rather than
 * uniformly. The spans below are chosen against the actual content, not picked
 * for looks:
 *
 *   salat   2x2  - five tappable targets plus a week strip; the only module
 *                  with enough inside it to justify the anchor slot
 *   verse   2x1  - wide because the Arabic needs horizontal room to breathe
 *   lessons 2x1  - progress bars read badly when squeezed narrow
 *   stats / leaderboard / games / events  1x1  - each is a handful of numbers
 *   explore / badges  full row - horizontal card strips
 *
 * grid-auto-flow stays row (the default): `dense` would backfill gaps by
 * reordering tiles, which breaks the match between DOM order and visual order
 * for anyone tabbing through.
 */
.ap-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--space-4);
	align-items: stretch;
}
/* Default tile: one square. */
.ap-mod { grid-column: span 1; }
/* The anchor. */
.ap-mod--salat {
	grid-column: span 2;
	grid-row: span 2;
}
.ap-verse,
.ap-mod--lessons { grid-column: span 2; }
/*
 * Events spans two so the row beside the 2x2 anchor closes cleanly.
 *
 * The anchor occupies columns 1-2 across two rows, leaving four cells at its
 * right. With My Progress moved up into the greeting there are only three
 * tiles for them, so one cell was left empty and the grid read as broken
 * rather than deliberately asymmetric. Widening events fills the second row
 * exactly.
 */
.ap-mod--events { grid-column: span 2; }
.ap-mod--wide,
.ap-mod--explore,
.ap-mod--badges { grid-column: 1 / -1; }
/* The verse sits in the grid now, so it needs the tile treatment too. */
.ap-verse { border-radius: 20px; }
.ap-mod {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	padding: var(--space-5);
	/* 24px: extra-rounded, and consistent across every tile — a shared radius
	   is what makes differently-sized tiles read as one set. */
	border-radius: 24px;
	/*
	 * A soft wash of the tile's own accent instead of white-plus-a-red-rule.
	 *
	 * Every tile previously carried a 3px accent bar on a white card, which
	 * made the grid read as a row of identical documents with coloured tabs.
	 * Tinting the whole surface lets a child find "my Salat" or "games" by
	 * colour before reading a word — which is the point of a bento for this
	 * age group.
	 *
	 * 7% keeps the tint clearly below the text: body copy stays near-black on
	 * a near-white ground, so contrast is unaffected.
	 */
	background: color-mix(in srgb, var(--ap-accent, var(--color-red)) 7%, #fff);
	border: 1px solid color-mix(in srgb, var(--ap-accent, var(--color-red)) 14%, transparent);
	/* Ambient elevation, not an outline stroke. */
	box-shadow: 0 1px 2px rgba(23,24,26,0.03), 0 8px 20px rgba(23,24,26,0.05);
}
/*
 * One hue per category. Chosen to be distinguishable from each other at a
 * glance AND to keep the brand red meaningful — red stays on lessons and
 * primary actions, so it still marks "the thing to do" rather than becoming
 * one voice among many.
 */
.ap-mod--lessons { --ap-accent: #c92127; }  /* brand red   */
.ap-mod--salat   { --ap-accent: #0f8a6a; }  /* mint green  */
.ap-mod--board   { --ap-accent: #b8860b; }  /* warm amber  */
.ap-mod--play    { --ap-accent: #2f6fae; }  /* sky blue    */
.ap-mod--events  { --ap-accent: #6d4aa8; }  /* violet      */
.ap-mod--explore { --ap-accent: #0f5c46; }  /* deep green  */
.ap-mod--badges  { --ap-accent: #b8860b; }  /* warm amber  */
.ap-mod--stats   { --ap-accent: #c92127; }  /* brand red   */

.ap-mod__head {
	display: flex;
	align-items: center;
	gap: var(--space-3);
}
.ap-mod__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 36px;
	height: 36px;
	border-radius: 11px;
	background: color-mix(in srgb, var(--ap-accent, var(--color-red)) 12%, transparent);
	color: var(--ap-accent, var(--color-red));
}
.ap-mod__icon .ap-i { width: 20px; height: 20px; }
.ap-mod__title {
	font-family: var(--font-body);
	margin: 0;
	font-size: var(--text-h3);
	font-weight: var(--weight-bold);
	letter-spacing: -0.01em;
	color: var(--color-ink);
}
.ap-mod__empty,
.ap-mod__lead {
	margin: 0;
	font-size: var(--text-sm);
	line-height: var(--leading-relaxed);
	color: var(--color-grey-600);
}
.ap-mod__note {
	margin: 0;
	font-size: var(--text-xs);
	color: var(--color-grey-600);
}
.ap-mod__more {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-top: auto;
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-red);
	text-decoration: none;
}
.ap-mod__more .ap-i { width: 15px; height: 15px; }
.ap-mod__more:hover,
.ap-mod__more:focus-visible { color: var(--color-red-deep); }
.ap-pill {
	margin-left: auto;
	padding: 4px 10px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--ap-accent, var(--color-red)) 12%, transparent);
	color: var(--ap-accent, var(--color-red));
	font-size: 11px;
	font-weight: var(--weight-bold);
	white-space: nowrap;
}
/* ---- Courses ---- */
.ap-courses { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.ap-course {
	display: block;
	padding: var(--space-3) var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: 14px;
	text-decoration: none;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-course:hover, .ap-course:focus-visible {
	border-color: var(--color-red);
	background: var(--color-red-tint);
}
.ap-course__row { display: flex; justify-content: space-between; gap: var(--space-3); margin-bottom: 8px; }
.ap-course__title { font-weight: var(--weight-semibold); color: var(--color-ink); }
.ap-course__count { font-size: var(--text-xs); color: var(--color-grey-600); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* ---- Salat ---- */
.ap-salat { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.ap-salat form { margin: 0; }
.ap-salat__btn {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	width: 100%;
	min-height: 48px;
	padding: var(--space-2) var(--space-3);
	border: 1px solid var(--color-grey-200);
	border-radius: 12px;
	background: var(--color-white);
	font-size: var(--text-base);
	color: var(--color-ink);
	cursor: pointer;
	text-align: left;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-salat__btn:hover { border-color: var(--ap-accent); }
.ap-salat__btn:focus-visible { outline: none; box-shadow: var(--focus-ring); border-color: var(--ap-accent); }
.ap-salat__tick {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 26px; height: 26px;
	border: 2px solid var(--color-grey-300);
	border-radius: 50%;
	color: #fff;
}
.ap-salat__tick .ap-i { width: 15px; height: 15px; }
.ap-salat__btn.is-done { border-color: var(--ap-accent); background: color-mix(in srgb, var(--ap-accent) 8%, transparent); }
.ap-salat__btn.is-done .ap-salat__tick { background: var(--ap-accent); border-color: var(--ap-accent); }
.ap-salat__btn.is-done .ap-salat__name { font-weight: var(--weight-semibold); }
.ap-week {
	list-style: none;
	display: flex;
	justify-content: space-between;
	gap: 4px;
	margin: 0;
	padding: 0;
}
.ap-week__day { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 1; }
.ap-week__dot {
	width: 22px; height: 22px; border-radius: 50%;
	border: 2px solid var(--color-grey-200);
	background: transparent;
}
.ap-week__day.is-full .ap-week__dot { background: var(--ap-accent); border-color: var(--ap-accent); }
.ap-week__day.is-today .ap-week__dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ap-accent) 22%, transparent); }
.ap-week__lbl { font-size: 10px; font-weight: var(--weight-semibold); color: var(--color-grey-600); text-transform: uppercase; }
/* ---- Explore links ---- */
.ap-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.ap-links a {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	min-height: 56px;
	padding: var(--space-2) var(--space-3);
	border: 1px solid var(--color-grey-200);
	border-radius: 12px;
	text-decoration: none;
	color: var(--color-ink);
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ap-links a:hover, .ap-links a:focus-visible {
	border-color: var(--ap-accent);
	background: color-mix(in srgb, var(--ap-accent) 6%, transparent);
}
.ap-links .ap-i { width: 22px; height: 22px; flex-shrink: 0; color: var(--ap-accent); }
.ap-links strong { display: block; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.ap-links small { display: block; font-size: var(--text-xs); color: var(--color-grey-600); }
/* ---- Events ---- */
.ap-events { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.ap-event { display: flex; gap: var(--space-3); align-items: flex-start; }
.ap-event__date {
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	flex-shrink: 0; width: 52px; padding: 6px 0;
	border-radius: 12px;
	background: color-mix(in srgb, var(--ap-accent) 10%, transparent);
	color: var(--ap-accent);
}
.ap-event__mon { font-size: 10px; font-weight: var(--weight-bold); letter-spacing: 0.06em; }
.ap-event__day { font-size: var(--text-h3); font-weight: var(--weight-heavy); line-height: 1; font-variant-numeric: tabular-nums; }
.ap-event__title { display: block; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--color-ink); }
.ap-event__title a { color: inherit; }
.ap-event__meta { display: block; font-size: var(--text-xs); color: var(--color-grey-600); }
/* ---- Header account button ---- */
.ap-header__account {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	min-height: 44px;
	padding: 4px 12px 4px 4px;
	border-radius: 999px;
	text-decoration: none;
	transition: background-color 0.15s ease;
}
/*
 * The handle is near-white so it reads against the dark header bar. The hover
 * state previously swapped the background to a near-white grey and left the
 * text as it was — light on light, and unreadable exactly when a member is
 * pointing at it.
 *
 * A translucent white lift keeps the bar dark, so the text needs no colour
 * change and there is no state where the two can collide.
 */
.ap-header__account:hover,
.ap-header__account:focus-visible {
	background: rgba(255, 255, 255, 0.12);
	/* The global `a:hover { text-decoration: underline }` puts a rule under the
	   handle; on a pill-shaped button that reads as a broken link, not a hover. */
	text-decoration: none !important;
}
.ap-header__account:hover .ap-header__handle,
.ap-header__account:focus-visible .ap-header__handle {
	color: #fff;
	text-decoration: none;
}
.ap-header__account:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ap-avatar {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 34px; height: 34px;
	border-radius: 50%;
	background: var(--color-red);
	color: #fff;
	font-weight: var(--weight-bold);
	font-size: var(--text-sm);
}
.ap-avatar--lg { width: 60px; height: 60px; font-size: var(--text-h3); }
/* ---- Profile ---- */
.ap-profile__head { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-5); }
.ap-profile__head .ap-card__title { margin-bottom: 2px; }
.ap-profile__head .ap-card__lead { margin: 0; }
.ap-profile__sub {
	font-family: var(--font-body);
	margin: var(--space-6) 0 var(--space-4);
	font-size: var(--text-h3);
	font-weight: var(--weight-bold);
	color: var(--color-ink);
}
.ap-facts {
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: 10px var(--space-5);
	margin: 0 0 var(--space-4);
	padding: var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: 14px;
}
.ap-facts dt { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-grey-600); }
.ap-facts dd { margin: 0; font-size: var(--text-sm); color: var(--color-ink); }
/*
 * Help FAQ — a plain static list, not an accordion. The markup is already a
 * <dl>: each question is a heavier label, each answer is secondary copy, and a
 * hairline rule between pairs keeps the four entries from running together.
 * Mirrors .ap-facts above, the portal's other <dl>.
 */
.ap-help {
	margin: 0;
	display: flex;
	flex-direction: column;
}
.ap-help dt {
	margin: 0;
	font-family: var(--font-body);
	font-size: var(--text-base);
	font-weight: var(--weight-semibold);
	color: var(--color-ink);
}
.ap-help dd {
	margin: var(--space-2) 0 0;
	font-size: var(--text-sm);
	line-height: var(--leading-relaxed);
	color: var(--color-grey-600);
}
/* Divider + spacing before every pair except the first. */
.ap-help dt + dd + dt {
	margin-top: var(--space-4);
	padding-top: var(--space-4);
	border-top: 1px solid var(--color-grey-200);
}
.ap-help dd a { font-weight: var(--weight-semibold); text-decoration: underline; }
/* ---- Buttons added for the dashboard ---- */
.ap-btn--block { width: 100%; justify-content: center; }
.ap-btn--onDark {
	background: rgba(255,255,255,0.14);
	/* !important: `.atfal-portal-body a` sets every link to brand red at
	   specificity (0,1,1), which beats this class on its own — the button
	   rendered as red text on dark green and was almost unreadable. Same
	   conflict and same fix as .ap-header__brand higher up this file. */
	color: #fff !important;
	border: 1px solid rgba(255,255,255,0.3);
	display: inline-flex;
	align-items: center;
	gap: 8px;
}
.ap-btn--onDark:hover, .ap-btn--onDark:focus-visible { background: rgba(255,255,255,0.24); }
.ap-btn--onDark .ap-i { width: 15px; height: 15px; }
@media (max-width: 640px) {
	.ap-hello { flex-direction: column; align-items: flex-start; }
	.ap-tally { width: 100%; }
	.ap-tally li { flex: 1; min-width: 0; padding: var(--space-2) var(--space-3); }
	.ap-verse__inner { padding: var(--space-5) var(--space-4); }
	.ap-grid { grid-template-columns: 1fr; }
	.ap-facts { grid-template-columns: 1fr; gap: 2px var(--space-4); }
	.ap-facts dd { margin-bottom: 10px; }
}
@media (prefers-reduced-motion: reduce) {
	.ap-course, .ap-salat__btn, .ap-links a, .ap-header__account { transition: none; }
}
/* ===========================================================================
   ARABIC, FEATURES BAR, EXPLORE TILES  (dashboard v2)
   =========================================================================== */

/*
 * Arabic is set in a system Naskh face, not a webfont. The site already sends
 * every visitor's IP to Google and Font Awesome for type, which was flagged as
 * a privacy issue on a children's site — adding a third font request to fix a
 * greeting would make that worse. Every current OS ships a competent Arabic
 * face, and Quranic diacritics render correctly in all of them.
 */
:root {
	/*
	 * Two Arabic stacks, because the two uses want different voices:
	 *
	 *   --font-arabic          classical Naskh, for Qur'anic text
	 *   --font-arabic-display  contemporary sans, for UI like the greeting
	 *
	 * Neither ends in a bare `serif`/`sans-serif` that Latin text could fall
	 * through to — that was the original cause of the header font clash.
	 */
	--font-arabic: "Amiri", "SF Arabic", "Geeza Pro", "Noto Naskh Arabic",
		"Traditional Arabic", serif;
	--font-arabic-display: "Aref Ruqaa", "SF Arabic", "Noto Naskh Arabic",
		"Geeza Pro", "Segoe UI", serif;
}
/*
 * NOTE: no font-family here, deliberately.
 *
 * This element is the WRAPPER around both the English transliteration and the
 * Arabic. It previously carried `font-family: var(--font-arabic)`, so the
 * English inherited the Arabic stack and fell through to its final `serif` —
 * which is exactly the serif-versus-heavy-sans clash against the username.
 * The Arabic face belongs on .ap-hello__ar and nowhere else.
 */
.ap-hello__salam {
	margin: 0;
	color: var(--color-grey-600);
}
.ap-verse__arabic {
	font-family: var(--font-arabic);
	margin: 0 0 var(--space-4);
	font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.1rem);
	line-height: 2.05;
	color: #fff;
	max-width: 40ch;
	/* Never let a long ayah force the card sideways. */
	overflow-wrap: anywhere;
}
/* ---- Daily features bar ---- */
.ap-features {
	/* Full-row grid item: the block spans the bento while keeping its own
	   two-up layout inside. */
	grid-column: 1 / -1;
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	gap: var(--space-4);
}
/*
 * Two banners share the row; a lone banner takes the whole width.
 *
 * :only-child rather than a PHP flag, so this corrects itself in both
 * directions — the quote spans full width while no facts are entered, and
 * drops back to half automatically the moment a fact is published. Nothing to
 * remember to change.
 */
.ap-feature:only-child {
	grid-column: 1 / -1;
}
.ap-feature {
	grid-column: span 6;
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: var(--space-4) var(--space-5);
	border-radius: 16px;
	border: 1px solid var(--color-grey-200);
	border-left: 3px solid var(--ap-accent);
	background: var(--color-white);
}
.ap-feature--quote { --ap-accent: #7a5a12; }
.ap-feature--fact  { --ap-accent: #4a3a8f; }
.ap-feature__label {
	margin: 0;
	font-size: 11px;
	font-weight: var(--weight-bold);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ap-accent);
}
.ap-feature__body {
	margin: 0;
	font-size: var(--text-sm);
	line-height: var(--leading-relaxed);
	color: var(--color-ink);
}
.ap-feature__src {
	margin: 0;
	font-size: var(--text-xs);
	color: var(--color-grey-600);
}
/* ---- Explore tiles ---- */
.ap-explore__heading {
	font-family: var(--font-body);
	margin: var(--space-2) 0 0;
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-grey-600);
}
.ap-tiles {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	/*
	 * 132px, not 150px: at 375px the card's usable width is ~303px, and two
	 * 150px tiles plus the gap need 312px — so every tile landed on its own row
	 * and the eight of them turned Explore into a long scroll on exactly the
	 * device most Atfal use. 132px fits two per row with room to spare.
	 */
	grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
	gap: var(--space-3);
}
.ap-tile {
	display: flex;
	flex-direction: column;
	gap: 3px;
	height: 100%;
	min-height: 104px;
	padding: var(--space-4);
	border: 1px solid var(--color-grey-200);
	border-radius: 14px;
	background: var(--color-white);
	text-decoration: none;
	transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.15s ease;
}
.ap-tile:hover,
.ap-tile:focus-visible {
	border-color: var(--ap-accent);
	background: color-mix(in srgb, var(--ap-accent) 6%, transparent);
	transform: translateY(-2px);
}
.ap-tile:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ap-tile__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px; height: 34px;
	margin-bottom: 6px;
	border-radius: 10px;
	background: color-mix(in srgb, var(--ap-accent) 12%, transparent);
	color: var(--ap-accent);
}
.ap-tile__icon .ap-i { width: 19px; height: 19px; }
.ap-tile__title {
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--color-ink);
	line-height: 1.25;
}
.ap-tile__desc {
	font-size: var(--text-xs);
	line-height: 1.35;
	color: var(--color-grey-600);
}
/* ---- Responsive: collapse the 12-column grids ---- */
/* Tablet: two columns. The anchor keeps its 2x2 shape by filling the row. */
@media (max-width: 1024px) {
	.ap-grid { grid-template-columns: repeat(2, 1fr); }
	.ap-mod--salat { grid-column: span 2; grid-row: span 1; }
	.ap-verse,
	.ap-mod--lessons { grid-column: span 2; }
	.ap-feature { grid-column: 1 / -1; }
}
/* Phone: a single column. Every span collapses, including the anchor's row
   span — a 2-row tile in a 1-column grid leaves an empty cell beneath it. */
@media (max-width: 700px) {
	.ap-grid { grid-template-columns: 1fr; }
	.ap-mod,
	.ap-verse,
	.ap-mod--salat,
	.ap-mod--lessons,
	.ap-feature { grid-column: 1 / -1; grid-row: auto; }
}
@media (prefers-reduced-motion: reduce) {
	.ap-tile { transition: none; }
	.ap-tile:hover, .ap-tile:focus-visible { transform: none; }
}
/* ===========================================================================
   DASHBOARD v3 — greeting, level ring, discovery cards, podium, celebration
   =========================================================================== */

/* ---- Greeting ---- */
.ap-hello__who { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.ap-hello__text { min-width: 0; }
/*
 * The avatar frame IS the level meter: a conic-gradient swept to --ap-ring
 * (progress toward the next level), masked into a ring by the inner disc.
 * One element, no extra markup, and it degrades to a plain red disc if
 * conic-gradient is unsupported.
 */
.ap-levelring {
	position: relative;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* Matches the height of the text column beside it — the name row, the gap
	   and the XP row together — so the header reads as one aligned block
	   rather than an icon floating against taller content. */
	width: 72px; height: 72px;
	border-radius: 50%;
	background: conic-gradient(var(--color-red) var(--ap-ring, 0%), var(--color-grey-200) 0);
}
.ap-levelring__inner {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 8px of ring left visible. */
	width: 60px; height: 60px;
	border-radius: 50%;
	background: linear-gradient(145deg, #e0454a, var(--color-red-deep));
	color: #fff;
	font-size: var(--text-h3);
	font-weight: var(--weight-heavy);
	box-shadow: inset 0 1px 0 rgba(255,255,255,0.35);
}
.ap-levelring__num {
	position: absolute;
	right: 0; bottom: 2px;
	min-width: 24px; height: 24px;
	padding: 0 5px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 999px;
	background: var(--color-ink);
	color: #fff;
	font-size: 11px;
	font-weight: var(--weight-heavy);
	border: 2px solid var(--color-cool-grey);
}
/* ---- Greeting: Arabic on its own line, then English + name ---- */

/*
 * TASHKEEL CLIPPING — the whole reason this element is styled the way it is.
 *
 * Arabic diacritics sit further above and below the baseline than Latin
 * ascenders and descenders do, so a line-height tuned for Latin clips them. The
 * fix is three things together, and all three are load-bearing:
 *
 *   line-height: 2      generous leading so the glyph box is never the limit
 *   padding-block       space inside the element so nothing meets a hard edge
 *   overflow: visible   nothing crops what the two above have made room for
 *
 * No background, border or pill: a container edge is exactly what tashkeel
 * collides with, and it was clipping in the previous version.
 */
.ap-hello__ar {
	font-family: var(--font-arabic-display);
	/* Roughly two-thirds of the name: clearly legible and a companion to it,
	   without competing with the name for the row. */
	/* Ruqaa reads smaller than a sans at the same nominal size, so it is set a
	   little larger; 700 because the face has no mid weights. */
	font-size: clamp(1.2rem, 1rem + 0.7vw, 1.5rem);
	font-weight: 700;
	color: var(--color-ink);
	/*
	 * Line-height matched to the name so both occupy the same box and the row
	 * stays symmetrical. A generous 1.9 here inflated the Arabic's box to 93px
	 * against the name's 58px, which pushed the whole text column out of step
	 * with the avatar ring beside it.
	 *
	 * Tashkeel is still safe: line-height governs LAYOUT height, not painting.
	 * With overflow visible the marks render outside the line box, and nothing
	 * sits above this row for them to collide with.
	 */
	line-height: var(--leading-snug);
	padding-block: 0;
	overflow: visible;
	/* Keeps the greeting on one line rather than breaking mid-phrase. */
	white-space: nowrap;
}
.ap-hello__name {
	font-family: var(--font-body);
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0 10px;
	line-height: var(--leading-snug);
	letter-spacing: -0.01em;
	color: var(--color-ink);
}
.ap-hello__who-name {
	/* One step down the scale: the header was outgrowing the tiles beneath it
	   and reading as a separate page rather than the top of this one. */
	font-size: var(--text-h2);
	font-weight: var(--weight-heavy);
	letter-spacing: -0.02em;
	/* Both runs are Latin here, so a shared baseline is real and worth using. */
	overflow-wrap: anywhere;
}
/* ---- Level pill + XP meter ---- */
.ap-xp {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 10px;
	margin-top: 8px;
}
.ap-xp__pill {
	display: inline-flex;
	align-items: center;
	padding: 4px 12px;
	border-radius: 999px;
	background: var(--color-red-tint);
	color: var(--color-red-deep);
	border: 1px solid rgba(201, 33, 39, 0.18);
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	letter-spacing: 0.02em;
	white-space: nowrap;
}
.ap-xp__meter {
	position: relative;
	display: block;
	width: 128px;
	height: 8px;
	border-radius: 999px;
	background: var(--color-grey-200);
	overflow: hidden;
}
.ap-xp__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: linear-gradient(90deg, #e0454a, var(--color-red-deep));
	transition: width 0.4s cubic-bezier(.2,.8,.3,1);
}
.ap-xp__count {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	font-variant-numeric: tabular-nums;
	color: var(--color-ink);
	white-space: nowrap;
}
.ap-xp__sep { color: var(--color-grey-300); margin: 0 1px; }
.ap-xp__unit { color: var(--color-grey-600); font-weight: var(--weight-medium); margin-left: 2px; }
.ap-xp__togo {
	font-size: var(--text-xs);
	color: var(--color-grey-600);
	white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) {
	.ap-xp__fill { transition: none; }
}
.ap-tally--points .ap-tally__n { color: var(--color-red); }
/* ---- Colourful module icons ---- */
/*
 * Dimensional rather than flat: a light-to-dark gradient, a highlight along the
 * top edge and a soft cast shadow read as a raised object. Cheaper than 3D
 * artwork, scales to any size, and stays crisp on every display.
 */
.ap-mod__icon {
	width: 42px;
	height: 42px;
	border-radius: 14px;
	background: linear-gradient(155deg,
		color-mix(in srgb, var(--ap-accent, var(--color-red)) 62%, white),
		var(--ap-accent, var(--color-red)) 65%,
		color-mix(in srgb, var(--ap-accent, var(--color-red)) 82%, black));
	color: #fff;
	box-shadow:
		inset 0 1.5px 0 rgba(255,255,255,0.55),
		inset 0 -1.5px 0 rgba(0,0,0,0.12),
		0 3px 8px color-mix(in srgb, var(--ap-accent, var(--color-red)) 32%, transparent);
}
.ap-mod__icon .ap-i { width: 22px; height: 22px; }
/* ---- Feature banners ---- */
.ap-feature { position: relative; overflow: hidden; }
.ap-feature__label { display: flex; align-items: center; gap: 7px; }
.ap-feature__label .ap-i { width: 15px; height: 15px; }
/* A soft tint bloom behind each banner, so quotes and facts read as ambience
   rather than as another task card. */
.ap-feature::after {
	content: "";
	position: absolute;
	right: -40px; top: -60px;
	width: 190px; height: 190px;
	border-radius: 50%;
	background: color-mix(in srgb, var(--ap-accent) 10%, transparent);
	pointer-events: none;
}
.ap-feature__body { position: relative; }
/* ---- Featured story ---- */
.ap-story {
	display: grid;
	grid-template-columns: 120px 1fr;
	gap: var(--space-4);
	align-items: center;
	padding: 0;
	overflow: hidden;
	border: 1px solid var(--color-grey-200);
	border-radius: 16px;
	background: var(--color-white);
	text-decoration: none;
}
.ap-story__art {
	align-self: stretch;
	min-height: 104px;
	background: linear-gradient(150deg, #7a5a12, #b98b1e 60%, #e0b455);
}
.ap-story__body { display: flex; flex-direction: column; gap: 4px; padding: var(--space-4) var(--space-4) var(--space-4) 0; }
.ap-story__tag {
	font-size: 10px; font-weight: var(--weight-bold);
	letter-spacing: 0.09em; text-transform: uppercase; color: #7a5a12;
}
.ap-story__text { font-size: var(--text-sm); line-height: var(--leading-relaxed); color: var(--color-ink); }
.ap-story__src { font-size: var(--text-xs); color: var(--color-grey-600); }
/* ---- Discovery cards ---- */
.ap-cards {
	list-style: none; margin: 0; padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
	gap: var(--space-4);
}
.ap-dcard {
	display: flex;
	flex-direction: column;
	height: 100%;
	overflow: hidden;
	border: 1px solid var(--color-grey-200);
	border-radius: 16px;
	background: var(--color-white);
	text-decoration: none;
	transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}
.ap-dcard:hover, .ap-dcard:focus-visible {
	transform: translateY(-3px);
	border-color: transparent;
	box-shadow: 0 10px 22px rgba(23,24,26,0.13);
}
.ap-dcard:focus-visible { outline: none; box-shadow: var(--focus-ring), 0 10px 22px rgba(23,24,26,0.13); }
/* Gradient cover art, one per category. Drawn in CSS: no images to download,
   crisp at any resolution, and no stock photography. */
.ap-dcard__art {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	height: 92px;
	background: linear-gradient(145deg, var(--ap-c1, #444), var(--ap-c2, #111));
}
.ap-dcard__art::after {
	content: "";
	position: absolute; inset: 0;
	background: radial-gradient(90% 120% at 18% -10%, rgba(255,255,255,0.32), rgba(255,255,255,0) 62%);
}
.ap-dcard__glyph {
	position: relative;
	display: inline-flex; align-items: center; justify-content: center;
	width: 46px; height: 46px;
	border-radius: 14px;
	background: rgba(255,255,255,0.2);
	color: #fff;
	box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
}
.ap-dcard__glyph .ap-i { width: 24px; height: 24px; }
.ap-dcard--quran    { --ap-c1: #17715c; --ap-c2: #0a3b38; }
.ap-dcard--science  { --ap-c1: #2f5fae; --ap-c2: #16306a; }
.ap-dcard--audio    { --ap-c1: #a4590a; --ap-c2: #5e2f04; }
.ap-dcard--podcast  { --ap-c1: #8a3d7a; --ap-c2: #4b1c46; }
.ap-dcard--video    { --ap-c1: #b03a3f; --ap-c2: #6a1418; }
.ap-dcard--books    { --ap-c1: #4a3a8f; --ap-c2: #241a52; }
.ap-dcard--articles { --ap-c1: #147a86; --ap-c2: #073e48; }
.ap-dcard--sermon   { --ap-c1: #7a5a12; --ap-c2: #3d2b04; }
.ap-dcard__body { display: flex; flex-direction: column; gap: 4px; padding: var(--space-4); }
.ap-dcard__tag {
	align-self: flex-start;
	padding: 2px 8px;
	border-radius: 999px;
	background: var(--color-grey-100);
	color: var(--color-grey-700);
	font-size: 10px; font-weight: var(--weight-bold);
	letter-spacing: 0.07em; text-transform: uppercase;
}
.ap-dcard__title { font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--color-ink); line-height: 1.25; }
.ap-dcard__teaser { font-size: var(--text-xs); line-height: 1.5; color: var(--color-grey-600); }
/* ---- Podium ---- */
.ap-podium {
	list-style: none;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--space-2);
	align-items: end;
	margin: 0 0 var(--space-4);
	padding: 0;
}
.ap-podium__slot { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; }
.ap-podium__avatar {
	display: inline-flex; align-items: center; justify-content: center;
	width: 40px; height: 40px;
	border-radius: 50%;
	background: linear-gradient(145deg, #b9b9bd, #86868b);
	color: #fff; font-weight: var(--weight-heavy);
	box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
}
.ap-podium__slot--1 .ap-podium__avatar { background: linear-gradient(145deg, #f0cf6b, #c9a227); width: 48px; height: 48px; }
.ap-podium__slot--3 .ap-podium__avatar { background: linear-gradient(145deg, #d8a37a, #a56a3c); }
.ap-podium__handle {
	font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-ink);
	max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ap-podium__points { font-size: 11px; color: var(--color-grey-600); font-variant-numeric: tabular-nums; }
.ap-podium__block {
	display: flex; align-items: flex-start; justify-content: center;
	width: 100%; padding-top: 5px;
	border-radius: 8px 8px 0 0;
	background: var(--color-grey-100);
	color: var(--color-grey-600);
	font-weight: var(--weight-heavy);
	font-size: var(--text-sm);
}
.ap-podium__slot--1 .ap-podium__block { height: 54px; background: color-mix(in srgb, #c9a227 22%, transparent); color: #7a5a12; }
.ap-podium__slot--2 .ap-podium__block { height: 40px; }
.ap-podium__slot--3 .ap-podium__block { height: 30px; }
.ap-podium__slot.is-me .ap-podium__handle { color: var(--color-red-deep); }
/* ---- Salat celebration ---- */
.ap-salat__done {
	display: flex; align-items: center; gap: 8px;
	margin: 0;
	padding: var(--space-3) var(--space-4);
	border-radius: 12px;
	background: color-mix(in srgb, var(--ap-accent) 12%, transparent);
	color: var(--ap-accent);
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
}
.ap-salat__done .ap-i { width: 18px; height: 18px; }
.ap-mod--salat.is-complete { border-top-color: var(--ap-accent); }
/* Fires once, when the module gains .just-completed from the JS below. */
@keyframes ap-pop {
	0%   { transform: scale(0.86); opacity: 0; }
	55%  { transform: scale(1.05); opacity: 1; }
	100% { transform: scale(1); opacity: 1; }
}
.ap-mod--salat.just-completed .ap-salat__done { animation: ap-pop 0.5s cubic-bezier(.2,.8,.3,1) both; }
@media (max-width: 640px) {
	.ap-levelring { width: 60px; height: 60px; }
	.ap-levelring__inner { width: 50px; height: 50px; font-size: var(--text-lg); }
	.ap-levelring__num { min-width: 21px; height: 21px; font-size: 10px; }
	.ap-story { grid-template-columns: 84px 1fr; }
	/*
	 * 138px, not 150px: at 375px the module's usable width is ~311px, and two
	 * 150px cards plus the gap need 312px — one pixel over, so every card took
	 * its own row and the eight of them became a ~1600px scroll. 138px fits two
	 * across comfortably.
	 */
	.ap-cards { grid-template-columns: repeat(auto-fill, minmax(138px, 1fr)); gap: var(--space-3); }
	.ap-dcard__art { height: 70px; }
	.ap-dcard__body { padding: var(--space-3); }
	/* Teasers vary in length; clamping keeps the two cards in a row the same
	   height so the grid stays even. */
	.ap-dcard__teaser {
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
}
@media (prefers-reduced-motion: reduce) {
	.ap-dcard { transition: none; }
	.ap-dcard:hover, .ap-dcard:focus-visible { transform: none; }
	.ap-mod--salat.just-completed .ap-salat__done { animation: none; }
}
/* ---- Curated books ---- */
.ap-books {
	list-style: none; margin: 0; padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
	gap: var(--space-4);
}
.ap-book { display: flex; flex-direction: column; gap: 8px; text-decoration: none; height: 100%; }
.ap-book__cover {
	width: 100%;
	/* Fixed ratio so a row of covers lines up even though the source images
	   vary in proportion. */
	aspect-ratio: 2 / 3;
	object-fit: cover;
	border-radius: 10px;
	background: var(--color-grey-100);
	box-shadow: 0 2px 8px rgba(23,24,26,0.16);
	transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.ap-book:hover .ap-book__cover,
.ap-book:focus-visible .ap-book__cover {
	transform: translateY(-3px);
	box-shadow: 0 10px 20px rgba(23,24,26,0.22);
}
.ap-book:focus-visible { outline: none; }
.ap-book:focus-visible .ap-book__cover { box-shadow: var(--focus-ring), 0 10px 20px rgba(23,24,26,0.22); }
.ap-book__cover--none { display: block; }
.ap-book__title {
	font-size: var(--text-xs);
	font-weight: var(--weight-semibold);
	line-height: 1.35;
	color: var(--color-ink);
	display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
@media (prefers-reduced-motion: reduce) {
	.ap-book__cover { transition: none; }
	.ap-book:hover .ap-book__cover, .ap-book:focus-visible .ap-book__cover { transform: none; }
}
@media (max-width: 640px) {
	/* Arabic stays generous — clipping is worse on small screens, not better. */
	.ap-hello__ar { font-size: 1.35rem; }
	.ap-hello__dash { font-size: var(--text-base); }
	.ap-hello__name { gap: 0 8px; }
}
/* ---- My Progress in the greeting row ---- */
/*
 * The tile keeps its .ap-mod card treatment but is sized for the header, not
 * for a grid cell: .ap-hello is flex/space-between, so it needs an intrinsic
 * width rather than the stretch it would get inside .ap-grid.
 */
.ap-hello .ap-mod--stats {
	flex: 0 0 auto;
	min-width: 280px;
	padding: var(--space-4);
	gap: var(--space-3);
}
.ap-hello .ap-mod--stats .ap-tally {
	/* Fill the card rather than clustering left — three even columns read as a
	   scoreboard, which is the point of putting it up here. */
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--space-2);
	margin: 0;
}
.ap-hello .ap-mod--stats .ap-tally li { min-width: 0; }
@media (max-width: 780px) {
	/* Stacked under the greeting: at this width the two would otherwise be
	   squeezed side by side and the numbers stop being scannable. */
	.ap-hello .ap-mod--stats { width: 100%; min-width: 0; }
}
/* ---- Inner surfaces on tinted tiles ---- */
/*
 * Rows and sub-cards inside a tinted tile revert to white so they still read
 * as distinct elements. Without this they disappear into the tile's own wash.
 */
.ap-mod .ap-course,
.ap-mod .ap-salat__btn,
.ap-mod .ap-tally li,
.ap-mod .ap-badge,
.ap-mod .ap-dcard,
.ap-mod .ap-tile,
.ap-mod .ap-story {
	background: #fff;
}
/* ---- Course card: progress ring + action ---- */
.ap-course {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: var(--space-4);
	border-radius: 18px;
}
.ap-course__body { min-width: 0; }
.ap-course__title { display: block; }
.ap-course__count { display: block; }
/*
 * Conic-gradient ring, masked to a ring by the inner disc. One element rather
 * than an SVG: no extra markup, and it stays sharp at any size.
 */
.ap-ring {
	position: relative;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	border-radius: 50%;
	background: conic-gradient(
		var(--ap-accent, var(--color-red)) var(--ap-pct, 0%),
		color-mix(in srgb, var(--ap-accent, var(--color-red)) 16%, transparent) 0
	);
}
.ap-ring__hole {
	display: inline-flex;
	align-items: baseline;
	justify-content: center;
	width: 42px;
	height: 42px;
	border-radius: 50%;
	background: #fff;
	font-size: var(--text-sm);
	font-weight: var(--weight-heavy);
	font-variant-numeric: tabular-nums;
	color: var(--color-ink);
	line-height: 42px;
}
.ap-ring__hole small { font-size: 9px; font-weight: var(--weight-bold); color: var(--color-grey-600); }
.ap-course__go {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	flex-shrink: 0;
	padding: 8px 14px;
	border-radius: 999px;
	background: var(--ap-accent, var(--color-red));
	color: #fff;
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	white-space: nowrap;
	box-shadow: inset 0 1px 0 rgba(255,255,255,0.3);
}
.ap-course__go .ap-i { width: 14px; height: 14px; }
.ap-course:hover .ap-course__go,
.ap-course:focus-visible .ap-course__go { background: color-mix(in srgb, var(--ap-accent) 82%, black); }
/* ---- Podium medals ---- */
.ap-podium__avatar { position: relative; }
.ap-podium__medal {
	position: absolute;
	right: -3px;
	bottom: -3px;
	width: 19px;
	height: 19px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	border: 2px solid #fff;
	font-size: 10px;
	font-weight: var(--weight-heavy);
	color: #fff;
	/* Gold / silver / bronze, matching the avatar tier beneath it. */
	background: linear-gradient(145deg, #b9b9bd, #86868b);
}
.ap-podium__slot--1 .ap-podium__medal { background: linear-gradient(145deg, #f0cf6b, #c9a227); }
.ap-podium__slot--3 .ap-podium__medal { background: linear-gradient(145deg, #d8a37a, #a56a3c); }
/* ---- Banner accent icons ---- */
.ap-feature__label::before {
	content: "";
	display: inline-block;
	width: 15px;
	height: 15px;
	margin-right: 7px;
	vertical-align: -2px;
	background: currentColor;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}
/* Open book for the excerpt, lightbulb for the fact — masked SVG so each
   inherits its banner's accent colour rather than shipping two coloured PNGs. */
.ap-feature--quote .ap-feature__label::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 5h7a3 3 0 0 1 3 3v11a2.5 2.5 0 0 0-2.5-2.5H2z'/%3E%3Cpath d='M22 5h-7a3 3 0 0 0-3 3v11a2.5 2.5 0 0 1 2.5-2.5H22z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 5h7a3 3 0 0 1 3 3v11a2.5 2.5 0 0 0-2.5-2.5H2z'/%3E%3Cpath d='M22 5h-7a3 3 0 0 0-3 3v11a2.5 2.5 0 0 1 2.5-2.5H22z'/%3E%3C/svg%3E");
}
.ap-feature--fact .ap-feature__label::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 18h6M10 22h4'/%3E%3Cpath d='M12 2a7 7 0 0 0-4 12.7V17h8v-2.3A7 7 0 0 0 12 2z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 18h6M10 22h4'/%3E%3Cpath d='M12 2a7 7 0 0 0-4 12.7V17h8v-2.3A7 7 0 0 0 12 2z'/%3E%3C/svg%3E");
}
@media (max-width: 520px) {
	.ap-course { grid-template-columns: auto 1fr; gap: var(--space-3); }
	.ap-course__go { grid-column: 1 / -1; justify-content: center; }
}
/* ---- Banner text clamp ---- */
/*
 * Insurance, not a fix for a present bug: the two banners currently match at
 * 176px each because flex stretch already equalises them, and today's entries
 * happen to be similar lengths (235 and 154 characters).
 *
 * But the pool holds ~340 entries up to 260 characters. A long excerpt beside
 * a short fact would push this row taller than any other in the bento. Clamping
 * to four lines caps that, and min-height stops a very short entry collapsing
 * the row in the other direction.
 */
.ap-feature { min-height: 160px; }
.ap-feature__body {
	display: -webkit-box;
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* ===========================================================================
   APP SHELL — left sidebar, top bar, workspace canvas
   =========================================================================== */

.ap-shell--app {
	display: grid;
	grid-template-columns: 256px minmax(0, 1fr);
	min-height: 100vh;
	background: var(--color-cool-grey);
}
.ap-work { display: flex; flex-direction: column; min-width: 0; }
/* ---- Sidebar ---- */
.ap-side {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
	padding: var(--space-5) var(--space-4);
	background: #fff;
	border-right: 1px solid var(--color-grey-200);
	/* Sticky rather than fixed: it scrolls with a short page but pins on a long
	   one, without taking the nav out of flow and needing a matching offset on
	   the workspace. */
	position: sticky;
	top: 0;
	align-self: start;
	height: 100vh;
	overflow-y: auto;
}
.ap-side__brand {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: var(--space-2) var(--space-3);
	text-decoration: none !important;
}
.ap-side__mark {
	width: 12px; height: 12px; border-radius: 50%;
	background: var(--color-red);
	box-shadow: 0 0 0 4px rgba(201,33,39,0.18);
}
.ap-side__name { font-weight: var(--weight-heavy); color: var(--color-ink); letter-spacing: -0.01em; }
.ap-side__group {
	margin: 0 0 6px var(--space-3);
	font-size: 10px;
	font-weight: var(--weight-bold);
	letter-spacing: 0.12em;
	color: var(--color-grey-300);
}
.ap-side__list { list-style: none; margin: 0 0 var(--space-5); padding: 0; display: grid; gap: 2px; }
.ap-side__link {
	display: flex;
	align-items: center;
	gap: 12px;
	/* 44px target, per the project a11y checklist. */
	min-height: 44px;
	padding: 0 var(--space-3);
	border-radius: 12px;
	font-size: var(--text-sm);
	font-weight: var(--weight-medium);
	color: var(--color-grey-600) !important;
	text-decoration: none !important;
	transition: background-color 0.15s ease, color 0.15s ease;
}
.ap-side__link .ap-i { width: 19px; height: 19px; flex-shrink: 0; }
.ap-side__link:hover { background: var(--color-grey-100); color: var(--color-ink) !important; }
.ap-side__link:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/*
 * Active state uses the BRAND red, not the emerald of the reference design.
 * The brand brief is explicit that the palette is red/white/black sampled from
 * the logo and not to be substituted — and red is already the portal's "act on
 * this" colour, so an emerald nav would introduce a second primary.
 */
.ap-side__link.is-active {
	background: var(--color-red);
	color: #fff !important;
	font-weight: var(--weight-semibold);
	box-shadow: 0 4px 12px rgba(201,33,39,0.28);
}
.ap-side__link.is-active:hover { background: var(--color-red-deep); color: #fff !important; }
.ap-side__out {
	margin-top: auto;
	padding: var(--space-3);
	font-size: var(--text-sm);
	color: var(--color-grey-600) !important;
	border-top: 1px solid var(--color-grey-200);
}
.ap-side__out:hover { color: var(--color-red) !important; }
/* ---- Top bar ---- */
.ap-topbar {
	display: flex;
	align-items: center;
	gap: var(--space-4);
	padding: var(--space-4) var(--space-6);
	background: transparent;
	border-bottom: 1px solid var(--color-grey-200);
}
.ap-topbar__title {
	margin: 0;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	color: var(--color-grey-600);
}
.ap-topbar__site-link {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	min-height: 44px;
	padding: 0 var(--space-3);
	border: 1px solid var(--color-grey-200);
	border-radius: 12px;
	color: var(--color-grey-600) !important;
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	text-decoration: none !important;
	white-space: nowrap;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.ap-topbar__site-link:hover {
	background: var(--color-grey-100);
	border-color: var(--color-grey-300);
	color: var(--color-ink) !important;
}
.ap-topbar__site-link:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ap-topbar__user {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin-left: auto;
	min-height: 44px;
	padding: 4px 12px 4px 4px;
	border-radius: 999px;
	text-decoration: none !important;
	transition: background-color 0.15s ease;
}
.ap-topbar__user:hover { background: var(--color-grey-100); }
.ap-topbar__user:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ap-topbar__handle { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--color-ink); }
.ap-topbar__burger {
	display: none;
	width: 40px; height: 40px;
	border: 1px solid var(--color-grey-200);
	border-radius: 10px;
	background: #fff;
	cursor: pointer;
	position: relative;
}
.ap-topbar__burger span,
.ap-topbar__burger span::before,
.ap-topbar__burger span::after {
	position: absolute; left: 11px; width: 18px; height: 2px;
	background: var(--color-ink); border-radius: 2px; content: "";
}
.ap-topbar__burger span { top: 19px; }
.ap-topbar__burger span::before { top: -6px; left: 0; }
.ap-topbar__burger span::after  { top: 6px; left: 0; }
/* Workspace + page wrapper */
.ap-shell--app .ap-main { padding: var(--space-6); display: block; }
.ap-page { max-width: 1280px; }
/* ---- Responsive: sidebar becomes a drawer ---- */
@media (max-width: 900px) {
	.ap-shell--app { grid-template-columns: minmax(0, 1fr); }
	.ap-side {
		position: fixed;
		z-index: 60;
		top: 0; left: 0; bottom: 0;
		width: 260px;
		height: 100vh;
		transform: translateX(-100%);
		transition: transform 0.22s ease;
		box-shadow: 0 0 40px rgba(23,24,26,0.18);
	}
	.ap-side.is-open { transform: translateX(0); }
	.ap-topbar__burger { display: block; }
	.ap-shell--app .ap-main { padding: var(--space-5) var(--space-4); }
}
@media (max-width: 620px) {
	.ap-topbar { gap: var(--space-2); padding-inline: var(--space-4); }
	.ap-topbar__title { display: none; }
	.ap-topbar__site-link { padding-inline: 10px; }
}
@media (prefers-reduced-motion: reduce) {
	.ap-side, .ap-side__link, .ap-topbar__user, .ap-topbar__site-link { transition: none; }
}
.ap-side__backdrop {
	position: fixed;
	inset: 0;
	z-index: 55;
	background: rgba(23, 24, 26, 0.4);
}
/* ===========================================================================
   PORTAL ACCENT: EMERALD
   ---------------------------------------------------------------------------
   The portal's primary shifts from brand red to emerald, at MAAC's direction.
   atfal.ca stays red, so the two now read as related-but-distinct products
   rather than one continuous surface — a deliberate split, recorded here so it
   is not later mistaken for drift.

   Red is NOT retired: it stays on the logo mark and on genuinely destructive
   or urgent affordances, so it keeps meaning something when it appears.
   =========================================================================== */
.atfal-portal-body {
	--ap-primary:       #10b981;
	--ap-primary-deep:  #059669;
	--ap-primary-tint:  #ecfdf5;
	--ap-primary-line:  #d1fae5;

	/* Slate scale for text, per the reference. */
	--ap-text:      #0f172a;
	--ap-text-soft: #475569;
	--ap-text-mute: #64748b;
	--ap-line:      #e2e8f0;
	--ap-canvas:    #f8fafc;

	/* Soft ambient elevation used on every card. */
	--ap-shadow: 0 2px 10px rgba(15, 23, 42, 0.04);
	--ap-shadow-lift: 0 6px 22px rgba(15, 23, 42, 0.08);
}
.ap-shell--app { background: var(--ap-canvas); }
/* ---- Cards: pure white, thin border, ambient shadow ---- */
.atfal-portal-body .ap-mod {
	background: #fff;
	border: 1px solid var(--ap-line);
	border-top: 1px solid var(--ap-line);
	border-radius: 16px;
	box-shadow: var(--ap-shadow);
	transition: box-shadow 0.18s ease;
}
.atfal-portal-body .ap-mod:hover { box-shadow: var(--ap-shadow-lift); }
.atfal-portal-body .ap-mod__title { color: var(--ap-text); }
.atfal-portal-body .ap-mod__empty,
.atfal-portal-body .ap-mod__lead,
.atfal-portal-body .ap-mod__note { color: var(--ap-text-mute); }
/* Inner surfaces sit on a tint rather than white-on-white. */
.atfal-portal-body .ap-mod .ap-course,
.atfal-portal-body .ap-mod .ap-salat__btn,
.atfal-portal-body .ap-mod .ap-tally li,
.atfal-portal-body .ap-mod .ap-badge,
.atfal-portal-body .ap-mod .ap-tile,
.atfal-portal-body .ap-mod .ap-dcard {
	background: #fff;
	border-color: var(--ap-line);
}
/* ---- Sidebar active pill ---- */
.atfal-portal-body .ap-side__link.is-active {
	background: var(--ap-primary);
	box-shadow: 0 4px 12px rgba(16, 185, 129, 0.30);
}
.atfal-portal-body .ap-side__link.is-active:hover { background: var(--ap-primary-deep); }
.atfal-portal-body .ap-side__link { color: var(--ap-text-mute) !important; }
.atfal-portal-body .ap-side__link:hover { background: #f1f5f9; color: var(--ap-text) !important; }
.atfal-portal-body .ap-side__out:hover { color: var(--ap-primary-deep) !important; }
/* ---- Primary actions ---- */
.atfal-portal-body .ap-btn--primary,
.atfal-portal-body .ap-course__go {
	background: var(--ap-primary);
	border-color: var(--ap-primary);
}
.atfal-portal-body .ap-btn--primary:hover,
.atfal-portal-body .ap-course:hover .ap-course__go {
	background: var(--ap-primary-deep);
	border-color: var(--ap-primary-deep);
}
.atfal-portal-body .ap-progress__bar,
.atfal-portal-body .ap-xp__fill { background: linear-gradient(90deg, #34d399, var(--ap-primary-deep)); }
.atfal-portal-body .ap-ring { background: conic-gradient(var(--ap-primary) var(--ap-pct,0%), var(--ap-primary-line) 0); }
.atfal-portal-body .ap-levelring { background: conic-gradient(var(--ap-primary) var(--ap-ring,0%), var(--ap-line) 0); }
.atfal-portal-body .ap-levelring__inner { background: linear-gradient(145deg, #34d399, var(--ap-primary-deep)); }
.atfal-portal-body .ap-xp__pill {
	background: var(--ap-primary-tint);
	color: var(--ap-primary-deep);
	border-color: var(--ap-primary-line);
}
.atfal-portal-body .ap-tally--points .ap-tally__n { color: var(--ap-primary-deep); }
/* Module icon badges keep their per-category hue but lose the heavy shadow. */
.atfal-portal-body .ap-mod__icon { box-shadow: inset 0 1.5px 0 rgba(255,255,255,0.5); }
/* ===========================================================================
   ANNOUNCEMENT BANNER
   =========================================================================== */
.ap-banner {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	padding: 14px 16px;
	margin-bottom: var(--space-5);
	background: #ecfdf5;
	border: 1px solid #d1fae5;
	border-radius: 16px;
	color: #064e3b;
}
.ap-banner__icon {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 34px; height: 34px;
	border-radius: 10px;
	background: #d1fae5;
	color: #047857;
}
.ap-banner__icon svg { width: 19px; height: 19px; }
.ap-banner__text {
	margin: 0;
	flex: 1 1 auto;
	min-width: 0;
	font-size: var(--text-base);
	line-height: 1.45;
	color: #064e3b;
}
.ap-banner__text strong { font-weight: var(--weight-heavy); }
.ap-banner__close {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	/* 44px target, drawn small — the hit area is the button, the glyph is the
	   part you see. Shrinking the button itself would fail the touch minimum. */
	width: 44px; height: 44px;
	margin: -10px -8px -10px 0;
	background: none;
	border: 0;
	border-radius: 10px;
	color: #047857;
	cursor: pointer;
}
.ap-banner__close svg { width: 17px; height: 17px; }
.ap-banner__close:hover { background: #d1fae5; }
.ap-banner__close:focus-visible { outline: 2px solid #047857; outline-offset: 2px; }
/* ===========================================================================
   WORKSPACE BENTO: 8 / 4
   =========================================================================== */
.ap-bento {
	display: grid;
	grid-template-columns: minmax(0, 8fr) minmax(0, 4fr);
	gap: var(--space-4);
	align-items: start;
}
.ap-bento__main,
.ap-bento__rail {
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
	min-width: 0;
}
@media (max-width: 1100px) {
	/*
	 * One column below this width. The rail's widgets are status readouts, so
	 * they follow the main column rather than leading it — a member arriving on
	 * a phone should land on what to do, not on what they have already done.
	 */
	.ap-bento { grid-template-columns: minmax(0, 1fr); }
}
/* ===========================================================================
   PERFORMANCE CARD: GAUGE + STAT ROWS
   =========================================================================== */
.ap-mod__sub {
	margin: 2px 0 0;
	font-size: var(--text-sm);
	color: var(--ap-text-mute);
	font-weight: var(--weight-normal);
}
.ap-mod__all {
	margin-left: auto;
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--ap-primary-deep);
	text-decoration: none;
	padding: 6px 12px;
	border: 1px solid var(--ap-primary-line);
	border-radius: 999px;
}
.ap-mod__all:hover { background: var(--ap-primary-tint); }
.ap-perf {
	display: grid;
	grid-template-columns: minmax(200px, 300px) minmax(0, 1fr);
	gap: var(--space-5);
	align-items: center;
}
@media (max-width: 820px) {
	.ap-perf { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
}
/* ---- Semi-circular gauge ---- */
.ap-gauge { position: relative; width: 100%; max-width: 300px; margin-inline: auto; }
.ap-gauge__svg { display: block; width: 100%; height: auto; overflow: visible; }
.ap-gauge__track,
.ap-gauge__value {
	fill: none;
	stroke-width: 20;
	stroke-linecap: round;
}
.ap-gauge__track { stroke: #e2e8f0; }
.ap-gauge__value {
	stroke: url(#ap-gauge-grad);
	/* Fallback for the gradient reference, which needs the <defs> below. */
	stroke: var(--ap-primary);
	stroke-dasharray: var(--ap-arc);
	stroke-dashoffset: var(--ap-offset);
	transition: stroke-dashoffset 900ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
	.ap-gauge__value { transition: none; }
}
.ap-gauge__center {
	position: absolute;
	left: 50%;
	/*
	 * The arc's centre of rotation sits at y=100 in a 118-tall viewBox, i.e.
	 * ~85% down. The readout is anchored just above it so it sits inside the
	 * bowl of the arc rather than on the baseline.
	 */
	top: 72%;
	transform: translate(-50%, -50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	text-align: center;
	pointer-events: none;
}
.ap-gauge__pct {
	font-size: clamp(1.9rem, 1.4rem + 1.6vw, 2.5rem);
	font-weight: var(--weight-heavy);
	line-height: 1;
	color: var(--ap-text);
	letter-spacing: -0.02em;
}
.ap-gauge__sym { font-size: 0.5em; margin-left: 1px; color: var(--ap-text-mute); }
.ap-gauge__tag {
	font-size: 0.66rem;
	font-weight: var(--weight-heavy);
	letter-spacing: 0.09em;
	color: var(--ap-primary-deep);
}
/* ---- Stat rows ---- */
.ap-stats { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.ap-stat {
	display: grid;
	/* Fixed badge, elastic text, fixed value. Naming the value track means the
	   three numbers align on one edge no matter how long the labels get —
	   which is what "DAY STREAK" wrapping used to break. */
	grid-template-columns: 44px minmax(0, 1fr) 58px;
	align-items: center;
	gap: 12px;
	padding: 10px 14px 10px 10px;
	background: #fff;
	border: 1px solid var(--ap-line);
	border-radius: 14px;
}
.ap-stat__badge {
	display: grid;
	place-items: center;
	width: 44px; height: 44px;
	border-radius: 50%;
}
.ap-stat__badge svg { width: 21px; height: 21px; }
.ap-stat--points .ap-stat__badge { background: #d1fae5; color: #047857; }
.ap-stat--rank   .ap-stat__badge { background: #fef3c7; color: #b45309; }
.ap-stat--streak .ap-stat__badge { background: #ede9fe; color: #6d28d9; }
.ap-stat__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ap-stat__label {
	font-size: var(--text-base);
	font-weight: var(--weight-bold);
	color: var(--ap-text);
	line-height: 1.25;
}
.ap-stat__meta { font-size: var(--text-sm); color: var(--ap-text-mute); line-height: 1.3; }
.ap-stat__plain {
	font-size: 1.2rem;
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	text-align: center;
	line-height: 1;
}
.ap-stat__ring {
	display: grid;
	place-items: center;
	width: 54px; height: 54px;
	border-radius: 50%;
	background: conic-gradient(var(--ap-primary) var(--ap-pct, 0%), #e2e8f0 0);
	justify-self: center;
}
.ap-stat__val {
	display: grid;
	place-items: center;
	width: 44px; height: 44px;
	border-radius: 50%;
	background: #fff;
	font-size: 0.9rem;
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1;
}
/* ===========================================================================
   SEVEN-DAY GRID
   =========================================================================== */
.ap-week {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(7, minmax(0, 1fr));
	gap: 4px;
}
.ap-week__day {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	padding: 8px 2px;
	border-radius: 12px;
}
.ap-week__day.is-today { background: var(--ap-primary-tint); }
.ap-week__mark {
	display: grid;
	place-items: center;
	width: 32px; height: 32px;
	border-radius: 50%;
	background: #f1f5f9;
	color: var(--ap-text-mute);
	font-size: 0.8rem;
	font-weight: var(--weight-heavy);
}
.ap-week__mark svg { width: 18px; height: 18px; }
.ap-week__day.is-lit .ap-week__mark { background: #fff7ed; color: #ea580c; }
.ap-week__label {
	font-size: 0.7rem;
	font-weight: var(--weight-bold);
	color: var(--ap-text-mute);
	letter-spacing: 0.02em;
}
.ap-week__foot {
	margin: var(--space-3) 0 0;
	font-size: var(--text-sm);
	color: var(--ap-text-mute);
}
/* ===========================================================================
   PENDING LIST
   =========================================================================== */
.ap-pending { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.ap-pending__row {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr) auto;
	align-items: center;
	gap: 10px;
}
.ap-pending__badge {
	display: grid;
	place-items: center;
	width: 40px; height: 40px;
	border-radius: 12px;
	background: #ede9fe;
	color: #6d28d9;
}
.ap-pending__badge svg { width: 19px; height: 19px; }
.ap-pending__text { display: flex; flex-direction: column; min-width: 0; }
.ap-pending__title {
	font-size: var(--text-base);
	font-weight: var(--weight-bold);
	color: var(--ap-text);
	line-height: 1.3;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.ap-pending__meta { font-size: var(--text-sm); color: var(--ap-text-mute); }
.ap-pending__go {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	/* 44px min height, per the project's own touch rule. */
	min-height: 44px;
	padding: 0 14px;
	border: 1px solid var(--ap-primary-line);
	border-radius: 999px;
	background: #fff;
	color: var(--ap-primary-deep);
	font-size: var(--text-sm);
	font-weight: var(--weight-heavy);
	text-decoration: none;
	white-space: nowrap;
}
.ap-pending__go:hover { background: var(--ap-primary-tint); border-color: var(--ap-primary); }
/* ===========================================================================
   GREETING: ONE LINE AT EVERY WIDTH
   ---------------------------------------------------------------------------
   The name, the dash and the Arabic are one greeting and must read as one row.
   With flex-wrap:wrap the Arabic dropped to a second line on narrow screens and
   left the dash dangling at the end of the name — which is what made the mobile
   header look broken rather than merely stacked.

   The fix is to forbid the wrap and let the type scale down instead, so the row
   survives to 320px. Both faces shrink together, so their relative weight stays
   the same and the row stays symmetrical at every size.
   =========================================================================== */
.ap-hello__name {
	flex-wrap: nowrap;
	align-items: center;
	min-width: 0;
}
.ap-hello__who-name,
.ap-hello__ar {
	/* Neither should absorb the shrink alone — they scale as a pair. */
	flex: 0 1 auto;
	min-width: 0;
}
.ap-hello__dash { flex: 0 0 auto; }
@media (max-width: 640px) {
	/*
	 * Sized to fit "CleverPanda63 – ٱلسَّلَامُ عَلَيْكُمْ" beside the ring at 375px.
	 * Both drop roughly a third; the Arabic keeps its slight size advantage
	 * because Ruqaa's x-height reads smaller than the sans at equal nominal
	 * size, so matching the numbers would make it look shrunken next to it.
	 */
	.ap-hello__who-name { font-size: clamp(1rem, 0.62rem + 1.85vw, 1.35rem); }
	.ap-hello__ar       { font-size: clamp(1rem, 0.58rem + 2.05vw, 1.4rem); }
	.ap-hello__name     { gap: 0 6px; }
	.ap-hello__dash     { font-size: var(--text-sm); }
	.ap-levelring       { width: 60px; height: 60px; }
	.ap-hello__who      { gap: var(--space-3); }
}
@media (max-width: 380px) {
	/* The last notch, for 320–360px handsets. */
	.ap-hello__who-name { font-size: 0.98rem; }
	.ap-hello__ar       { font-size: 1rem; }
	.ap-levelring       { width: 54px; height: 54px; }
}
/*
 * Active nav text, restated at higher specificity.
 *
 * The muted-link rule above carries !important (it has to, to beat the parent
 * theme's own nav colours) and sits later in the file than the active state —
 * so without this the active pill would render muted grey on emerald, which is
 * both wrong and well below AA. Specificity, not source order, settles it.
 */
.atfal-portal-body .ap-side__link.is-active,
.atfal-portal-body .ap-side__link.is-active:hover { color: #fff !important; }
.atfal-portal-body .ap-side__link.is-active svg { color: #fff; }
/* ---------------------------------------------------------------------------
   ACCENTS FOR THE NEW MODULES
   ---------------------------------------------------------------------------
   The default accent is brand red, so any module without an explicit hue lands
   on it. With emerald now carrying "primary", three red icon badges in a row
   read as alarm rather than as category — so each new module gets a hue, and
   lessons moves to emerald to match the primary action colour it now uses.

   Red is not reassigned to anything here. It stays free, which is what keeps it
   available to mean something when it does appear.
   --------------------------------------------------------------------------- */
.ap-mod--perf    { --ap-accent: #059669; }  /* emerald — primary */
.ap-mod--week    { --ap-accent: #ea580c; }  /* flame orange      */
.ap-mod--pending { --ap-accent: #6d28d9; }  /* violet            */
.ap-mod--lessons { --ap-accent: #059669; }  /* emerald — primary */

/*
 * The performance card is the page's anchor and carries the gauge, so it gets
 * a plain white ground rather than the emerald wash the accent would otherwise
 * give it — a tinted card behind a tinted arc muddies both.
 */
.atfal-portal-body .ap-mod--perf { background: #fff; }
/* ---- Remaining red carried over into the emerald shell ---- */
.atfal-portal-body .ap-avatar { background: var(--ap-primary-deep); }
.atfal-portal-body .ap-side__mark {
	background: var(--ap-primary);
	box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.20);
}
/* ---- Gauge on small screens ---- */
@media (max-width: 820px) {
	/*
	 * Unconstrained, the gauge grows to the full card width on a phone and
	 * pushes the three stats — the numbers a member actually came to see —
	 * below the fold. Capped so the whole card stays in one screenful.
	 */
	.ap-gauge { max-width: 230px; }
	.ap-gauge__pct { font-size: 1.75rem; }
}
/* ---------------------------------------------------------------------------
   CONTRAST CORRECTIONS TO THE EMERALD PALETTE
   ---------------------------------------------------------------------------
   Measured, not assumed. Two values from the reference design fail WCAG AA at
   the sizes this portal uses them:

     white on #10b981 (emerald-500)  = 2.54:1   needs 4.5:1
     #059669 text on white           = 3.76:1   needs 4.5:1

   The nav pill and the small emerald labels therefore use emerald-700 (#047857,
   5.2:1 on white and against white text), which is visually the same decision —
   a vibrant green pill — at a value a child with low vision can actually read.
   The 500 stays in use for large shapes where contrast is not load-bearing: the
   gauge arc, progress bars and rings, which carry no text.
   --------------------------------------------------------------------------- */
.atfal-portal-body { --ap-primary-text: #047857; }
.atfal-portal-body .ap-side__link.is-active {
	background: var(--ap-primary-text);
	box-shadow: 0 4px 12px rgba(4, 120, 87, 0.28);
}
.atfal-portal-body .ap-side__link.is-active:hover { background: #036649; }
.ap-gauge__tag,
.atfal-portal-body .ap-mod__all,
.atfal-portal-body .ap-pending__go,
.atfal-portal-body .ap-xp__pill,
.atfal-portal-body .ap-banner__icon,
.atfal-portal-body .ap-side__out:hover { color: var(--ap-primary-text) !important; }
.atfal-portal-body .ap-btn--primary,
.atfal-portal-body .ap-course__go {
	/* Button labels are white on the fill, so the fill must clear 4.5 too. */
	background: var(--ap-primary-deep);
	border-color: var(--ap-primary-deep);
}
.atfal-portal-body .ap-btn--primary:hover,
.atfal-portal-body .ap-course:hover .ap-course__go {
	background: var(--ap-primary-text);
	border-color: var(--ap-primary-text);
}
/* ---- Remaining measured AA fixes ---- */
/*
 * White-on-emerald buttons need the 700 too: at 4.5:1 the fill can be no
 * lighter than #047857. This is the same correction as the nav pill, applied
 * everywhere a white label sits on green.
 */
.atfal-portal-body .ap-btn--primary,
.atfal-portal-body .ap-course__go,
.atfal-portal-body .ap-avatar {
	background: var(--ap-primary-text);
	border-color: var(--ap-primary-text);
}
.atfal-portal-body .ap-btn--primary:hover,
.atfal-portal-body .ap-course:hover .ap-course__go {
	background: #036649;
	border-color: #036649;
}
/* Sidebar group labels: 10px bold at 2.24 was effectively decorative. */
.atfal-portal-body .ap-side__group { color: #475569; }
/* Unlit day counts sat at 4.34 — a hair under, on the one number in the widget
   a member is meant to read. */
.ap-week__mark { color: #475569; }
/* Pre-existing, fixed while measuring: month label and podium place. */
.atfal-portal-body .ap-event__mon { color: #5b3f96; }
.atfal-portal-body .ap-podium__place { color: var(--ap-text); }
/*
 * Decorative separators. Both are aria-hidden and carry no meaning, but at
 * 2.14 they were near-invisible rather than deliberately quiet.
 */
.ap-hello__dash, .ap-xp__sep { color: #556071; }
/* ---- Last two components still painting brand red ---- */
/*
 * "Full leaderboard" and the member's own handle on the podium. Both used red
 * to mean "this one matters to you", which is exactly the job emerald now does
 * in the portal — leaving them red would make red mean two different things on
 * the same screen.
 */
.atfal-portal-body .ap-mod__more { color: var(--ap-primary-text); }
.atfal-portal-body .ap-mod__more:hover { color: #036649; }
.atfal-portal-body .ap-podium__handle { color: var(--ap-primary-text); }
/* ---- Focus ring, restated in emerald for the portal ---- */
/*
 * The global token is a red halo. Inside the portal that now reads as an error
 * state rather than "you are here", so the ring is re-tinted at the body scope
 * and every existing :focus-visible rule picks it up unchanged.
 */
.atfal-portal-body { --focus-ring: 0 0 0 3px rgba(4, 120, 87, 0.40); }
/* New interactive elements need the ring explicitly — they are not .ap-btn. */
.ap-pending__go:focus-visible,
.ap-mod__all:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
	border-color: var(--ap-primary-text);
}
.atfal-portal-body .ap-mod__more:focus-visible { color: #036649; }
/* Beats `.ap-podium__slot.is-me .ap-podium__handle`, which is more specific
   than the body-scoped rule above. */
.atfal-portal-body .ap-podium__slot.is-me .ap-podium__handle { color: var(--ap-primary-text); }
/* The Salat streak pill: emerald on emerald tint measured 3.71. */
.atfal-portal-body .ap-pill { color: var(--ap-primary-text); }
/* ===========================================================================
   NO TRUNCATION, AND A SLEEKER TYPE SCALE
   ---------------------------------------------------------------------------
   Two related problems. Card titles were set at h3 (22px), which is large for
   a widget heading and forced long labels into ellipsis to fit — so the type
   size was causing the truncation, not just co-existing with it.

   Fixed together: headings come down a step, and every ellipsis and line-clamp
   in the portal is removed so text wraps to as many lines as it needs. Nothing
   in this interface is long enough to justify hiding, and a member should never
   have to guess at the end of a word.
   =========================================================================== */

/* ---- Truncation removed ---- */
.ap-podium__handle,
.ap-pending__title {
	overflow: visible;
	text-overflow: clip;
	white-space: normal;
	/* Long generated handles have no spaces to break on. */
	overflow-wrap: anywhere;
}
.ap-book__title,
.ap-dcard__teaser,
.ap-feature__body {
	display: block;
	-webkit-line-clamp: none;
	overflow: visible;
}
/* ---- Card headings: one step down ---- */
.atfal-portal-body .ap-mod__title {
	font-size: 1.0625rem;   /* 17px */
	line-height: 1.3;
	letter-spacing: -0.005em;
}
.atfal-portal-body .ap-mod__sub { font-size: var(--text-xs); margin-top: 1px; }
.atfal-portal-body .ap-mod__icon { width: 34px; height: 34px; border-radius: 10px; }
.atfal-portal-body .ap-mod__icon svg { width: 17px; height: 17px; }
.atfal-portal-body .ap-mod__head { gap: 10px; align-items: center; }
/* ---- Stat rows: smaller, and roomier for two-word labels ---- */
.ap-stat {
	grid-template-columns: 38px minmax(0, 1fr) auto;
	gap: 10px;
	padding: 9px 12px 9px 9px;
}
.ap-stat__badge { width: 38px; height: 38px; }
.ap-stat__badge svg { width: 18px; height: 18px; }
.ap-stat__label { font-size: var(--text-sm); line-height: 1.25; }
.ap-stat__meta  { font-size: var(--text-xs); }
.ap-stat__plain { font-size: 1.0625rem; min-width: 34px; }
.ap-stat__ring  { width: 46px; height: 46px; }
.ap-stat__val   { width: 37px; height: 37px; font-size: 0.8125rem; }
/* ---- Gauge: trimmed to match ---- */
.ap-gauge { max-width: 250px; }
.ap-gauge__pct { font-size: clamp(1.6rem, 1.2rem + 1.2vw, 2rem); }
.ap-gauge__tag { font-size: 0.6rem; letter-spacing: 0.08em; }
/* ---- Week grid ---- */
.ap-week__mark { width: 29px; height: 29px; font-size: 0.75rem; }
.ap-week__mark svg { width: 16px; height: 16px; }
.ap-week__label { font-size: 0.65rem; }
.ap-week__foot { font-size: var(--text-xs); margin-top: var(--space-2); }
/* ---- Pending rows ---- */
.ap-pending__row { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 9px; align-items: center; }
.ap-pending__badge { width: 34px; height: 34px; border-radius: 10px; }
.ap-pending__badge svg { width: 16px; height: 16px; }
.ap-pending__title { font-size: var(--text-sm); }
.ap-pending__meta { font-size: var(--text-xs); }
.ap-pending__go { font-size: var(--text-xs); padding: 0 12px; }
/* ---- Banner ---- */
.ap-banner__text { font-size: var(--text-sm); }
.ap-banner { padding: 12px 14px; margin-bottom: var(--space-4); }
.ap-banner__icon { width: 30px; height: 30px; border-radius: 9px; }
.ap-banner__icon svg { width: 17px; height: 17px; }
/* ---- Podium handles need room now that they wrap ---- */
.ap-podium__handle { font-size: 0.7rem; line-height: 1.25; text-align: center; }
.ap-podium__handle small { display: block; color: var(--ap-text-mute); font-weight: var(--weight-medium); }
.ap-podium__points { font-size: 0.65rem; }
/* ---- Sidebar / topbar ---- */
.atfal-portal-body .ap-side__link { font-size: var(--text-sm); }
.atfal-portal-body .ap-topbar__title { font-size: var(--text-sm); }
.atfal-portal-body .ap-topbar__handle { font-size: var(--text-sm); }
/* ===========================================================================
   DASHBOARD REFINEMENT — HIERARCHY PASS
   ---------------------------------------------------------------------------
   The previous layout gave every region the same card treatment, so nothing
   read as more important than anything else. Three levels are introduced here:

     Primary    Continue Learning — the only element that answers "what next".
                Dark, full-bleed, its own button. Elevated above the rest.
     Secondary  Overview, Verse, My Lessons — white cards, soft border.
     Tertiary   Rail widgets — flatter still: no shadow, lighter border.

   Everything else in this block exists to serve that ordering.
   =========================================================================== */

/* ---- Spacing scale used throughout this pass ----
   4 / 8 / 12 / 16 / 20 / 24 / 32. No arbitrary values below. */
.atfal-portal-body {
	--ap-pad-card: 20px;
	--ap-gap-sec: 16px;
	--ap-radius: 16px;
}
/* ---- Page header (not a card) ---- */
.ap-greet { margin-bottom: 20px; }
.ap-greet__title {
	margin: 0;
	display: flex;
	align-items: center;
	flex-wrap: nowrap;
	gap: 0;
	line-height: 1.25;
	letter-spacing: -0.01em;
	color: var(--ap-text);
	font-family: var(--font-body);
}
.ap-greet__ar {
	font-family: var(--font-arabic-display);
	font-size: clamp(1.15rem, 0.95rem + 0.7vw, 1.45rem);
	font-weight: 700;
	line-height: var(--leading-snug);
	color: var(--ap-text);
	white-space: nowrap;
	flex: 0 1 auto;
	/* Tashkeel paints outside the line box; nothing sits above it to collide. */
	overflow: visible;
}
.ap-greet__sep { margin-inline-end: 7px; color: var(--ap-text); flex: 0 0 auto; }
.ap-greet__name {
	font-size: clamp(1.15rem, 0.9rem + 0.9vw, 1.5rem);
	font-weight: var(--weight-heavy);
	flex: 0 1 auto;
	min-width: 0;
}
.ap-greet__sub {
	margin: 4px 0 0;
	font-size: var(--text-sm);
	color: var(--ap-text-mute);
}
/* ---- Section titles: quieter than the old card headings ---- */
.atfal-portal-body .ap-mod__title--quiet {
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--ap-text-soft);
	letter-spacing: 0;
}
/* ===========================================================================
   OVERVIEW
   =========================================================================== */
.atfal-portal-body .ap-mod--overview { padding: var(--ap-pad-card); }
.ap-ov {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: 24px;
	align-items: center;
	margin-top: 14px;
}
.ap-ov__level { display: flex; align-items: center; gap: 16px; min-width: 0; }
.ap-ov__meta { min-width: 0; }
.ap-ov__name {
	margin: 0;
	font-size: var(--text-base);
	font-weight: var(--weight-heavy);
	color: var(--ap-primary-text);
	line-height: 1.25;
}
.ap-ov__xp {
	margin: 3px 0 0;
	font-size: var(--text-sm);
	color: var(--ap-text-mute);
	font-variant-numeric: tabular-nums;
}
.ap-ov__meter {
	display: block;
	width: min(240px, 100%);
	height: 8px;
	margin-top: 8px;
	border-radius: 999px;
	background: #e2e8f0;
	overflow: hidden;
}
.ap-ov__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: linear-gradient(90deg, #34d399, var(--ap-primary-deep));
}
.ap-ov__togo { margin: 7px 0 0; font-size: var(--text-xs); color: var(--ap-text-mute); }
/* ---- Stats: rules, not boxes ---- */
.ap-ov__stats {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	align-items: stretch;
}
.ap-ovstat {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	gap: 2px;
	padding: 0 20px;
	text-align: center;
	min-width: 0;
}
.ap-ovstat + .ap-ovstat { border-left: 1px solid var(--ap-line); }
.ap-ovstat:last-child { padding-right: 4px; }
.ap-ovstat__icon {
	display: grid;
	place-items: center;
	width: 34px; height: 34px;
	border-radius: 50%;
	margin-bottom: 4px;
}
.ap-ovstat__icon svg { width: 17px; height: 17px; }
.ap-ovstat--streak .ap-ovstat__icon { background: #ffedd5; color: #c2410c; }
.ap-ovstat--points .ap-ovstat__icon { background: #d1fae5; color: var(--ap-primary-text); }
.ap-ovstat--rank   .ap-ovstat__icon { background: #ede9fe; color: #5b21b6; }
.ap-ovstat__n {
	font-size: 1.35rem;
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1.1;
	font-variant-numeric: tabular-nums;
}
.ap-ovstat__l { font-size: var(--text-xs); color: var(--ap-text-mute); line-height: 1.3; }
.ap-ovstat__sub { font-size: 0.6875rem; color: var(--ap-text-mute); line-height: 1.3; }
@media (max-width: 900px) {
	.ap-ov { grid-template-columns: minmax(0, 1fr); gap: 18px; }
	.ap-ov__stats { justify-content: space-between; }
	.ap-ovstat { flex: 1 1 0; padding: 0 8px; }
}
/* ===========================================================================
   CONTINUE LEARNING — the primary action
   =========================================================================== */
.atfal-portal-body .ap-continue {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: end;
	gap: 20px;
	padding: 22px;
	border: 0;
	border-radius: var(--ap-radius);
	background:
		radial-gradient(120% 140% at 100% 0%, rgba(52, 211, 153, 0.22), transparent 60%),
		linear-gradient(135deg, #064e3b, #065f46 58%, #047857);
	/* The one genuinely elevated surface on the page. */
	box-shadow: 0 10px 28px rgba(6, 78, 59, 0.22);
	color: #fff;
}
.atfal-portal-body .ap-continue:hover { box-shadow: 0 14px 34px rgba(6, 78, 59, 0.28); }
.ap-continue__body { min-width: 0; }
.ap-continue__eyebrow {
	margin: 0 0 6px;
	font-size: 0.6875rem;
	font-weight: var(--weight-heavy);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: #a7f3d0;
}
.ap-continue__title {
	margin: 0;
	font-size: clamp(1.2rem, 1rem + 0.8vw, 1.6rem);
	font-weight: var(--weight-heavy);
	line-height: 1.2;
	letter-spacing: -0.01em;
	color: #fff;
}
.ap-continue__meta {
	margin: 8px 0 0;
	font-size: var(--text-sm);
	color: #d1fae5;
}
.ap-continue__dot { margin: 0 7px; opacity: 0.65; }
.ap-continue__track { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
.ap-continue__meter {
	flex: 1 1 auto;
	max-width: 320px;
	height: 8px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.22);
	overflow: hidden;
}
.ap-continue__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: #6ee7b7;
}
.ap-continue__pct {
	flex: 0 0 auto;
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: #d1fae5;
	font-variant-numeric: tabular-nums;
}
.ap-continue__left { margin: 10px 0 0; font-size: var(--text-xs); color: #a7f3d0; }
.ap-continue__go {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 48px;
	padding: 0 22px;
	border-radius: 999px;
	background: #fff;
	color: #065f46;
	font-size: var(--text-base);
	font-weight: var(--weight-heavy);
	text-decoration: none;
	white-space: nowrap;
	transition: transform 0.15s ease, background 0.15s ease;
}
.ap-continue__go:hover { background: #ecfdf5; transform: translateX(2px); }
.ap-continue__go:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.65);
}
@media (prefers-reduced-motion: reduce) {
	.ap-continue__go, .ap-continue__go:hover { transition: none; transform: none; }
}
@media (max-width: 720px) {
	.atfal-portal-body .ap-continue { grid-template-columns: minmax(0, 1fr); align-items: start; }
	.ap-continue__go { width: 100%; justify-content: center; }
}
/* ===========================================================================
   RAIL: flatter than the main column
   =========================================================================== */
.atfal-portal-body .ap-bento__rail .ap-mod {
	box-shadow: none;
	border-color: #e8edf3;
	padding: 18px;
}
.atfal-portal-body .ap-bento__rail .ap-mod:hover { box-shadow: var(--ap-shadow); }
.atfal-portal-body .ap-bento__rail .ap-mod__head { margin-bottom: 10px; }
/* ---- Daily progress ---- */
.ap-week__head {
	margin: 0;
	font-size: var(--text-base);
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1.25;
}
.ap-week__sub { margin: 2px 0 14px; font-size: var(--text-xs); color: var(--ap-text-mute); }
.ap-week__day { gap: 7px; padding: 0; }
.ap-week__day.is-today { background: none; }
.ap-week__mark {
	background: #f1f5f9;
	border: 1px solid transparent;
	color: var(--ap-text-mute);
}
.ap-week__day.is-done .ap-week__mark { background: #d1fae5; color: var(--ap-primary-text); }
.ap-week__day.is-part .ap-week__mark { background: #ffedd5; color: #c2410c; }
.ap-week__day.is-empty .ap-week__mark { background: transparent; border-color: var(--ap-line); }
/* Today gets a ring rather than a filled cell, so it reads as "now" without
   claiming a completion the member has not earned yet. */
.ap-week__day.is-today .ap-week__mark { box-shadow: 0 0 0 2px var(--ap-primary-line); }
/* ---- Games & quizzes, with the folded-in pending rows ---- */
.ap-mod--play .ap-pending { margin-top: 10px; }
.ap-mod--play .ap-pending__row {
	grid-template-columns: minmax(0, 1fr) auto;
	padding: 8px 0;
	border-top: 1px solid var(--ap-line);
}
.ap-mod--play .ap-mod__more {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-top: 12px;
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	text-decoration: none;
}
/* ---- The member's own leaderboard row, in the portal's own accent ---- */
/*
 * The original comment on these rules called this "the one thing on this screen
 * worth marking in red". That reasoning still holds — it is just emerald now,
 * and leaving it red would put two different "this matters" colours in the same
 * widget.
 */
.atfal-portal-body .ap-board__row--me { background: var(--ap-primary-tint); }
.atfal-portal-body .ap-board__row--me .ap-board__rank,
.atfal-portal-body .ap-board__row--me .ap-board__points { color: var(--ap-primary-text); }
.atfal-portal-body .ap-board__you { background: var(--ap-primary-text); }
/*
 * Leaderboard rank numbers were grey-300 (2.24:1) — fine as decoration in the
 * old podium layout where the medal carried the place, but in the list they are
 * the only thing stating position, so they have to be readable.
 */
.atfal-portal-body .ap-board__rank { color: var(--ap-text-mute); }
/* ---------------------------------------------------------------------------
   MOBILE: THE NEXT ACTION LEADS
   ---------------------------------------------------------------------------
   On desktop the overview is a single compact row, so Continue Learning still
   sits high on the page. Stacked on a phone the overview runs ~250px and pushes
   Continue past the halfway mark of the first screen — so on small viewports
   the order flips and the action leads.

   This does put visual order out of step with DOM order for these two sections.
   That is a deliberate, contained trade: they are adjacent siblings, both are
   landmarks, and a screen-reader user still reaches both immediately. The
   alternative — reordering in the markup — would push the overview below the
   fold for desktop users, who are the majority here.
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
	.ap-bento__main { display: flex; flex-direction: column; }
	.ap-bento__main .ap-continue { order: -1; }
}
/* ---------------------------------------------------------------------------
   GLOBAL LINK COLOUR
   ---------------------------------------------------------------------------
   `.atfal-portal-body a` still resolved to brand red. Its specificity (0,1,1)
   quietly beat every single-class component rule I wrote, so any new link came
   out red unless it happened to be over-qualified — the Continue button was the
   first to show it, and it would have caught every link added after.

   Fixed at the root rather than per-component. Restated at identical
   specificity and later in the file so it wins by source order.
   --------------------------------------------------------------------------- */
.atfal-portal-body a { color: var(--ap-primary-text); }
.atfal-portal-body .ap-continue__go { color: #065f46; }
/* ===========================================================================
   CONTRIBUTE & MY JOURNEY
   ---------------------------------------------------------------------------
   Both pages are deliberately quieter than the dashboard. No rings, no
   percentages, no progress bars — those belong to the parts of the portal that
   measure. These parts record.
   =========================================================================== */

/* ---- Opportunity card ---- */
.ap-opp {
	background: #fff;
	border: 1px solid var(--ap-line);
	border-radius: 16px;
	padding: 20px;
	margin-bottom: var(--space-4);
	box-shadow: var(--ap-shadow);
}
.ap-opp--approved { border-color: var(--ap-primary-line); background: #fbfffd; }
.ap-opp__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.ap-opp__kind {
	display: inline-block;
	padding: 3px 10px;
	border-radius: 999px;
	font-size: var(--text-xs);
	font-weight: var(--weight-heavy);
	/* Tinted from the pillar rather than a fixed palette, so the five pillars
	   stay visually distinct without a per-kind rule for each. */
	color: var(--ap-tint, #475569);
	background: color-mix(in srgb, var(--ap-tint, #475569) 12%, #fff);
}
.ap-opp__done,
.ap-opp__waiting {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	padding: 3px 10px;
	border-radius: 999px;
}
.ap-opp__done { background: var(--ap-primary-tint); color: var(--ap-primary-text); }
.ap-opp__waiting { background: #fef3c7; color: #92400e; }
.ap-opp__title {
	margin: 0 0 6px;
	font-size: 1.0625rem;
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1.3;
}
.ap-opp__why { margin: 0 0 12px; font-size: var(--text-sm); color: var(--ap-text-soft); }
.ap-opp__facts {
	list-style: none;
	margin: 0 0 14px;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 6px 14px;
	font-size: var(--text-xs);
	color: var(--ap-text-mute);
}
.ap-opp__facts li { display: flex; align-items: center; gap: 6px; }
.ap-opp__facts li + li::before { content: "·"; margin-right: 8px; color: var(--ap-line); }
.ap-opp__steps { margin-bottom: 14px; }
.ap-opp__steps h3 {
	margin: 0 0 4px;
	font-size: var(--text-xs);
	font-weight: var(--weight-heavy);
	text-transform: uppercase;
	letter-spacing: 0.07em;
	color: var(--ap-text-mute);
}
.ap-opp__steps p { margin: 0 0 6px; font-size: var(--text-sm); color: var(--ap-text-soft); line-height: 1.5; }
.ap-opp__label {
	display: block;
	margin-bottom: 6px;
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--ap-text);
}
.ap-opp__textarea {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var(--ap-line);
	border-radius: 12px;
	font: inherit;
	font-size: var(--text-sm);
	color: var(--ap-text);
	margin-bottom: 10px;
	resize: vertical;
}
.ap-opp__textarea:focus-visible {
	outline: none;
	border-color: var(--ap-primary);
	box-shadow: var(--focus-ring);
}
.ap-opp__note {
	background: #fffbeb;
	border-left: 3px solid #f59e0b;
	padding: 10px 12px;
	border-radius: 8px;
	font-size: var(--text-sm);
	color: #78350f;
	margin: 0 0 12px;
}
.ap-opp__note strong { display: block; margin-bottom: 2px; }
.ap-opp__done-box { border-top: 1px solid var(--ap-line); padding-top: 12px; margin-top: 4px; }
.ap-opp__quote {
	margin: 0 0 8px;
	font-size: var(--text-sm);
	color: var(--ap-text-soft);
	font-style: italic;
}
/* ---- My Journey ---- */
.ap-story { padding: 20px; }
.ap-story__line {
	margin: 0 0 8px;
	font-size: 1.0625rem;
	line-height: 1.5;
	color: var(--ap-text);
}
.ap-story__line:last-child { margin-bottom: 0; }
.ap-recog { list-style: none; margin: 0; padding: 0; }
.ap-recog__item {
	padding: 14px 0;
	border-bottom: 1px solid var(--ap-line);
}
.ap-recog__item:last-child { border-bottom: 0; padding-bottom: 0; }
.ap-recog__msg {
	margin: 0 0 6px;
	font-size: var(--text-base);
	line-height: 1.5;
	color: var(--ap-text);
}
.ap-recog__by { margin: 0; font-size: var(--text-xs); color: var(--ap-text-mute); }
.ap-recog__sep { margin: 0 6px; }
.ap-contrib { list-style: none; margin: 0; padding: 0; }
.ap-contrib__item { padding: 12px 0; border-bottom: 1px solid var(--ap-line); }
.ap-contrib__item:last-child { border-bottom: 0; padding-bottom: 0; }
.ap-contrib__what {
	margin: 0 0 4px;
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	color: var(--ap-text);
}
.ap-contrib__quote { margin: 0 0 4px; font-size: var(--text-sm); color: var(--ap-text-soft); font-style: italic; }
.ap-contrib__when { margin: 0; font-size: var(--text-xs); color: var(--ap-text-mute); }
/* ---- Verse splash and banner: emerald, not red ---- */
/*
 * These predate the palette change and were still painting the brand red on
 * the one screen a member sees before anything else. Scoped overrides rather
 * than edits to the original rules, so the marketing site's verse treatment is
 * untouched.
 */
.atfal-portal-body .ap-splash__eyebrow,
.atfal-portal-body .ap-splash__ref,
.atfal-portal-body .ap-vbanner__ref,
.atfal-portal-body .ap-verse-banner__ref { color: var(--ap-primary-text) !important; }
.atfal-portal-body .ap-vbanner,
.atfal-portal-body .ap-verse-banner {
	background: var(--ap-primary-tint);
	border-color: var(--ap-primary-line);
}
.atfal-portal-body .ap-splash__ref a { color: var(--ap-primary-text) !important; }
/* The verse bar's real class names. */
.atfal-portal-body .ap-verse-bar {
	background: var(--ap-primary-tint);
	border-color: var(--ap-primary-line);
}
.atfal-portal-body .ap-verse-bar__ref,
.atfal-portal-body .ap-verse-bar__ref a { color: var(--ap-primary-text) !important; }
/* ---- Journey story: block, not the module's default flex ---- */
/*
 * .ap-mod is a flex column with a gap, which laid these sentences out as flex
 * items and let them shrink into narrow columns beside each other. The story
 * is prose and wants normal block flow.
 */
.atfal-portal-body .ap-story { display: block; }
/* Recognition module had no accent and so fell back to brand red. */
.ap-mod--recog { --ap-accent: #be123c; }
.ap-mod--contrib { --ap-accent: #b45309; }
.ap-contrib__reply {
	margin: 6px 0 4px;
	padding: 8px 12px;
	background: var(--ap-primary-tint);
	border-left: 3px solid var(--ap-primary);
	border-radius: 8px;
	font-size: var(--text-sm);
	color: #064e3b;
	line-height: 1.45;
}
.ap-contrib__replyby { display: block; margin-top: 3px; font-size: var(--text-xs); color: var(--ap-primary-text); }
/* ===========================================================================
   MY JOURNEY — THE VISUAL PATH
   ---------------------------------------------------------------------------
   Everything here is drawn with CSS: rings are conic-gradients, the connecting
   line is a pseudo-element, the icons are inline SVG already in the page. No
   images, so it costs no requests, scales to any density, and recolours per
   pillar from one custom property.
   =========================================================================== */

.ap-jhead { margin-bottom: 22px; }
.ap-jhead__title {
	margin: 0;
	font-size: clamp(1.4rem, 1.1rem + 1.2vw, 1.9rem);
	font-weight: var(--weight-heavy);
	letter-spacing: -0.02em;
	color: var(--ap-text);
}
.ap-jhead__sub { margin: 4px 0 0; font-size: var(--text-sm); color: var(--ap-text-mute); }
.ap-jhead__sub strong { color: var(--ap-text); font-weight: var(--weight-heavy); }
/* ---- The path ---- */
.ap-path { margin-bottom: 20px; }
.ap-path__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 0;
}
.ap-path__item { position: relative; display: flex; justify-content: center; }
/*
 * The connector. Drawn behind the nodes and stopping at the first and last
 * item so the line does not run off either end of the path.
 */
.ap-path__item::before {
	content: "";
	position: absolute;
	top: 32px;
	left: 0;
	right: 0;
	height: 2px;
	background: var(--ap-line);
	z-index: 0;
}
.ap-path__item:first-child::before { left: 50%; }
.ap-path__item:last-child::before { right: 50%; }
.ap-node {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	width: 100%;
	padding: 4px 2px 8px;
	background: none;
	border: 0;
	cursor: pointer;
	font: inherit;
	color: inherit;
	border-radius: 12px;
}
.ap-node:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* The ring is the milestone count, drawn as an arc in the pillar's colour. */
.ap-node__ring {
	position: relative;
	display: grid;
	place-items: center;
	width: 64px;
	height: 64px;
	border-radius: 50%;
	background: conic-gradient(var(--ap-p) var(--ap-pct, 0%), var(--ap-line) 0);
	transition: transform 0.18s ease;
}
.ap-node__disc {
	display: grid;
	place-items: center;
	width: 54px;
	height: 54px;
	border-radius: 50%;
	background: #fff;
	color: var(--ap-p);
}
.ap-node__disc svg { width: 23px; height: 23px; }
.ap-node.is-dormant .ap-node__ring { background: var(--ap-line); }
.ap-node.is-dormant .ap-node__disc { color: #94a3b8; }
/* A finished pillar fills solid — the clearest possible "this one is done". */
.ap-node.is-complete .ap-node__disc { background: var(--ap-p); color: #fff; }
.ap-node__tick {
	position: absolute;
	right: -2px;
	bottom: -2px;
	display: grid;
	place-items: center;
	width: 22px;
	height: 22px;
	border-radius: 50%;
	background: var(--ap-p);
	color: #fff;
	border: 2px solid #fff;
}
.ap-node__tick svg { width: 11px; height: 11px; }
.ap-node__label {
	font-size: var(--text-sm);
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1.2;
}
.ap-node__count {
	font-size: var(--text-xs);
	color: var(--ap-text-mute);
	font-variant-numeric: tabular-nums;
}
.ap-node.is-open .ap-node__label { color: var(--ap-p); }
@media (hover: hover) {
	.ap-node:hover .ap-node__ring { transform: translateY(-2px); }
}
/* An open node sits slightly proud so the connection to its panel is obvious. */
.ap-node.is-open .ap-node__ring { transform: translateY(-3px); box-shadow: 0 6px 16px color-mix(in srgb, var(--ap-p) 30%, transparent); }
@media (prefers-reduced-motion: reduce) {
	.ap-node__ring, .ap-node:hover .ap-node__ring, .ap-node.is-open .ap-node__ring { transition: none; transform: none; }
}
/* ---- Milestone panel ---- */
.ap-panel {
	display: none;
	background: #fff;
	border: 1px solid var(--ap-line);
	border-top: 3px solid var(--ap-p);
	border-radius: 16px;
	padding: 18px 20px;
	margin-bottom: 22px;
	box-shadow: var(--ap-shadow);
}
.ap-panel.is-open { display: block; }
/*
 * No .no-js fallback is needed: each node is a real link to ?pillar=…, so with
 * scripting off the server simply renders a different panel open. The page is
 * fully usable either way.
 */

.ap-panel__tag {
	margin: 0 0 14px;
	font-size: var(--text-xs);
	font-weight: var(--weight-heavy);
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--ap-p);
}
.ap-mslist { list-style: none; margin: 0; padding: 0; }
.ap-ms {
	position: relative;
	display: grid;
	grid-template-columns: 34px minmax(0, 1fr);
	gap: 12px;
	padding-bottom: 18px;
}
.ap-ms:last-child { padding-bottom: 0; }
/* Vertical rail joining the milestone dots. */
.ap-ms:not(:last-child)::before {
	content: "";
	position: absolute;
	left: 16px;
	top: 34px;
	bottom: 2px;
	width: 2px;
	background: var(--ap-line);
}
.ap-ms.is-done:not(:last-child)::before { background: color-mix(in srgb, var(--ap-p) 45%, #fff); }
.ap-ms__dot {
	display: grid;
	place-items: center;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	font-size: var(--text-xs);
	font-weight: var(--weight-heavy);
	background: #f1f5f9;
	color: var(--ap-text-mute);
	border: 2px solid transparent;
}
.ap-ms__dot svg { width: 15px; height: 15px; }
.ap-ms.is-done .ap-ms__dot { background: var(--ap-p); color: #fff; }
.ap-ms.is-next .ap-ms__dot { background: #fff; border-color: var(--ap-p); color: var(--ap-p); }
.ap-ms.is-locked .ap-ms__dot { opacity: 0.55; }
.ap-ms__body { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding-top: 5px; }
.ap-ms__label {
	font-size: var(--text-sm);
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1.3;
}
.ap-ms.is-locked .ap-ms__label { color: var(--ap-text-mute); font-weight: var(--weight-bold); }
.ap-ms__line { font-size: var(--text-xs); color: var(--ap-text-mute); line-height: 1.4; }
.ap-ms__meter {
	display: block;
	width: min(220px, 100%);
	height: 6px;
	margin: 4px 0 2px;
	border-radius: 999px;
	background: var(--ap-line);
	overflow: hidden;
}
.ap-ms__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: var(--ap-p);
	transition: width 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) { .ap-ms__fill { transition: none; } }
/* ---- Recognition & contribution cards ---- */
.ap-jsection { margin-bottom: 22px; }
.ap-jsection__title {
	margin: 0 0 12px;
	font-size: var(--text-sm);
	font-weight: var(--weight-heavy);
	color: var(--ap-text-soft);
}
.ap-cards {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: 12px;
}
.ap-rcard, .ap-ccard {
	background: #fff;
	border: 1px solid var(--ap-line);
	border-left: 3px solid var(--ap-p);
	border-radius: 14px;
	padding: 14px 16px;
	box-shadow: var(--ap-shadow);
}
.ap-rcard__kind, .ap-ccard__kind {
	display: inline-block;
	margin-bottom: 8px;
	padding: 2px 9px;
	border-radius: 999px;
	font-size: 0.6875rem;
	font-weight: var(--weight-heavy);
	color: var(--ap-p);
	background: color-mix(in srgb, var(--ap-p) 12%, #fff);
}
.ap-rcard__msg {
	margin: 0 0 8px;
	font-size: var(--text-sm);
	line-height: 1.5;
	color: var(--ap-text);
}
.ap-rcard__by, .ap-ccard__when { margin: 0; font-size: var(--text-xs); color: var(--ap-text-mute); }
.ap-ccard__what {
	margin: 0 0 6px;
	font-size: var(--text-sm);
	font-weight: var(--weight-heavy);
	color: var(--ap-text);
	line-height: 1.35;
}
.ap-ccard__reply {
	margin: 0 0 8px;
	padding: 8px 10px;
	background: var(--ap-primary-tint);
	border-radius: 8px;
	font-size: var(--text-xs);
	color: #064e3b;
	line-height: 1.45;
}
/* ---- Small screens: the path turns vertical ---- */
@media (max-width: 720px) {
	.ap-path__list { grid-template-columns: minmax(0, 1fr); }
	.ap-path__item { justify-content: flex-start; }
	.ap-path__item::before {
		top: 0; bottom: 0; left: 36px; right: auto;
		width: 2px; height: auto;
	}
	.ap-path__item:first-child::before { top: 36px; left: 36px; }
	.ap-path__item:last-child::before { bottom: 50%; }
	.ap-node {
		flex-direction: row;
		align-items: center;
		gap: 14px;
		padding: 6px 8px;
		text-align: left;
	}
	.ap-node__ring { width: 56px; height: 56px; flex: 0 0 auto; }
	.ap-node__disc { width: 47px; height: 47px; }
	.ap-node__label { flex: 1 1 auto; }
	.ap-node.is-open .ap-node__ring,
	.ap-node:hover .ap-node__ring { transform: none; }
}
/* ---- Measured contrast corrections on the journey ---- */
/*
 * Locked milestone numbers sat at 4.34 on their grey disc — just under AA, and
 * they are the only thing identifying which step is which.
 */
.ap-ms__dot { color: #475569; }
/*
 * Pillar-tinted labels on a 12% tint of the same hue: fine for the darker
 * pillars, 4.26 for the amber one. Mixing the text toward black darkens every
 * pillar consistently rather than hand-tuning five values that would drift
 * apart the moment a pillar colour changes.
 */
.ap-rcard__kind,
.ap-ccard__kind,
.ap-opp__kind { color: color-mix(in srgb, var(--ap-p, var(--ap-tint, #475569)) 78%, #000); }
/* ---- Opportunity instructions, collapsed by default ---- */
.ap-opp__steps > summary {
	cursor: pointer;
	list-style: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: var(--text-xs);
	font-weight: var(--weight-heavy);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ap-text-mute);
	padding: 4px 0;
	min-height: 32px;
}
.ap-opp__steps > summary::-webkit-details-marker { display: none; }
.ap-opp__steps > summary::after {
	content: "";
	width: 7px; height: 7px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg) translateY(-2px);
	transition: transform 0.16s ease;
}
.ap-opp__steps[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
.ap-opp__steps > summary:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: 6px; }
@media (prefers-reduced-motion: reduce) { .ap-opp__steps > summary::after { transition: none; } }
/* ---- Today ---- */
.atfal-portal-body .ap-today{padding:18px 20px}
.ap-today__head{display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:14px}
.ap-today__title{
	margin:0; font-size:1.15rem; font-weight:var(--weight-heavy);
	color:var(--ap-text); line-height:1.2; letter-spacing:-.01em;
}
.ap-today__sub{margin:3px 0 0; font-size:var(--text-sm); color:var(--ap-text-mute)}
.ap-today.is-complete .ap-today__sub{color:var(--ap-primary-text); font-weight:var(--weight-bold)}
.ap-today__streak{
	display:inline-flex; align-items:baseline; gap:5px; flex:0 0 auto;
	padding:6px 12px; border-radius:999px;
	background:#fff7ed; border:1px solid #fed7aa;
}
.ap-today__flame{color:#ea580c; align-self:center; display:grid; place-items:center}
.ap-today__flame svg{width:15px; height:15px}
.ap-today__streakn{font-size:1.05rem; font-weight:var(--weight-heavy); color:#9a3412}
.ap-today__streakl{font-size:var(--text-xs); color:#c2410c}
/* Five prayers, one row. The tile is the target — 56px tall, well over the
   44px minimum, because this is the most-tapped control in the portal. */
.ap-prayers{
	list-style:none; margin:0 0 14px; padding:0;
	display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:8px;
}
.ap-prayers form{margin:0}
.ap-prayer{
	width:100%; min-height:56px;
	display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
	padding:8px 4px; border-radius:12px; cursor:pointer;
	background:#fff; border:1.5px solid var(--ap-line);
	font:inherit; color:var(--ap-text-soft);
	transition:background .15s ease, border-color .15s ease, transform .12s ease;
}
.ap-prayer:hover{border-color:var(--ap-primary); transform:translateY(-1px)}
.ap-prayer:focus-visible{outline:none; box-shadow:var(--focus-ring)}
.ap-prayer__mark{
	display:grid; place-items:center; width:22px; height:22px; border-radius:50%;
	border:1.5px solid var(--ap-line); background:#fff; color:transparent;
}
.ap-prayer__mark svg{width:12px; height:12px}
.ap-prayer__name{font-size:var(--text-xs); font-weight:var(--weight-bold); line-height:1.2}
.ap-prayer.is-done{
	background:var(--ap-primary-tint); border-color:var(--ap-primary-line);
	color:var(--ap-primary-text);
}
.ap-prayer.is-done .ap-prayer__mark{
	background:var(--ap-primary-text); border-color:var(--ap-primary-text); color:#fff;
}
@media (prefers-reduced-motion:reduce){
	.ap-prayer,.ap-prayer:hover{transition:none; transform:none}
}
/* Seven-day strip, tucked under the prayers as context not as a headline. */
.ap-today__week{border-top:1px solid var(--ap-line); padding-top:12px}
.ap-wk{
	list-style:none; margin:0; padding:0;
	display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:6px;
}
.ap-wk__day{display:flex; flex-direction:column; align-items:center; gap:5px}
.ap-wk__mark{
	display:grid; place-items:center; width:26px; height:26px; border-radius:50%;
	background:#f1f5f9; color:#475569;
	font-size:.7rem; font-weight:var(--weight-heavy);
	border:1px solid transparent;
}
.ap-wk__mark svg{width:13px; height:13px}
.ap-wk__day.is-done .ap-wk__mark{background:var(--ap-primary-tint); color:var(--ap-primary-text)}
.ap-wk__day.is-part .ap-wk__mark{background:#ffedd5; color:#c2410c}
.ap-wk__day.is-empty .ap-wk__mark{background:transparent; border-color:var(--ap-line)}
.ap-wk__day.is-today .ap-wk__mark{box-shadow:0 0 0 2px var(--ap-primary-line)}
.ap-wk__lbl{font-size:.65rem; font-weight:var(--weight-bold); color:var(--ap-text-mute)}
/* ---- Badge cards on My Journey ---- */
.ap-bcard{
	display:flex; align-items:flex-start; gap:11px;
	background:#fff; border:1px solid var(--ap-line);
	border-left:3px solid #f59e0b; border-radius:14px; padding:13px 15px;
	box-shadow:var(--ap-shadow);
}
.ap-bcard__medal{
	display:grid; place-items:center; width:32px; height:32px; border-radius:50%;
	background:#fffbeb; color:#b45309; flex:0 0 auto;
}
.ap-bcard__medal svg{width:16px; height:16px}
.ap-bcard__text{display:flex; flex-direction:column; gap:2px; min-width:0}
.ap-bcard__name{font-size:var(--text-sm); font-weight:var(--weight-heavy); color:var(--ap-text)}
.ap-bcard__desc{font-size:var(--text-xs); color:var(--ap-text-mute); line-height:1.4}
/* ---- Focused home: tighter rail, and the features stack in it ---- */
.ap-dash--focused .ap-bento{align-items:start}
.ap-dash--focused .ap-bento__rail .ap-features{grid-template-columns:minmax(0,1fr)}
.ap-dash--focused .ap-feature{min-height:0}
@media (max-width:900px){
	.ap-idbar{flex-direction:column; align-items:flex-start; gap:12px}
	/* The next action and today's prayers lead on a phone; context follows. */
	.ap-dash--focused .ap-bento__main{display:flex; flex-direction:column}
	.ap-dash--focused .ap-continue{order:-2}
	.ap-dash--focused .ap-today{order:-1}
}
@media (max-width:520px){
	/* Five across gets tight; two rows keeps the targets comfortable. */
	.ap-prayers{grid-template-columns:repeat(3,minmax(0,1fr))}
}
/* ---- Verse card, sized for the dashboard rail ----
   Its display type is set for a full-width card; in a four-column rail the
   same size wraps to five lines and makes the column 140px taller than the
   actions beside it. Scoped to the dashboard so the standalone verse
   treatment elsewhere is untouched. */
.ap-dash--focused .ap-bento__rail .ap-verse__inner{padding:18px 20px}
.ap-dash--focused .ap-bento__rail .ap-verse__arabic{
	font-size:1.35rem; margin-bottom:10px;
}
.ap-dash--focused .ap-bento__rail .ap-verse__text{
	font-size:1.02rem; line-height:1.5; margin-bottom:8px;
}
.ap-dash--focused .ap-bento__rail .ap-verse__ref{font-size:var(--text-xs); margin-bottom:12px}
.ap-dash--focused .ap-bento__rail .ap-verse .ap-btn{min-height:40px; font-size:var(--text-xs); padding:0 14px}
/* ---- Focused home: reclaim the spacing the old, longer page needed ----
   The 32px main padding and 24px section gap were set for a page that always
   scrolled, where generous separation helped. On a single-screen dashboard
   they are 72px of the budget. Trimmed, not removed — the cards keep their own
   internal padding, so nothing gets cramped. */
.ap-dash--focused{gap:14px}
.ap-main:has(.ap-dash--focused){padding-top:20px; padding-bottom:20px}
.ap-dash--focused .ap-banner{margin-bottom:0}
.ap-dash--focused .ap-bento{gap:14px}
.ap-dash--focused .ap-features{gap:14px}
/* The portal footer is a one-line credit; on the command-center page it does
   not need 64px of its own. Scoped with :has() so only the dashboard is
   affected — longer pages keep the roomier footer. */
.atfal-portal-body .ap-main:has(.ap-dash--focused) ~ .ap-footer,
.atfal-portal-body .ap-work:has(.ap-dash--focused) .ap-footer{
	padding-block:10px; font-size:var(--text-xs);
}
/* ---- Home bottom row: two quote cards plus the leaderboard, equal height ---- */
.ap-homerow{display:grid; grid-template-columns:minmax(0,2fr) minmax(0,1fr); gap:14px; align-items:stretch}
/* .ap-features is itself a two-up grid, so it occupies the 2fr track and the
   leaderboard takes the 1fr — three equal-height columns overall. */
.ap-homerow .ap-features{margin:0; height:100%}
.ap-homerow .ap-feature{height:100%}
.atfal-portal-body .ap-mini{padding:14px 16px; display:flex; flex-direction:column; gap:8px}
.ap-mini__head{display:flex; align-items:center; gap:8px}
.ap-mini__icon{
	display:grid; place-items:center; width:24px; height:24px; border-radius:7px;
	background:#fef3c7; color:#b45309; flex:0 0 auto;
}
.ap-mini__icon svg{width:13px; height:13px}
.ap-mini__title{
	margin:0; font-size:var(--text-sm); font-weight:var(--weight-heavy);
	color:var(--ap-text); flex:1 1 auto;
}
.ap-mini__all{
	font-size:var(--text-xs); font-weight:var(--weight-heavy);
	color:var(--ap-primary-text); text-decoration:none; white-space:nowrap;
}
.ap-mini__all:hover{text-decoration:underline}
.ap-mini__list{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:3px}
.ap-mini__row{
	display:grid; grid-template-columns:20px minmax(0,1fr) auto;
	align-items:center; gap:9px;
	padding:5px 8px; border-radius:8px;
	font-size:var(--text-xs);
}
.ap-mini__rank{
	color:var(--ap-text-mute); font-weight:var(--weight-heavy);
	font-variant-numeric:tabular-nums; text-align:right;
}
.ap-mini__handle{
	color:var(--ap-text); font-weight:var(--weight-bold);
	overflow:hidden; text-overflow:clip;
}
.ap-mini__pts{color:var(--ap-text-mute); font-variant-numeric:tabular-nums}
.ap-mini__row.is-me{background:var(--ap-primary-tint)}
.ap-mini__row.is-me .ap-mini__rank,
.ap-mini__row.is-me .ap-mini__handle,
.ap-mini__row.is-me .ap-mini__pts{color:var(--ap-primary-text)}
@media (max-width:900px){
	.ap-homerow{grid-template-columns:minmax(0,1fr)}
}
/* .ap-features carries `grid-column: 1 / -1` from when it was a full-row item
   in the old bento. Inside the home bottom row that span claims the whole row
   and pushes the leaderboard onto a second one, doubling the row's height. */
.ap-homerow > .ap-features{
	grid-column:auto;
	/* Keep the 12-column track: the two cards inside span 6 each, so a 2-column
	   template overflows them onto separate rows. */
	grid-template-columns:repeat(12,minmax(0,1fr));
}
/* ---- Identity bar on small screens ----
   The Arabic is nowrap and the handle is long; side by side at 375px they run
   past the card edge. Both scale down together so the row still reads as one
   greeting rather than wrapping into a stack. */
@media (max-width:560px){
	.ap-idbar__who{width:100%; min-width:0}
	.ap-levelring{width:52px; height:52px; flex:0 0 auto}
}
@media (max-width:400px){
	.ap-idbar__ar{font-size:.85rem}
	.ap-levelring{width:46px; height:46px}
}


/* ===========================================================================
   PROFILE HEADER
   ---------------------------------------------------------------------------
   Two bands in one card. Top: identity and progress, a hairline, then earned
   achievements. Bottom: the summary strip and the two actions.

   Grouping is done with two dividers and alignment — no item has its own box,
   which is what keeps a component this dense from reading as clutter.
   =========================================================================== */
.ap-profile{
	background:#fff;
	border:1px solid var(--ap-line);
	border-radius:22px;
	box-shadow:0 1px 2px rgba(15,23,42,.04), 0 8px 26px rgba(15,23,42,.05);
	overflow:hidden;
}

/* ---- Top band ---- */
.ap-profile__top{
	display:grid;
	grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
	gap:34px;
	padding:26px 30px 24px;
}

.ap-profile__identity{display:flex; align-items:flex-start; gap:22px; min-width:0}

.ap-profile__avatar{
	position:relative; flex:0 0 auto;
	display:grid; place-items:center;
	width:92px; height:92px; border-radius:50%;
	background:linear-gradient(150deg,#1f9d63,#0d7a4a);
	/* White collar plus a soft cast, so the disc lifts off the card rather
	   than sitting flat on it. */
	box-shadow:0 0 0 6px #fff, 0 6px 18px rgba(6,95,70,.22);
	color:#fff;
}
.ap-profile__initial{font-size:2.6rem; font-weight:var(--weight-heavy); line-height:1}
/* Two small sparks, drawn not imported. Purely decorative and hidden from
   assistive tech via the parent's aria-hidden. */
.ap-profile__avatar::before,
.ap-profile__avatar::after{
	content:""; position:absolute; background:#34d399;
	clip-path:polygon(50% 0,61% 39%,100% 50%,61% 61%,50% 100%,39% 61%,0 50%,39% 39%);
}
.ap-profile__avatar::before{width:15px; height:15px; top:-4px; left:-14px; opacity:.85}
.ap-profile__avatar::after{width:9px; height:9px; top:14px; left:-24px; opacity:.55}

/* flex:1 so the block takes the width the column gives it. Without this it
   sized to its own content and the progress bar came out 243px in a 468px
   space — the bar should span the identity column, as in the reference. */
.ap-profile__names{flex:1 1 auto; min-width:0; padding-top:2px}
.ap-profile__salam{
	margin:0 0 2px;
	font-family:var(--font-arabic-display);
	font-size:1.15rem; font-weight:700; line-height:1.55;
	color:var(--ap-primary-deep);
	overflow:visible;
	/*
	 * dir="rtl" governs the ORDER of the characters; it also makes the block
	 * align right, which pushed the greeting to the far edge of a 400px column.
	 * text-align restores the box alignment without touching the ordering.
	 */
	text-align:left;
}
.ap-profile__name{
	margin:0 0 6px;
	display:flex; align-items:center; gap:10px; flex-wrap:wrap;
	font-size:clamp(1.5rem,1.15rem+1.1vw,2.1rem);
	font-weight:var(--weight-heavy); line-height:1.12; letter-spacing:-.02em;
	color:var(--ap-text);
}
.ap-profile__handle{
	min-width:0;
	/* break-word, not `anywhere`: `anywhere` shrinks the element's min-content
	   width and lets a flex parent split the handle mid-word in a box wide
	   enough to hold it. */
	overflow-wrap:break-word;
}
.ap-profile__verified{
	display:grid; place-items:center; flex:0 0 auto;
	width:24px; height:24px; border-radius:50%;
	background:var(--ap-primary-deep); color:#fff;
}
.ap-profile__verified svg{width:13px; height:13px}

.ap-profile__level{
	margin:0 0 12px;
	font-size:1.12rem; font-weight:var(--weight-heavy);
	color:var(--ap-primary-deep); line-height:1.2;
}
.ap-profile__meter{
	display:block; width:100%; max-width:430px; height:9px;
	border-radius:999px; background:#e8edf2; overflow:hidden;
}
.ap-profile__fill{
	display:block; height:100%; border-radius:999px;
	background:var(--ap-primary-deep);
	transition:width .5s cubic-bezier(.22,1,.36,1);
}
@media (prefers-reduced-motion:reduce){.ap-profile__fill{transition:none}}
.ap-profile__xp{
	margin:11px 0 0; font-size:1rem; line-height:1.3;
	font-variant-numeric:tabular-nums;
}
.ap-profile__xp strong{color:var(--ap-primary-deep); font-weight:var(--weight-heavy)}
.ap-profile__xpmuted{color:var(--ap-text-mute)}

/* ---- Achievements ---- */
.ap-profile__achievements{
	min-width:0;
	border-left:1px solid var(--ap-line);
	padding-left:34px;
}
.ap-profile__achead{display:flex; align-items:center; justify-content:space-between; gap:16px; margin-bottom:20px}
.ap-profile__actitle{
	margin:0; font-size:1.05rem; font-weight:var(--weight-heavy);
	color:var(--ap-text); letter-spacing:-.01em;
}
.ap-profile__acall{
	display:inline-flex; align-items:center; gap:6px;
	font-size:var(--text-sm); font-weight:var(--weight-bold);
	color:var(--ap-primary-deep); text-decoration:none; white-space:nowrap;
}
.ap-profile__acall:hover{text-decoration:underline}

.ap-profile__aclist{
	list-style:none; margin:0; padding:0;
	display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px;
}
.ap-ach{display:flex; flex-direction:column; align-items:center; text-align:center; gap:8px; min-width:0}
.ap-ach__hex{
	display:grid; place-items:center;
	width:58px; height:64px; color:#fff;
	/* A hexagon rather than a circle: it reads as a crest, and distinguishes an
	   achievement from the round stat icons in the strip below. */
	clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
	background:linear-gradient(155deg,var(--ap-h1),var(--ap-h2));
	filter:drop-shadow(0 4px 8px var(--ap-hs));
}
.ap-ach__hex svg{width:26px; height:26px}
.ap-ach--amber{--ap-h1:#fbbf24; --ap-h2:#d97706; --ap-hs:rgba(217,119,6,.30)}
.ap-ach--green{--ap-h1:#34d399; --ap-h2:#059669; --ap-hs:rgba(5,150,105,.28)}
.ap-ach--violet{--ap-h1:#a78bfa; --ap-h2:#6d28d9; --ap-hs:rgba(109,40,217,.28)}
.ap-ach--blue{--ap-h1:#60a5fa; --ap-h2:#2563eb; --ap-hs:rgba(37,99,235,.28)}
.ap-ach__name{
	font-size:var(--text-sm); font-weight:var(--weight-heavy);
	color:var(--ap-text); line-height:1.25; overflow-wrap:break-word;
}
.ap-ach__meta{font-size:var(--text-xs); color:var(--ap-text-mute); line-height:1.3}

/* ---- Bottom strip ---- */
.ap-profile__strip{
	display:flex; align-items:center; justify-content:space-between;
	flex-wrap:wrap; gap:18px 28px;
	padding:18px 30px 20px;
	border-top:1px solid var(--ap-line);
}
.ap-profile__stats{
	list-style:none; margin:0; padding:0;
	display:flex; align-items:center; flex-wrap:wrap; gap:12px 0;
}
.ap-pstat{display:flex; align-items:center; gap:12px; padding-right:26px}
.ap-pstat + .ap-pstat{border-left:1px solid var(--ap-line); padding-left:26px}
.ap-pstat__icon{
	display:grid; place-items:center; flex:0 0 auto;
	width:42px; height:42px; border-radius:50%;
	background:var(--ap-primary-tint); color:var(--ap-primary-deep);
}
.ap-pstat__icon svg{width:19px; height:19px}
.ap-pstat__text{display:flex; flex-direction:column; line-height:1.2}
.ap-pstat__label{font-size:var(--text-xs); color:var(--ap-text-mute)}
.ap-pstat__value{
	font-size:1.22rem; font-weight:var(--weight-heavy);
	color:var(--ap-text); font-variant-numeric:tabular-nums;
}

.ap-profile__cta{display:flex; align-items:center; gap:14px; flex-wrap:wrap}
.ap-profile__pill{
	display:inline-flex; align-items:center; gap:9px;
	min-height:46px; padding:0 22px;
	border:1.5px solid #fcd9a0; border-radius:999px;
	background:#fffaf0; color:#92400e;
	font-size:var(--text-base); font-weight:var(--weight-heavy);
	text-decoration:none; white-space:nowrap;
}
.ap-profile__pill svg{width:19px; height:19px; color:#d97706}
.ap-profile__pill:hover{background:#fff4e0; border-color:#f6c177}
.ap-profile__pill:focus-visible{outline:none; box-shadow:0 0 0 3px rgba(217,119,6,.35)}

.ap-profile__go{
	display:inline-flex; align-items:center; gap:9px;
	min-height:46px; padding:0 24px;
	border-radius:999px; border:0;
	background:var(--ap-primary-deep); color:#fff;
	font-size:var(--text-base); font-weight:var(--weight-heavy);
	text-decoration:none; white-space:nowrap;
	transition:background .15s ease, transform .12s ease;
}
.ap-profile__go:hover{background:#036649; transform:translateX(2px)}
.ap-profile__go:focus-visible{outline:none; box-shadow:var(--focus-ring)}
@media (prefers-reduced-motion:reduce){
	.ap-profile__go,.ap-profile__go:hover{transition:none; transform:none}
}

/* ---- Container declaration only. All responsive behaviour is defined in one
   authoritative mobile-first block at the end of this file — see
   "PROFILE + DASHBOARD RESPONSIVE ARCHITECTURE". Keeping it in one place is
   deliberate: the previous max-width rules were written at (0,1,0) and a later
   (0,2,0) base rule silently re-imposed the two-column layout at every width,
   which is what wrapped the member's name onto three lines. */
.ap-dash--focused{container-type:inline-size; container-name:dash}

/* ===========================================================================
   DASHBOARD: ONE CARD SYSTEM, ONE TYPE SCALE, ONE GRID
   ---------------------------------------------------------------------------
   Every card on Home now draws its radius, padding, border, shadow, heading
   size and icon size from the tokens below. Previously each module set its own,
   which is why the page read as widgets rather than a product.
   =========================================================================== */
.ap-dash--focused{
	--c-radius:16px;
	--c-pad:18px;
	--c-gap:16px;
	--c-border:1px solid #e6ebf0;
	--c-shadow:0 1px 2px rgba(15,23,42,.03), 0 6px 18px rgba(15,23,42,.04);

	/* Type scale. Deliberately compact: the old page used h2-sized headings
	   inside 300px cards, which is most of what made it feel oversized. */
	--t-title:.95rem;     /* card heading            */
	--t-sub:.78rem;       /* card sub-line           */
	--t-body:.86rem;      /* card body text          */
	--t-meta:.72rem;      /* captions, references    */
	--t-num:1.15rem;      /* stat figures            */

	display:flex; flex-direction:column; gap:var(--c-gap);
}

/* ---- Rows ---- */
.ap-row{display:grid; gap:var(--c-gap); align-items:stretch}
.ap-row--2{grid-template-columns:repeat(2,minmax(0,1fr))}
.ap-row--3{grid-template-columns:repeat(3,minmax(0,1fr))}

/* ---- The card primitive ---- */
.ap-dash--focused .ap-card{
	display:flex; flex-direction:column;
	background:#fff; border:var(--c-border); border-radius:var(--c-radius);
	box-shadow:var(--c-shadow); padding:var(--c-pad);
	min-width:0;
}
.ap-card__head{display:flex; align-items:center; gap:10px; margin-bottom:12px}
.ap-card__icon{
	display:grid; place-items:center; flex:0 0 auto;
	width:30px; height:30px; border-radius:9px;
}
.ap-card__icon svg{width:16px; height:16px}
.ap-card__icon--green{background:var(--ap-primary-tint); color:var(--ap-primary-deep)}
.ap-card__icon--violet{background:#ede9fe; color:#5b21b6}
.ap-card__icon--amber{background:#fef3c7; color:#b45309}
.ap-card__title{
	margin:0; font-size:var(--t-title); font-weight:var(--weight-heavy);
	color:var(--ap-text); line-height:1.25; letter-spacing:-.005em;
}
.ap-card__sub{margin:2px 0 0; font-size:var(--t-sub); color:var(--ap-text-mute); line-height:1.3}
.ap-card__more{
	margin-left:auto; flex:0 0 auto;
	font-size:var(--t-sub); font-weight:var(--weight-bold);
	color:var(--ap-primary-deep); text-decoration:none; white-space:nowrap;
}
.ap-card__more:hover{text-decoration:underline}

/* A quiet outlined action, used at the foot of a card. */
.ap-cardbtn{
	display:inline-flex; align-items:center; justify-content:center; gap:7px;
	margin-top:auto; min-height:38px; padding:0 16px;
	border:1px solid var(--ap-primary-line); border-radius:10px;
	background:#fff; color:var(--ap-primary-deep);
	font-size:var(--t-sub); font-weight:var(--weight-heavy); text-decoration:none;
}
.ap-cardbtn:hover{background:var(--ap-primary-tint)}
.ap-cardbtn:focus-visible{outline:none; box-shadow:var(--focus-ring)}

/* ---- Continue Learning: the one card with extra weight ---- */
.ap-dash--focused .ap-continue{
	display:flex; flex-direction:column; align-items:flex-start;
	gap:0; padding:22px; border:0; border-radius:var(--c-radius);
	background:linear-gradient(140deg,#0b5137,#0e6b47 62%,#128054);
	box-shadow:0 6px 20px rgba(11,81,55,.20);
	color:#fff;
}
.ap-dash--focused .ap-continue__eyebrow{
	font-size:var(--t-sub); letter-spacing:.02em; text-transform:none;
	font-weight:var(--weight-bold); color:#a7f3d0; margin:0 0 6px;
}
.ap-dash--focused .ap-continue__title{font-size:1.28rem; margin:0}
.ap-dash--focused .ap-continue__meta{font-size:var(--t-body); margin:6px 0 0; color:#cdeee0}
.ap-dash--focused .ap-continue__track{margin-top:14px; width:100%; max-width:none}
.ap-dash--focused .ap-continue__pct{font-size:var(--t-sub)}
.ap-dash--focused .ap-continue__left{font-size:var(--t-meta); margin-top:9px; color:#a7f3d0}
.ap-dash--focused .ap-continue__go{
	margin-top:auto; align-self:flex-end; min-height:42px;
	font-size:var(--t-body); padding:0 20px;
}

/* ---- Today's Prayers ---- */
.ap-dash--focused .ap-prayers{
	list-style:none; margin:0 0 14px; padding:0;
	display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:8px;
}
.ap-prayers form{margin:0}
.ap-dash--focused .ap-prayer{
	width:100%; min-height:88px;
	display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px;
	padding:10px 4px; border-radius:12px; cursor:pointer;
	background:#fff; border:1px solid #e6ebf0; font:inherit; color:var(--ap-text-soft);
	transition:border-color .15s ease, background .15s ease;
}
.ap-prayer__icon{display:grid; place-items:center; width:26px; height:26px}
.ap-prayer__icon svg{width:24px; height:24px; stroke-width:1.6}
/* Time-of-day colour: dawn through night, so the set is readable as a day. */
.ap-prayer--fajr    .ap-prayer__icon{color:#6366f1}
.ap-prayer--zuhr    .ap-prayer__icon{color:#f59e0b}
.ap-prayer--asr     .ap-prayer__icon{color:#ea9010}
.ap-prayer--maghrib .ap-prayer__icon{color:#ef6c3f}
.ap-prayer--isha    .ap-prayer__icon{color:#4f46e5}
.ap-prayer__name{font-size:var(--t-sub); font-weight:var(--weight-bold); line-height:1.2}
.ap-prayer__dot{
	display:grid; place-items:center; width:18px; height:18px; border-radius:50%;
	border:1.5px solid #cbd5e1; background:#fff; color:transparent;
}
.ap-prayer__dot svg{width:10px; height:10px}
.ap-prayer:hover{border-color:var(--ap-primary); background:#fbfffd}
.ap-prayer:focus-visible{outline:none; box-shadow:var(--focus-ring)}
.ap-dash--focused .ap-prayer.is-done{background:var(--ap-primary-tint); border-color:var(--ap-primary-line)}
.ap-prayer.is-done .ap-prayer__dot{background:var(--ap-primary-deep); border-color:var(--ap-primary-deep); color:#fff}
@media (prefers-reduced-motion:reduce){.ap-prayer{transition:none}}

/* Week strip: label above the dot, matching the prayers above it. */
.ap-dash--focused .ap-wk{
	list-style:none; margin:auto 0 0; padding:12px 0 0;
	border-top:1px solid #eef2f6;
	display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:6px;
}
.ap-dash--focused .ap-wk__day{display:flex; flex-direction:column; align-items:center; gap:6px; padding:6px 0; border-radius:9px}
.ap-dash--focused .ap-wk__lbl{font-size:var(--t-meta); font-weight:var(--weight-bold); color:var(--ap-text-mute)}
.ap-dash--focused .ap-wk__mark{
	display:grid; place-items:center; width:22px; height:22px; border-radius:50%;
	border:1.5px solid #cbd5e1; background:#fff; color:transparent;
	font-size:.65rem; font-weight:var(--weight-heavy);
}
.ap-dash--focused .ap-wk__mark svg{width:11px; height:11px}
.ap-dash--focused .ap-wk__day.is-done .ap-wk__mark{background:var(--ap-primary-deep); border-color:var(--ap-primary-deep); color:#fff}
.ap-dash--focused .ap-wk__day.is-part .ap-wk__mark{background:#ffedd5; border-color:#fdba74; color:#c2410c}
.ap-dash--focused .ap-wk__day.is-today{background:var(--ap-primary-tint)}
.ap-dash--focused .ap-wk__day.is-today .ap-wk__mark{border-color:var(--ap-primary)}

/* ---- Verse, light ---- */
.ap-dash--focused .ap-verse{background:#fff; color:var(--ap-text); overflow:visible}
.ap-verse__body{flex:1 1 auto; text-align:center; padding:4px 0 14px}
.ap-dash--focused .ap-verse__arabic{
	font-family:var(--font-arabic-display);
	font-size:1.4rem; line-height:1.9; color:var(--ap-primary-deep);
	margin:0 0 10px; text-align:center;
}
.ap-dash--focused .ap-verse__text{
	font-size:var(--t-body); line-height:1.5; color:var(--ap-text); margin:0 0 6px;
	font-family:var(--font-body); font-style:normal;
}
.ap-dash--focused .ap-verse__ref{font-size:var(--t-meta); color:var(--ap-text-mute); margin:0}

/* ---- Events ---- */
.ap-dash--focused .ap-events{list-style:none; margin:0; padding:0; display:flex; flex-direction:column}
.ap-dash--focused .ap-event{display:flex; gap:11px; padding:10px 0; align-items:flex-start}
.ap-dash--focused .ap-event + .ap-event{border-top:1px solid #eef2f6}
.ap-dash--focused .ap-event__date{
	flex:0 0 auto; display:flex; flex-direction:column; align-items:center; justify-content:center;
	width:44px; padding:6px 0; border-radius:10px;
	background:#f3f1fd; color:#5b21b6;
}
.ap-dash--focused .ap-event__mon{font-size:.6rem; font-weight:var(--weight-heavy); letter-spacing:.08em; color:#6d28d9}
.ap-dash--focused .ap-event__day{font-size:1.05rem; font-weight:var(--weight-heavy); line-height:1.1; color:#4c1d95}
.ap-dash--focused .ap-event__title{font-size:var(--t-body); font-weight:var(--weight-bold); line-height:1.3}
.ap-dash--focused .ap-event__meta{font-size:var(--t-meta); color:var(--ap-text-mute); line-height:1.35}

/* ---- Mini leaderboard ---- */
.ap-dash--focused .ap-mini__list{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px}
.ap-dash--focused .ap-mini__row{
	display:grid; grid-template-columns:18px minmax(0,1fr) auto;
	align-items:center; gap:10px; padding:8px 10px; border-radius:9px;
	font-size:var(--t-body);
}
.ap-dash--focused .ap-mini__rank{color:var(--ap-text-mute); font-weight:var(--weight-heavy); text-align:right}
.ap-dash--focused .ap-mini__handle{font-weight:var(--weight-bold); white-space:nowrap; overflow:hidden}
.ap-dash--focused .ap-mini__pts{color:var(--ap-text-mute); font-variant-numeric:tabular-nums}

/* ---- Feature cards, matched to the row above ---- */
.ap-dash--focused .ap-features{
	display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--c-gap);
}
.ap-dash--focused .ap-feature{
	grid-column:auto; min-height:0;
	background:#fff; border:var(--c-border); border-left:3px solid var(--ap-accent,#b45309);
	border-radius:var(--c-radius); box-shadow:var(--c-shadow); padding:var(--c-pad);
}
.ap-dash--focused .ap-feature__eyebrow{font-size:var(--t-sub); letter-spacing:.02em}
.ap-dash--focused .ap-feature__body{font-size:var(--t-body); line-height:1.5; display:block; -webkit-line-clamp:none; overflow:visible}
.ap-dash--focused .ap-feature__cite,
.ap-dash--focused .ap-feature__source{font-size:var(--t-meta)}

/* ---- Sign-off ---- */
.ap-dash__sign{
	display:flex; align-items:center; justify-content:center; gap:8px;
	margin:6px 0 0; font-size:var(--t-sub); color:var(--ap-text-mute);
}
.ap-dash__sign svg{width:15px; height:15px; color:var(--ap-primary-deep)}

/* ---- Responsive rows ---- */
@container dash (max-width:900px){
	.ap-row--3{grid-template-columns:repeat(2,minmax(0,1fr))}
	/* The leaderboard takes the full width of the second row rather than
	   leaving a half-empty cell. */
	.ap-row--3 > :last-child{grid-column:1 / -1}
}
@container dash (max-width:640px){
	.ap-row--2,.ap-row--3,.ap-dash--focused .ap-features{grid-template-columns:minmax(0,1fr)}
	.ap-row--3 > :last-child{grid-column:auto}
	.ap-dash--focused .ap-prayers{grid-template-columns:repeat(3,minmax(0,1fr))}
	.ap-dash--focused .ap-continue__go{align-self:stretch; justify-content:center}
}

/* ---- Profile card, tightened to the dashboard's scale ---- */
.ap-dash--focused .ap-profile{border-radius:var(--c-radius); border:var(--c-border); box-shadow:var(--c-shadow)}
.ap-dash--focused .ap-profile__top{padding:20px 22px 18px; gap:26px}
.ap-dash--focused .ap-profile__avatar{width:74px; height:74px; box-shadow:0 0 0 5px #fff, 0 5px 14px rgba(6,95,70,.20)}
.ap-dash--focused .ap-profile__initial{font-size:2rem}
.ap-dash--focused .ap-profile__salam{font-size:.95rem; margin-bottom:1px}
.ap-dash--focused .ap-profile__name{font-size:1.45rem; margin-bottom:3px; gap:8px}
.ap-dash--focused .ap-profile__verified{width:19px; height:19px}
.ap-dash--focused .ap-profile__verified svg{width:10px; height:10px}
.ap-dash--focused .ap-profile__level{font-size:var(--t-body); margin-bottom:9px}
.ap-dash--focused .ap-profile__meter{height:7px; max-width:340px}
.ap-dash--focused .ap-profile__xp{font-size:var(--t-sub); margin-top:8px}
.ap-dash--focused .ap-profile__actitle{font-size:var(--t-title)}
.ap-dash--focused .ap-profile__acall{font-size:var(--t-sub)}
.ap-dash--focused .ap-profile__achead{margin-bottom:14px}
.ap-dash--focused .ap-profile__achievements{padding-left:26px}
.ap-dash--focused .ap-ach__hex{width:46px; height:51px}
.ap-dash--focused .ap-ach__hex svg{width:21px; height:21px}
.ap-dash--focused .ap-ach__name{font-size:var(--t-sub)}
.ap-dash--focused .ap-ach__meta{font-size:var(--t-meta)}
.ap-dash--focused .ap-profile__strip{padding:14px 22px 16px; gap:14px 22px}
.ap-dash--focused .ap-pstat{gap:10px; padding-right:20px}
.ap-dash--focused .ap-pstat + .ap-pstat{padding-left:20px}
.ap-dash--focused .ap-pstat__icon{width:34px; height:34px}
.ap-dash--focused .ap-pstat__icon svg{width:16px; height:16px}
.ap-dash--focused .ap-pstat__label{font-size:var(--t-meta)}
.ap-dash--focused .ap-pstat__value{font-size:var(--t-num)}
.ap-dash--focused .ap-profile__pill{min-height:40px; padding:0 18px; font-size:var(--t-sub)}
.ap-dash--focused .ap-profile__pill svg{width:16px; height:16px}

/* ---- My Journey: contrast fix ----
   It was white on a mid-green fill, which measured poorly and sat right beside
   an amber pill of similar weight. Outlined instead: deep green on white is
   8.6:1, it reads clearly as a secondary action, and it stops competing with
   the primary Continue button elsewhere on the page. */
.ap-dash--focused .ap-profile__go{
	min-height:40px; padding:0 18px; font-size:var(--t-sub);
	background:#fff;
	color:var(--ap-primary-text);
	border:1.5px solid var(--ap-primary-line);
}
.ap-dash--focused .ap-profile__go:hover{
	background:var(--ap-primary-tint);
	border-color:var(--ap-primary);
	color:#036649;
}
.ap-dash--focused .ap-profile__go:active{background:#d7f5e7}
.ap-dash--focused .ap-profile__go:focus-visible{outline:none; box-shadow:var(--focus-ring); border-color:var(--ap-primary)}

@container dash (max-width:900px){
	.ap-dash--focused .ap-profile__top{padding:18px 18px 16px}
	.ap-dash--focused .ap-profile__strip{padding:14px 18px 16px}
}

/* ---- Row children own no span of their own ----
   .ap-verse and .ap-mod--events still carried `grid-column: span 2` from the
   old bento, which in a two-track row made each of them full width and stacked
   the whole section. The row decides the tracks; its children just fill one. */
.ap-row > *{grid-column:auto}
@container dash (max-width:900px){
	.ap-row--3 > :last-child{grid-column:1 / -1}
}
@container dash (max-width:640px){
	.ap-row--3 > :last-child{grid-column:auto}
}

/* ---- Green text on white uses the 700, not the 600 ----
   #059669 measures 3.77:1 on white — under AA. #047857 is 5.2:1 and visually
   the same decision. The 600 stays on fills and bars, where no text sits on it. */
.ap-dash--focused .ap-profile__salam,
.ap-dash--focused .ap-profile__level,
.ap-dash--focused .ap-profile__xp strong,
.ap-dash--focused .ap-verse__arabic,
.ap-dash--focused .ap-card__more,
.ap-dash--focused .ap-profile__acall,
.ap-dash--focused .ap-cardbtn{color:var(--ap-primary-text)}

/* ===========================================================================
   REFINEMENT PASS
   =========================================================================== */

/* ---- Profile: compact, and balanced across the two halves ----
   The achievements half was a 1fr column holding one crest, so most of it was
   empty and the whole card ran ~100px taller than it needed to. The crests now
   lay out left-aligned at their natural width, and the two halves are sized to
   their content rather than split down the middle. */
.ap-dash--focused .ap-profile__top{
	grid-template-columns:minmax(0,1fr) minmax(0,.9fr);
	padding:16px 20px 14px; gap:22px;
	align-items:start;
}
.ap-dash--focused .ap-profile__avatar{width:64px; height:64px; box-shadow:0 0 0 4px #fff, 0 4px 12px rgba(6,95,70,.18)}
.ap-dash--focused .ap-profile__initial{font-size:1.7rem}
.ap-dash--focused .ap-profile__identity{gap:16px}
.ap-dash--focused .ap-profile__salam{font-size:.88rem; line-height:1.5}
.ap-dash--focused .ap-profile__name{font-size:1.3rem; margin-bottom:2px}
.ap-dash--focused .ap-profile__level{font-size:var(--t-sub); margin-bottom:7px}
.ap-dash--focused .ap-profile__meter{height:6px; max-width:300px}
.ap-dash--focused .ap-profile__xp{font-size:var(--t-meta); margin-top:6px}

.ap-dash--focused .ap-profile__achead{margin-bottom:10px}
.ap-dash--focused .ap-profile__achievements{padding-left:22px}
/* Crests sit at their own width instead of stretching across empty tracks. */
.ap-dash--focused .ap-profile__aclist{
	display:flex; flex-wrap:wrap; gap:14px 18px; justify-content:flex-start;
}
.ap-dash--focused .ap-ach{flex:0 0 auto; width:82px; gap:6px}
.ap-dash--focused .ap-ach__hex{width:40px; height:44px}
.ap-dash--focused .ap-ach__hex svg{width:18px; height:18px}
.ap-dash--focused .ap-ach__name{font-size:var(--t-meta); line-height:1.25}
/* The description was the tallest thing in an otherwise empty half. It is
   available on My Journey, where there is room for it. */
.ap-dash--focused .ap-ach__meta{display:none}

.ap-dash--focused .ap-profile__strip{padding:12px 20px 13px}
.ap-dash--focused .ap-pstat__icon{width:30px; height:30px}
.ap-dash--focused .ap-pstat__icon svg{width:15px; height:15px}
.ap-dash--focused .ap-pstat__value{font-size:1.05rem}
.ap-dash--focused .ap-pstat{padding-right:18px}
.ap-dash--focused .ap-pstat + .ap-pstat{padding-left:18px}

/* ---- My Journey: a text action, not a third pill ----
   With the streak pill gone this no longer needs a border to separate it from
   a neighbour, so it drops to a link with an arrow — the same treatment as
   "View all" and "All" elsewhere on the page, which is what makes the set of
   navigation actions read as one system. */
.ap-dash--focused .ap-profile__go{
	background:none; border:0; padding:0 2px; min-height:36px;
	color:var(--ap-primary-text);
	font-size:var(--t-sub); font-weight:var(--weight-heavy);
	gap:7px; border-radius:6px;
}
.ap-dash--focused .ap-profile__go span{transition:transform .15s ease}
.ap-dash--focused .ap-profile__go:hover{background:none; color:#036649; text-decoration:underline; text-underline-offset:3px}
.ap-dash--focused .ap-profile__go:hover span{transform:translateX(3px)}
.ap-dash--focused .ap-profile__go:focus-visible{box-shadow:var(--focus-ring)}
@media (prefers-reduced-motion:reduce){
	.ap-dash--focused .ap-profile__go span{transition:none}
	.ap-dash--focused .ap-profile__go:hover span{transform:none}
}

/* ---- Feature cards: folded body, icon accent ---- */
.ap-dash--focused .ap-feature{padding:14px 16px}
.ap-dash--focused .ap-feature__label{
	display:flex; align-items:center; gap:8px; margin:0 0 8px;
	font-size:var(--t-meta); font-weight:var(--weight-heavy);
	letter-spacing:.07em; text-transform:uppercase; color:var(--ap-accent,#b45309);
}
.ap-feature__mark{
	display:grid; place-items:center; flex:0 0 auto;
	width:24px; height:24px; border-radius:7px;
	background:color-mix(in srgb, var(--ap-accent,#b45309) 12%, #fff);
}
.ap-feature__mark svg{width:13px; height:13px}

.ap-feature__fold{margin:0}
.ap-feature__summary{
	list-style:none; cursor:pointer; display:block;
	border-radius:8px;
}
.ap-feature__summary::-webkit-details-marker{display:none}
.ap-feature__summary:focus-visible{outline:none; box-shadow:var(--focus-ring)}
.ap-dash--focused .ap-feature__body{
	display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
	overflow:hidden;
	font-size:var(--t-body); line-height:1.5; color:var(--ap-text);
}
/* Opening lifts the clamp — the same element, now unfolded. */
.ap-feature__fold[open] .ap-feature__body{-webkit-line-clamp:none; overflow:visible}
.ap-feature__toggle{
	display:inline-block; margin-top:6px;
	font-size:var(--t-meta); font-weight:var(--weight-heavy);
	color:var(--ap-primary-text);
}
.ap-feature__less{display:none}
.ap-feature__fold[open] .ap-feature__more{display:none}
.ap-feature__fold[open] .ap-feature__less{display:inline}
.ap-feature__summary:hover .ap-feature__toggle{text-decoration:underline}
.ap-dash--focused .ap-feature__src{margin:8px 0 0; font-size:var(--t-meta)}

/* The feature label already carried a masked-SVG icon via ::before. The card
   now renders a real inline icon in a tinted box, so the legacy one would show
   twice — suppressed here rather than deleted, since the banner treatment
   elsewhere still uses it. */
.ap-dash--focused .ap-feature__label::before{display:none}

/* ---- Final type audit: the last values not drawn from the scale ----
   Two steps added at the top so the only large sizes on the page are named
   ones, and the banner joins the body step instead of sitting 1px off it. */
.ap-dash--focused{
	--t-lead:1.3rem;   /* the member's name — the page's largest text */
	--t-head:1.2rem;   /* the one primary card heading (Continue)     */
}
.ap-dash--focused .ap-profile__name{font-size:var(--t-lead)}
.ap-dash--focused .ap-continue__title{font-size:var(--t-head)}
.ap-dash--focused .ap-banner__text{font-size:var(--t-body)}
.ap-dash--focused .ap-profile__salam{font-size:var(--t-body)}
/* Event day/month share the stat and meta steps rather than their own pair. */
.ap-dash--focused .ap-event__day{font-size:var(--t-num)}
.ap-dash--focused .ap-event__mon{font-size:.6rem}

/* ---- Feature fold: a height clamp, not a line clamp ----
   -webkit-line-clamp only takes effect on display:-webkit-box, and inside a
   <summary> the span resolved to flow-root, so the clamp was silently inert
   and the full passage showed with a "Read more" beneath it that did nothing.
   A max-height clamp works whatever the display type resolves to. */
.ap-dash--focused .ap-feature__fold .ap-feature__body{
	display:block; overflow:hidden;
	/* two lines at this line-height */
	max-height:3em;
	-webkit-line-clamp:none;
}
.ap-dash--focused .ap-feature__fold[open] .ap-feature__body{max-height:none; overflow:visible}
.ap-dash--focused .ap-feature__body--full{display:block; overflow:visible; max-height:none}

/* ---- Feature fold ----
   The clamp only exists once the script has confirmed there is something to
   clamp; the toggle is hidden until then. See portal-challenge.js. */
.ap-feature__toggle{
	display:none; margin-top:6px; padding:2px 0;
	background:none; border:0; cursor:pointer; font:inherit;
	font-size:var(--t-meta); font-weight:var(--weight-heavy);
	color:var(--ap-primary-text);
}
.ap-feature__fold.is-foldable .ap-feature__toggle{display:inline-block}
.ap-feature__toggle:hover{text-decoration:underline}
.ap-feature__toggle:focus-visible{outline:none; box-shadow:var(--focus-ring); border-radius:5px}
.ap-dash--focused .ap-feature__fold.is-foldable .ap-feature__body{
	display:block; overflow:hidden; max-height:3em; -webkit-line-clamp:none;
}
.ap-dash--focused .ap-feature__fold.is-foldable.is-open .ap-feature__body{max-height:none; overflow:visible}
.ap-feature__less{display:none}
.ap-feature__fold.is-open .ap-feature__more{display:none}
.ap-feature__fold.is-open .ap-feature__less{display:inline}

/* The fold toggle's tap area, without changing how it looks.
   As a bare inline label it measured 18px — well under the 44px minimum this
   project holds itself to. Padding grows the target on touch devices only, so
   the desktop card keeps its tight rhythm. */
.ap-feature__toggle{min-height:26px}
@media (pointer:coarse){
	.ap-feature__toggle{min-height:44px; display:inline-flex; align-items:center}
	.ap-feature__fold.is-foldable .ap-feature__toggle{display:inline-flex}
}

/* ===========================================================================
   PROFILE + DASHBOARD RESPONSIVE ARCHITECTURE
   ---------------------------------------------------------------------------
   This block is the single owner of how the dashboard reorganises. It is last
   in the file and every selector is qualified with .ap-dash--focused, so no
   earlier rule can outrank it and no later base rule can silently undo it.

   It is written MOBILE-FIRST on purpose. The previous version defined the
   two-column layout as the base and stripped it back with max-width queries;
   a later, more specific base rule then re-imposed two columns at every width
   and the queries became dead code. Nothing announced this — the name simply
   started wrapping onto three lines.

   Written this way, the failure mode inverts: if an enhancement rule is ever
   lost, the layout falls back to stacked and readable rather than to squeezed
   and broken.

   Breakpoints are chosen from where THIS content stops fitting, not from
   device names, and they measure the container because the card sits beside a
   256px sidebar.
   =========================================================================== */

/* ---------- BASE: everything stacked, nothing narrower than it needs ------- */
.ap-dash--focused .ap-profile__top{
	display:grid;
	grid-template-columns:minmax(0,1fr);
	gap:16px;
	padding:16px 18px 14px;
	align-items:start;
}
.ap-dash--focused .ap-profile__identity{
	display:flex; align-items:flex-start; gap:14px; min-width:0;
}
.ap-dash--focused .ap-profile__names{flex:1 1 auto; min-width:0}
/* The name wraps at word boundaries only, and never breaks mid-word. */
.ap-dash--focused .ap-profile__name{
	display:flex; align-items:center; gap:8px; flex-wrap:wrap;
	font-size:var(--t-lead); line-height:1.2; margin:0 0 2px;
}
.ap-dash--focused .ap-profile__handle{min-width:0; overflow-wrap:normal; word-break:normal}
.ap-dash--focused .ap-profile__meter{max-width:none}

/* Achievements sit below identity, separated by a rule rather than squeezed
   into a column beside it. */
.ap-dash--focused .ap-profile__achievements{
	min-width:0;
	border-left:0; padding-left:0;
	border-top:1px solid var(--ap-line); padding-top:14px;
}
.ap-dash--focused .ap-profile__achead{
	display:flex; align-items:center; justify-content:space-between;
	gap:12px; margin-bottom:10px; flex-wrap:wrap;
}
/* "Top Achievements" and "View all" are short labels; keeping them unbroken is
   what stops the heading fragmenting and the action clipping. */
.ap-dash--focused .ap-profile__actitle{white-space:nowrap}
.ap-dash--focused .ap-profile__acall{white-space:nowrap; flex:0 0 auto}
.ap-dash--focused .ap-profile__aclist{display:flex; flex-wrap:wrap; gap:14px 18px}

/* Stats are a grid, so the three items stay a set instead of one floating
   under the other two. */
.ap-dash--focused .ap-profile__strip{
	display:flex; flex-direction:column; align-items:stretch; gap:14px;
	padding:14px 18px; border-top:1px solid var(--ap-line);
}
.ap-dash--focused .ap-profile__stats{
	display:grid;
	/*
	 * One column at the narrowest sizes, not two.
	 *
	 * Three items in a two-column grid leaves the third stranded on its own
	 * row under the other two — which reads as a layout accident rather than a
	 * set. A single column keeps all three aligned on the same left edge and
	 * is only ~40px taller.
	 */
	grid-template-columns:minmax(0,1fr);
	gap:10px; margin:0; padding:0; list-style:none;
}
.ap-dash--focused .ap-pstat{
	display:flex; align-items:center; gap:10px; min-width:0;
	padding:0; border-left:0;
}
.ap-dash--focused .ap-pstat + .ap-pstat{padding-left:0; border-left:0}
.ap-dash--focused .ap-pstat__text{min-width:0}
.ap-dash--focused .ap-pstat__label{white-space:nowrap}
.ap-dash--focused .ap-profile__cta{display:flex; justify-content:flex-start}

/* ---------- 520px+: stats fit three across ---------- */
@container dash (min-width:520px){
	.ap-dash--focused .ap-profile__stats{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* ---------- 640px+: the stats row and the action share a line ---------- */
@container dash (min-width:640px){
	.ap-dash--focused .ap-profile__strip{
		flex-direction:row; align-items:center; justify-content:space-between;
		gap:20px; padding:12px 20px 13px;
	}
	.ap-dash--focused .ap-profile__stats{flex:1 1 auto}
	.ap-dash--focused .ap-profile__cta{flex:0 0 auto}
	/* Dividers only once the three are genuinely side by side. */
	.ap-dash--focused .ap-pstat + .ap-pstat{
		border-left:1px solid var(--ap-line); padding-left:18px;
	}
}

/* ---------- 780px+: identity and achievements side by side ----------
   Measured, not guessed: below this the achievements column drops under
   ~300px, at which point "Top Achievements" fragments and "View all" is
   pushed past the card edge. */
@container dash (min-width:780px){
	.ap-dash--focused .ap-profile__top{
		grid-template-columns:minmax(340px,1fr) minmax(300px,.85fr);
		gap:24px; padding:18px 22px 16px;
	}
	.ap-dash--focused .ap-profile__achievements{
		border-left:1px solid var(--ap-line); padding-left:24px;
		border-top:0; padding-top:0;
	}
}

/* ---------- Rows ---------- */
.ap-dash--focused .ap-row--2,
.ap-dash--focused .ap-row--3,
.ap-dash--focused .ap-features{grid-template-columns:minmax(0,1fr)}
@container dash (min-width:640px){
	/* Quote/fact and the three-up row pair earlier: their content is text and
	   reflows cleanly at ~310px. */
	.ap-dash--focused .ap-features{grid-template-columns:repeat(2,minmax(0,1fr))}
	.ap-dash--focused .ap-row--3{grid-template-columns:repeat(2,minmax(0,1fr))}
	.ap-dash--focused .ap-row--3 > :last-child{grid-column:1 / -1}
}
@container dash (min-width:740px){
	/*
	 * Continue Learning and Today's Prayers pair later than the other rows.
	 * Measured: Continue needs ~340px before its course title stops breaking
	 * into three lines, and the five prayer tiles need ~300px. Below 740 the
	 * pair would each get ~325px, so they stack instead — which is the point of
	 * reorganising rather than shrinking.
	 */
	.ap-dash--focused .ap-row--2{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@container dash (min-width:900px){
	.ap-dash--focused .ap-row--3{grid-template-columns:repeat(3,minmax(0,1fr))}
	.ap-dash--focused .ap-row--3 > :last-child{grid-column:auto}
}

/* ---------- Prayers ---------- */
.ap-dash--focused .ap-prayers{grid-template-columns:repeat(3,minmax(0,1fr))}
@container dash (min-width:460px){
	.ap-dash--focused .ap-prayers{grid-template-columns:repeat(5,minmax(0,1fr))}
}

/* ---------- Continue Learning ----------
   No fixed height and no stretched button. The card is as tall as its content;
   the action sits inline with the progress once there is room for it. */
.ap-dash--focused .ap-continue{gap:0; padding:20px}
.ap-dash--focused .ap-continue__track{
	display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-top:12px;
}
.ap-dash--focused .ap-continue__meter{flex:1 1 140px; max-width:260px}
.ap-dash--focused .ap-continue__go{
	margin-top:14px; align-self:stretch; justify-content:center;
	min-height:44px; width:100%;
}
@container dash (min-width:520px){
	/* Beside the progress rather than below it — which is what made this card
	   tall enough to set the height of the whole row. */
	.ap-dash--focused .ap-continue__go{
		margin-top:0; align-self:flex-end; width:auto; justify-content:center;
	}
	.ap-dash--focused .ap-continue__body{
		display:flex; flex-direction:column; justify-content:flex-start; flex:1 1 auto;
	}
	.ap-dash--focused .ap-continue{
		display:grid; grid-template-columns:minmax(0,1fr) auto;
		/*
		 * stretch, not end. With `align-items:end` the whole card's content
		 * bottom-aligned once the card stretched to match its neighbour, which
		 * moved the empty band to the TOP of the card — the same void, mirrored.
		 * The body now fills the height and starts at the top; only the button
		 * pins itself to the bottom.
		 */
		align-items:stretch; gap:16px 20px;
	}
	.ap-dash--focused .ap-continue__go{align-self:end}
}

/* ---------- Banner ----------
   Icon fixed, message elastic, close pinned. It grew three lines tall because
   the message had no room to use. */
.ap-dash--focused .ap-banner{
	display:grid; grid-template-columns:auto minmax(0,1fr) auto;
	align-items:center; gap:12px; padding:12px 14px;
}
.ap-dash--focused .ap-banner__icon{width:28px; height:28px; border-radius:8px}
.ap-dash--focused .ap-banner__icon svg{width:15px; height:15px}
.ap-dash--focused .ap-banner__text{margin:0; min-width:0; line-height:1.45}
.ap-dash--focused .ap-banner__close{
	width:36px; height:36px; margin:0; align-self:start;
}

/* Browsers without container queries: viewport breakpoints offset for the
   256px sidebar. The same order, so the fallback degrades the same way. */
@supports not (container-type:inline-size){
	.ap-dash--focused .ap-profile__stats{grid-template-columns:repeat(3,minmax(0,1fr))}
	@media (min-width:900px){
		.ap-dash--focused .ap-profile__strip{flex-direction:row; align-items:center; justify-content:space-between}
		.ap-dash--focused .ap-row--2,.ap-dash--focused .ap-features{grid-template-columns:repeat(2,minmax(0,1fr))}
		.ap-dash--focused .ap-prayers{grid-template-columns:repeat(5,minmax(0,1fr))}
	}
	@media (min-width:1160px){
		.ap-dash--focused .ap-profile__top{grid-template-columns:minmax(340px,1fr) minmax(300px,.85fr)}
		.ap-dash--focused .ap-profile__achievements{border-left:1px solid var(--ap-line); padding-left:24px; border-top:0; padding-top:0}
		.ap-dash--focused .ap-row--3{grid-template-columns:repeat(3,minmax(0,1fr))}
	}
}

/* ---- Today's Prayers: no dead space at the foot of the card ----
   The card stretches to match Continue Learning beside it (that is what keeps
   the row's edges aligned), but its content is shorter, so the slack collected
   as an empty band above the card's bottom edge.

   The prayers grid now absorbs it instead: the tiles grow into whatever height
   the row gives them. The space becomes a larger tap target rather than a gap,
   and the card looks deliberate at every row height instead of only when the
   two cards happen to match. */
.ap-dash--focused .ap-prayers{
	flex:1 1 auto;
	align-content:stretch;
	margin-bottom:12px;
}
.ap-dash--focused .ap-prayers > li{display:flex}
.ap-dash--focused .ap-prayers > li > form{display:flex; width:100%}
.ap-dash--focused .ap-prayer{
	height:100%;
	/* A floor and a ceiling. Without the cap, a much taller neighbour pushed
	   the tiles to 194px — the void moved rather than went away. */
	min-height:88px;
	max-height:118px;
}
/* Pinned to the foot of the card. Between the cap above and this, slack is
   shared between the tiles and the space around them instead of pooling into
   a single empty band. */
.ap-dash--focused .ap-today .ap-wk{flex:0 0 auto; margin-top:auto; padding-top:12px}

/* ===========================================================================
   PRIMARY ROW: CONTINUE LEARNING + TODAY'S PRAYERS
   =========================================================================== */

/* ---- The .ap-card collision ----
   `.ap-card` predates the dashboard: it is the login/registration card, and it
   is `width:100%; max-width:420px` so that form sits centred and narrow. The
   dashboard primitive reused the name and silently inherited the cap, so
   Today's Prayers rendered 420px inside a 575px grid track and left a 155px
   dead strip beside it.

   Neutralised in the dashboard scope rather than renamed, so the auth screens
   keep the card they were built with. (Fourth name collision in this
   stylesheet — .ap-work, .ap-step, .ap-card. Grep before reusing a base
   class.) */
.ap-dash--focused .ap-card{width:auto; max-width:none}

/* ---- Continue Learning: one column, no floating CTA ----
   The card was a two-column grid with the action pinned bottom-right via
   align-self:end. Because the row equalises heights, the button was pushed
   58px clear of the text it belongs to, leaving an unexplained hole in the
   middle of the card.

   It is now a single column in the order the eye reads it — label, title,
   lesson, progress, lessons-left, action — with the rhythm carried by gap
   rather than by anything being pushed anywhere. */
.ap-dash--focused .ap-continue{
	display:flex; flex-direction:column; align-items:flex-start;
	gap:0; padding:20px;
}
.ap-dash--focused .ap-continue__body{
	display:flex; flex-direction:column; align-items:flex-start;
	width:100%; flex:0 0 auto;
}
.ap-dash--focused .ap-continue__eyebrow{margin:0 0 6px}
.ap-dash--focused .ap-continue__title{margin:0}
.ap-dash--focused .ap-continue__meta{margin:6px 0 0}
.ap-dash--focused .ap-continue__track{margin-top:16px; width:100%}
.ap-dash--focused .ap-continue__left{margin:10px 0 0}
.ap-dash--focused .ap-continue__go{
	/* Sits directly under the text it acts on, at its own width. */
	margin-top:18px; align-self:flex-start; width:auto;
	min-height:44px; padding:0 22px;
}

/* ---- Both primary cards share a floor, not a forced height ----
   A modest min-height keeps the pair looking like a matched set when their
   content is close, without either card inventing space to reach it. Anything
   beyond this comes from real content. */
.ap-dash--focused .ap-continue,
.ap-dash--focused .ap-today{min-height:236px}

/* ---- Today's Prayers: tighter vertical rhythm ---- */
.ap-dash--focused .ap-today{padding:18px}
.ap-dash--focused .ap-today .ap-card__head{margin-bottom:12px}
.ap-dash--focused .ap-prayers{margin-bottom:12px}
/* Tiles keep one size. Letting them grow to fill the card made Today taller,
   which in turn forced Continue to stretch further — the void moved rather
   than closed. */
.ap-dash--focused .ap-prayer{min-height:86px; max-height:none; height:auto}
.ap-dash--focused .ap-prayers{flex:0 0 auto; align-content:start}
.ap-dash--focused .ap-today .ap-wk{margin-top:auto; padding-top:12px}

@media (max-width:560px){
	/* Full width only where it genuinely helps the thumb. */
	.ap-dash--focused .ap-continue__go{align-self:stretch; width:100%; justify-content:center}
}

/* ---- Meeting the two cards in the middle ----
   Continue's natural content came to 204px against Today's 259, so the row's
   stretch left 55px below the button. Rather than pad one card to match the
   other, both move toward a common height: Today's rhythm tightens a little,
   and Continue's gaps open a little. What is left is real spacing in both
   cards, not a void in one. */

/* Today: -20px, all of it from spacing that was looser than it needed to be. */
.ap-dash--focused .ap-today{padding:16px 18px}
.ap-dash--focused .ap-today .ap-card__head{margin-bottom:10px}
.ap-dash--focused .ap-prayer{min-height:82px}
.ap-dash--focused .ap-prayers{margin-bottom:10px}
.ap-dash--focused .ap-today .ap-wk{padding-top:10px}
.ap-dash--focused .ap-wk__day{padding:4px 0}

/* Continue: +30px, spread across the rhythm so each step reads as deliberate
   rather than as one gap doing all the work. */
.ap-dash--focused .ap-continue{padding:22px}
.ap-dash--focused .ap-continue__eyebrow{margin:0 0 8px}
.ap-dash--focused .ap-continue__meta{margin:8px 0 0}
.ap-dash--focused .ap-continue__track{margin-top:20px}
.ap-dash--focused .ap-continue__left{margin:12px 0 0}
.ap-dash--focused .ap-continue__go{margin-top:22px}

/* ---- Week header on Today's Prayers ----
   The strip is a record of a specific Monday-to-Sunday week, so it says which
   one. Sits on the divider line above the days, at meta weight so it labels
   the strip without competing with the prayers above it. */
.ap-dash--focused .ap-wk__head{
	display:flex; align-items:baseline; justify-content:space-between;
	gap:10px; margin-top:auto; padding-top:10px;
	border-top:1px solid var(--ap-line);
}
.ap-dash--focused .ap-wk__caption{
	font-size:var(--t-meta); font-weight:var(--weight-heavy);
	letter-spacing:.06em; text-transform:uppercase; color:var(--ap-text-mute);
}
.ap-dash--focused .ap-wk__range{
	font-size:var(--t-meta); font-weight:var(--weight-bold);
	color:var(--ap-text); white-space:nowrap;
}
/* The divider now lives on the header above, so the list drops its own. */
.ap-dash--focused .ap-today .ap-wk{
	margin-top:8px; padding-top:0; border-top:0;
}

/* Days later this week have not happened yet: outlined and faint, so an empty
   Saturday on a Wednesday does not read as a missed day. */
.ap-dash--focused .ap-wk__day.is-future .ap-wk__mark{
	background:transparent; border-color:var(--ap-line); opacity:.5;
}
.ap-dash--focused .ap-wk__day.is-future .ap-wk__lbl{opacity:.55}

/* ===========================================================================
   CONTINUE LEARNING — two zones, content-driven height
   ---------------------------------------------------------------------------
   Course information on the left, the action on the right. No fixed height, no
   space-between, no stretched button: the card is as tall as its content and
   the right zone is a real destination for the eye rather than the leftover
   space the CTA was previously pushed into.
   =========================================================================== */
.ap-dash--focused .ap-continue{
	display:grid;
	/* The action column takes what it needs; the information column takes the
	   rest. minmax(0,1fr) is what stops a long course title forcing overflow. */
	grid-template-columns:minmax(0,1fr) auto;
	align-items:center;
	gap:20px 28px;
	padding:22px 24px;
	position:relative;
	overflow:hidden;
}

.ap-dash--focused .ap-continue__body{
	display:flex; flex-direction:column; align-items:flex-start;
	width:100%; min-width:0;
}

/* ---- Eyebrow ---- */
.ap-dash--focused .ap-continue__eyebrow{
	display:flex; align-items:center; gap:9px;
	margin:0 0 10px;
	font-size:var(--t-meta); font-weight:var(--weight-heavy);
	letter-spacing:.11em; text-transform:uppercase; color:#8ee4bd;
}
.ap-continue__badge{
	display:grid; place-items:center; flex:0 0 auto;
	width:26px; height:26px; border-radius:9px;
	background:rgba(255,255,255,.13); color:#a7f3d0;
}
.ap-continue__badge svg{width:14px; height:14px}

/* ---- Title and lesson ---- */
.ap-dash--focused .ap-continue__title{
	margin:0; font-size:var(--t-head); line-height:1.2;
	font-weight:var(--weight-heavy); letter-spacing:-.015em; color:#fff;
	overflow-wrap:break-word;
}
.ap-dash--focused .ap-continue__meta{
	margin:6px 0 0; font-size:var(--t-body); color:#c6ecdb; line-height:1.35;
}
.ap-dash--focused .ap-continue__dot{
	margin:0 8px; color:#4ade9b; font-size:1.1em; vertical-align:-.05em;
}

/* ---- Progress: bar and figure read as one unit ---- */
.ap-dash--focused .ap-continue__track{
	display:flex; align-items:center; gap:14px;
	margin-top:18px; width:100%;
}
.ap-dash--focused .ap-continue__meter{
	/* Capped, not stretched: a bar running the full width of a wide card reads
	   as decoration rather than as a measure. */
	flex:1 1 auto; max-width:280px;
	height:8px; border-radius:999px;
	background:rgba(255,255,255,.18); overflow:hidden;
}
.ap-dash--focused .ap-continue__fill{
	display:block; height:100%; border-radius:999px; background:#6ee7b7;
	transition:width .5s cubic-bezier(.22,1,.36,1);
}
@media (prefers-reduced-motion:reduce){.ap-dash--focused .ap-continue__fill{transition:none}}
.ap-dash--focused .ap-continue__pct{
	flex:0 0 auto;
	font-size:var(--t-sub); font-weight:var(--weight-heavy); color:#fff;
	font-variant-numeric:tabular-nums; white-space:nowrap;
}
.ap-dash--focused .ap-continue__left{
	margin:9px 0 0; font-size:var(--t-meta); color:#9fd9c0;
}

/* ---- Action zone ---- */
.ap-dash--focused .ap-continue__action{
	position:relative;
	display:flex; flex-direction:column; align-items:center; justify-content:center;
	gap:16px; flex:0 0 auto;
	padding-left:28px;
	/* One hairline separating information from action — the only divider in
	   the card, and it earns its place. */
	border-left:1px solid rgba(255,255,255,.14);
	align-self:stretch;
}
/* A quiet accent, from the design system's own icon set. It sits behind the
   button at low opacity so the right zone has weight without an illustration
   competing with the course title. */
.ap-continue__mark{
	position:absolute; inset:0;
	display:grid; place-items:center;
	color:#fff; opacity:.07; pointer-events:none;
}
.ap-continue__mark svg{width:104px; height:104px}

.ap-dash--focused .ap-continue__go{
	position:relative; z-index:1;
	display:inline-flex; align-items:center; justify-content:center; gap:10px;
	margin:0; width:auto; align-self:auto;
	min-height:46px; padding:0 26px;
	border-radius:999px; border:0;
	background:#fff; color:#0b5137;
	font-size:var(--t-body); font-weight:var(--weight-heavy);
	text-decoration:none; white-space:nowrap;
	transition:background .15s ease;
}
.ap-dash--focused .ap-continue__go:hover{background:#ecfdf5}
.ap-dash--focused .ap-continue__go:focus-visible{
	outline:none; box-shadow:0 0 0 3px rgba(255,255,255,.7);
}
.ap-continue__arrow{transition:transform .15s ease}
.ap-dash--focused .ap-continue__go:hover .ap-continue__arrow{transform:translateX(3px)}
@media (prefers-reduced-motion:reduce){
	.ap-dash--focused .ap-continue__go,.ap-continue__arrow{transition:none}
	.ap-dash--focused .ap-continue__go:hover .ap-continue__arrow{transform:none}
}

/* ---- Reorganise before the columns get tight ---- */
@container dash (max-width:1000px){
	/* Below this the information column drops under ~300px and the title starts
	   breaking badly, so the two zones stack instead of narrowing. */
	.ap-dash--focused .ap-continue{grid-template-columns:minmax(0,1fr); gap:18px}
	.ap-dash--focused .ap-continue__action{
		flex-direction:row; align-items:center; justify-content:flex-start;
		border-left:0; padding-left:0;
		border-top:1px solid rgba(255,255,255,.14); padding-top:18px;
		align-self:auto;
	}
	/* The watermark belongs to the tall right column; stacked, it would sit
	   behind the button as noise. */
	.ap-continue__mark{display:none}
}
@container dash (max-width:420px){
	.ap-dash--focused .ap-continue{padding:18px}
	.ap-dash--focused .ap-continue__go{width:100%}
	.ap-dash--focused .ap-continue__meter{max-width:none}
}

/* ---- Closing the last of the slack ----
   The card's own content came to ~141px in a 267px card, so 63px sat above and
   below it. Even space reads as padding rather than as a hole, but that much is
   airier than the brief's "compact enough that every section feels connected".

   The rhythm opens instead: more room between the four blocks and a slightly
   deeper pad, so the height is filled by real spacing and the residual drops to
   a few pixels a side. Nothing is stretched and no height is fixed. */
.ap-dash--focused .ap-continue{padding:26px}
.ap-dash--focused .ap-continue__eyebrow{margin-bottom:14px}
.ap-dash--focused .ap-continue__meta{margin-top:8px}
.ap-dash--focused .ap-continue__track{margin-top:22px}
.ap-dash--focused .ap-continue__left{margin-top:12px}

/* The shared floor is now below both cards' natural heights, so it no longer
   does anything except guarantee a sensible minimum on a sparse account. */
.ap-dash--focused .ap-continue,
.ap-dash--focused .ap-today{min-height:200px}

/* ---- Did You Know / Promised Messiah: headline + folded fact ---- */
.ap-dash--focused .ap-feature__hook{
	margin:0 0 6px;
	font-size:var(--t-body); font-weight:var(--weight-heavy);
	line-height:1.3; color:var(--ap-text); letter-spacing:-.005em;
}
.ap-dash--focused .ap-feature__why{
	margin:10px 0 0; padding-left:10px;
	border-left:2px solid color-mix(in srgb, var(--ap-accent,#b45309) 45%, #fff);
	font-size:var(--t-meta); line-height:1.45; color:var(--ap-text-soft);
}
.ap-feature__whylabel{
	display:block;
	font-weight:var(--weight-heavy); letter-spacing:.05em; text-transform:uppercase;
	color:var(--ap-accent,#b45309); font-size:.66rem; margin-bottom:2px;
}
