.sdi-button{display: inline-flex;align-items: center;justify-content: center;gap: var(--sdi-space-2xs);padding: 0.75em 1.5em;border: 1px solid transparent;border-radius: var(--sdi-radius);background: var(--sdi-primary);color: var(--sdi-on-invert);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-button);font-weight: var(--sdi-weight-semibold);line-height: 1.2;text-decoration: none;cursor: pointer;transition: background-color var(--sdi-duration) var(--sdi-ease),border-color var(--sdi-duration) var(--sdi-ease),color var(--sdi-duration) var(--sdi-ease),box-shadow var(--sdi-duration) var(--sdi-ease),transform var(--sdi-duration-fast) var(--sdi-ease)}.sdi-button:hover{background: var(--sdi-primary-hover);color: var(--sdi-on-invert);box-shadow: var(--sdi-shadow);transform: translateY(-1px)}.sdi-button:active{transform: translateY(0);box-shadow: var(--sdi-shadow-sm)}.sdi-button[disabled],.sdi-button[aria-disabled="true"]{opacity: 0.5;box-shadow: none;transform: none;cursor: not-allowed;pointer-events: none}.sdi-button__icon{display: inline-block;transition: transform var(--sdi-duration) var(--sdi-ease-out)}.sdi-button:hover .sdi-button__icon{transform: translateX(3px)}.sdi-link__icon{display: inline-block;transition: transform var(--sdi-duration) var(--sdi-ease)}a:hover > .sdi-link__icon{transform: translateX(3px)}.sdi-button--secondary{background: transparent;border-color: var(--sdi-line-interactive);color: var(--sdi-heading)}.sdi-button--secondary:hover{background: var(--sdi-surface);border-color: var(--sdi-primary);color: var(--sdi-primary)}.sdi-button--accent{background: var(--sdi-accent)}.sdi-button--accent:hover{background: var(--sdi-brass-500);color: var(--sdi-navy-900)}.sdi-button--ghost{padding-inline: 0;background: none;color: var(--sdi-accent)}.sdi-button--ghost:hover{background: none;box-shadow: none;color: var(--sdi-primary-hover)}.sdi-button--large{padding: 0.9em 1.9em;font-size: var(--sdi-text-body)}.sdi-button--full{width: 100%}.sdi-invert .sdi-button{background: var(--sdi-on-invert);color: var(--sdi-navy-900)}.sdi-invert .sdi-button:hover{background: var(--sdi-brass-500);color: var(--sdi-navy-900)}.sdi-invert .sdi-button--secondary{background: transparent;border-color: rgba(255,255,255,0.45);color: var(--sdi-on-invert)}.sdi-invert .sdi-button--secondary:hover{background: rgba(255,255,255,0.08);border-color: var(--sdi-on-invert);color: var(--sdi-on-invert)}.sdi-link{display: inline-flex;align-items: center;min-height: 1.5rem;gap: var(--sdi-space-3xs);color: var(--sdi-accent);font-weight: var(--sdi-weight-medium);text-decoration: none;background-image: linear-gradient(currentColor,currentColor);background-size: 0% 1px;background-position: 0 100%;background-repeat: no-repeat;transition: background-size var(--sdi-duration) var(--sdi-ease-out)}.sdi-link:hover,.sdi-link:focus-visible{background-size: 100% 1px}.sdi-media{position: relative;overflow: hidden;aspect-ratio: var(--sdi-ratio-card);max-width: 100%;background: var(--sdi-surface-alt);border-radius: var(--sdi-radius)}.sdi-media--hero{aspect-ratio: var(--sdi-ratio-hero)}.sdi-media--split{aspect-ratio: var(--sdi-ratio-split)}.sdi-media--card{aspect-ratio: var(--sdi-ratio-card)}.sdi-media--article{aspect-ratio: var(--sdi-ratio-article)}.sdi-media--portrait{aspect-ratio: var(--sdi-ratio-portrait)}.sdi-media--square{aspect-ratio: 1 / 1}.sdi-media > img{width: 100%;height: 100%;object-fit: cover;transition: transform var(--sdi-duration-slow) var(--sdi-ease-out)}.sdi-media__placeholder{position: absolute;inset: 0;display: flex;flex-direction: column;align-items: center;justify-content: center;gap: var(--sdi-space-2xs);padding: var(--sdi-space-md);background: radial-gradient(circle at 30% 25%,rgba(184,147,63,0.16),transparent 55%),linear-gradient(145deg,var(--sdi-navy-800),var(--sdi-navy-900));color: rgba(255,255,255,0.72);text-align: center}.sdi-media__placeholder svg{width: clamp(1.25rem,22%,3rem);height: auto;aspect-ratio: 1 / 1;opacity: 0.55}/* * The "artwork still to come" chip. * * It is a sibling of the panel,not a child,and it is positioned against * the slot itself. Two visual QA findings drove that. Centred inside the * panel it wrote itself straight through the hero headline at every * viewport;and inside the panel it also inherited the parallax layer's 8%
 * scale, which pushed it past the slot's clipped edge and shaved five * pixels off its bottom. Anchored to the slot it is legible,unclipped and * out of the copy's way in every context.
 */
.sdi-media__placeholder-label {
	position: absolute;
	inset-inline: var(--sdi-space-sm);
	bottom: var(--sdi-space-sm);
	z-index: 1;
	width: fit-content;
	max-width: calc(100% - (2 * var(--sdi-space-sm)));
	margin-inline: auto;
	padding: 0.25em 0.7em;
	background: rgba(10, 32, 62, 0.72);
	border: 1px solid rgba(255, 255, 255, 0.18);
	border-radius: var(--sdi-radius-pill);
	color: rgba(255, 255, 255, 0.82);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-caption);
	letter-spacing: var(--sdi-tracking-wide);
	line-height: var(--sdi-leading-snug);
	text-align: center;
	text-transform: uppercase;
	overflow-wrap: anywhere;
}

/*
 * Behind hero copy the panel is a backdrop, so its compass mark is dropped
 * rather than drawn through the headline. Scoped to the hero's own media * layer,not to every 16:9 slot — a 16:9 slot elsewhere on the page is an * ordinary image and keeps its mark. */ .sdi-hero__media .sdi-media__placeholder svg{display: none}.sdi-media__scrim{position: absolute;inset: 0;background: linear-gradient(180deg,rgba(10,32,62,0.15) 0%,rgba(10,32,62,0.72) 100%)}.sdi-open{display: flex;flex-direction: column;gap: var(--sdi-space-xs)}.sdi-card{display: flex;flex-direction: column;overflow: hidden;background: var(--sdi-surface);border: 1px solid var(--sdi-line);border-radius: var(--sdi-radius);transition: border-color var(--sdi-duration) var(--sdi-ease),box-shadow var(--sdi-duration) var(--sdi-ease),transform var(--sdi-duration) var(--sdi-ease)}.sdi-card__body{display: flex;flex-direction: column;gap: var(--sdi-space-2xs);padding: var(--sdi-card-padding);flex: 1 1 auto}.sdi-card__title{margin: 0;font-size: var(--sdi-text-h4)}.sdi-card__title a{color: var(--sdi-heading)}.sdi-card__meta{color: var(--sdi-muted);font-size: var(--sdi-text-caption)}/* * The footer carries the card's own gutters. It previously set only a top
 * padding, which left every footer link and button flush against the card's * left edge — visible the moment a real card was rendered rather than a * style-guide sample with no footer. */ .sdi-card__footer{margin-top: auto;padding: var(--sdi-space-sm) var(--sdi-card-padding) var(--sdi-card-padding)}/* The body already owns the space above;a footer under it should not add the card's full padding again. */
.sdi-card__body + .sdi-card__footer { padding-top: 0; }

.sdi-card--interactive:hover {
	border-color: var(--sdi-line-strong);
	box-shadow: var(--sdi-shadow-lift);
	transform: translateY(-2px);
}

.sdi-card--interactive:hover .sdi-media > img { transform: scale(var(--sdi-image-zoom)); }

.sdi-card--raised { box-shadow: var(--sdi-shadow); }

/* Caution card. Used where a card states a limit rather than a benefit — on
   the eligibility page, the list of what reaching a tier does not do.
 *
 * It is deliberately the same size and weight as the card beside it: the two
 * are equally important, and shrinking the qualification would be a way of
 * burying it. Only the rail and the surface change, which is enough to mark
 * the card without making it look like an error. */
.sdi-card--caution {
	background: var(--sdi-warning-surface);
	border-color: var(--sdi-warning);
	border-top: 3px solid var(--sdi-warning);
}

/* Programme and directory cards share the card shell and differ only in
   the accent rail, so the family stays visually consistent. */
.sdi-card--program { border-top: 3px solid var(--sdi-accent); }
.sdi-card--directory .sdi-card__body { gap: var(--sdi-space-3xs); }

/* Membership card. The featured variant is lifted with the brand navy
   rather than a coloured border, so it reads as the recommended plan
   without shouting. */
.sdi-card--membership { text-align: left; }
.sdi-card--membership .sdi-card__body { gap: var(--sdi-space-sm); }

.sdi-price {
	display: flex;
	align-items: baseline;
	gap: var(--sdi-space-3xs);
	color: var(--sdi-heading);
	font-family: var(--sdi-font-display);
	font-size: var(--sdi-text-h2);
	font-weight: var(--sdi-weight-semibold);
	line-height: 1;
}

.sdi-price__period { color: var(--sdi-muted); font-family: var(--sdi-font-ui); font-size: var(--sdi-text-body-sm); font-weight: var(--sdi-weight-regular); }

/*
 * Text colour, the focus ring and the bullet colour all come from the token
 * remap in tokens.css, which lists this class alongside `.sdi-invert`. Only
 * the two things the remap does not cover are set here: the card's own * ground,and the button,whose fill is a component decision rather than a * ground-dependent one. */ .sdi-card--featured{background: var(--sdi-navy-900);border-color: var(--sdi-navy-900)}.sdi-card--featured .sdi-button{background: var(--sdi-brass-500);color: var(--sdi-navy-900)}.sdi-card--featured .sdi-button:hover{background: var(--sdi-on-invert)}.sdi-feature-list{margin: 0;padding: 0;list-style: none;display: flex;flex-direction: column;gap: var(--sdi-space-2xs)}.sdi-feature-list li{display: flex;gap: var(--sdi-space-2xs);align-items: flex-start;font-size: var(--sdi-text-body-sm)}.sdi-feature-list li::before{content: "";flex: 0 0 auto;width: 0.5rem;height: 0.5rem;margin-top: 0.45em;border-radius: 50%;background: var(--sdi-accent)}.sdi-testimonial{display: flex;flex-direction: column;gap: var(--sdi-space-sm);padding: var(--sdi-card-padding);background: var(--sdi-surface);border-left: 3px solid var(--sdi-accent);border-radius: 0 var(--sdi-radius) var(--sdi-radius) 0}.sdi-testimonial__quote{margin: 0;color: var(--sdi-heading);font-family: var(--sdi-font-display);font-size: var(--sdi-text-body-lg);line-height: var(--sdi-leading-snug)}.sdi-testimonial__attribution{display: flex;align-items: center;gap: var(--sdi-space-xs)}.sdi-testimonial__avatar{width: 2.75rem;height: 2.75rem;border-radius: 50%;overflow: hidden;flex: 0 0 auto}.sdi-testimonial__name{color: var(--sdi-heading);font-size: var(--sdi-text-body-sm);font-weight: var(--sdi-weight-semibold)}.sdi-testimonial__role{color: var(--sdi-muted);font-size: var(--sdi-text-caption)}.sdi-stat{display: flex;flex-direction: column;gap: var(--sdi-space-3xs)}.sdi-stat__value{color: var(--sdi-heading);font-family: var(--sdi-font-display);font-size: var(--sdi-text-h1);font-weight: var(--sdi-weight-semibold);line-height: 1;font-variant-numeric: tabular-nums}.sdi-stat__label{color: var(--sdi-muted);font-size: var(--sdi-text-body-sm)}.sdi-stat--placeholder .sdi-stat__value{color: var(--sdi-muted);opacity: 0.55}.sdi-badge{display: inline-flex;align-items: center;gap: var(--sdi-space-3xs);padding: 0.25em 0.7em;border-radius: var(--sdi-radius-pill);background: var(--sdi-surface-accent);color: var(--sdi-heading);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-caption);font-weight: var(--sdi-weight-semibold);letter-spacing: var(--sdi-tracking-wide);text-transform: uppercase;white-space: nowrap}.sdi-badge--success{background: var(--sdi-success-surface);color: var(--sdi-success)}.sdi-badge--warning{background: var(--sdi-warning-surface);color: var(--sdi-warning)}.sdi-badge--error{background: var(--sdi-error-surface);color: var(--sdi-error)}.sdi-badge--info{background: var(--sdi-info-surface);color: var(--sdi-info)}.sdi-badge--neutral{background: var(--sdi-surface-alt);color: var(--sdi-body)}.sdi-status{display: inline-flex;align-items: center;gap: var(--sdi-space-2xs);font-size: var(--sdi-text-body-sm);font-weight: var(--sdi-weight-medium)}.sdi-status::before{content: "";width: 0.55rem;height: 0.55rem;border-radius: 50%;background: currentColor;flex: 0 0 auto}.sdi-status--active{color: var(--sdi-success)}.sdi-status--pending{color: var(--sdi-warning)}.sdi-status--expired{color: var(--sdi-error)}.sdi-status--inactive{color: var(--sdi-muted)}.sdi-alert{display: flex;flex-direction: column;gap: var(--sdi-space-3xs);padding: var(--sdi-space-sm) var(--sdi-space-md);border: 1px solid transparent;border-left-width: 3px;border-radius: var(--sdi-radius);font-size: var(--sdi-text-body-sm);line-height: var(--sdi-leading-normal)}.sdi-alert p{margin: 0}.sdi-alert--info{background: var(--sdi-info-surface);border-color: var(--sdi-info);--sdi-alert-accent: var(--sdi-info)}.sdi-alert--success{background: var(--sdi-success-surface);border-color: var(--sdi-success);--sdi-alert-accent: var(--sdi-success)}.sdi-alert--warning{background: var(--sdi-warning-surface);border-color: var(--sdi-warning);--sdi-alert-accent: var(--sdi-warning)}.sdi-alert--error{background: var(--sdi-error-surface);border-color: var(--sdi-error);--sdi-alert-accent: var(--sdi-error)}.sdi-alert__title{display: block;color: var(--sdi-alert-accent,var(--sdi-heading));font-weight: var(--sdi-weight-semibold)}.sdi-alert{color: var(--sdi-body)}.sdi-field{display: flex;flex-direction: column;gap: var(--sdi-space-3xs);margin-bottom: var(--sdi-form-gap)}.sdi-label{color: var(--sdi-heading);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-label);font-weight: var(--sdi-weight-semibold)}.sdi-label__required{color: var(--sdi-error)}.sdi-help{color: var(--sdi-muted);font-size: var(--sdi-text-help)}.sdi-error-text{color: var(--sdi-error);font-size: var(--sdi-text-help);font-weight: var(--sdi-weight-medium)}.sdi-input,.sdi-select,.sdi-textarea,input[type="text"],input[type="email"],input[type="url"],input[type="tel"],input[type="number"],input[type="password"],input[type="search"],input[type="date"],select,textarea{width: 100%;padding: 0.7em 0.9em;background: var(--sdi-surface);color: var(--sdi-body);border: 1px solid var(--sdi-line-interactive);border-radius: var(--sdi-radius);font-family: var(--sdi-font-body);font-size: var(--sdi-text-body);line-height: 1.4;transition: border-color var(--sdi-duration) var(--sdi-ease),box-shadow var(--sdi-duration) var(--sdi-ease)}.sdi-input:hover,.sdi-select:hover,.sdi-textarea:hover,input:hover:not([type="checkbox"]):not([type="radio"]):not([type="submit"]),select:hover,textarea:hover{border-color: var(--sdi-primary)}.sdi-input:focus,.sdi-select:focus,.sdi-textarea:focus,input:focus:not([type="checkbox"]):not([type="radio"]),select:focus,textarea:focus{outline: none;border-color: var(--sdi-accent);box-shadow: 0 0 0 3px rgba(138,106,33,0.18)}.sdi-field--invalid .sdi-input,.sdi-input[aria-invalid="true"]{border-color: var(--sdi-error)}textarea,.sdi-textarea{min-height: 8rem;resize: vertical}.sdi-select,select{appearance: none;padding-right: 2.25em;background-image: linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position: calc(100% - 1.15em) 55%,calc(100% - 0.8em) 55%;background-size: 0.35em 0.35em,0.35em 0.35em;background-repeat: no-repeat}.sdi-choice{display: flex;align-items: flex-start;gap: var(--sdi-space-2xs);font-size: var(--sdi-text-body-sm)}.sdi-choice input{width: 1.5rem;height: 1.5rem;margin: 0.05em 0 0;accent-color: var(--sdi-accent);flex: 0 0 auto}.sdi-progress{display: flex;flex-direction: column;gap: var(--sdi-space-3xs)}.sdi-progress__track{height: 0.6rem;overflow: hidden;background: var(--sdi-surface-alt);border-radius: var(--sdi-radius-pill)}.sdi-progress__bar{height: 100%;width: 0;border-radius: inherit;background: linear-gradient(90deg,var(--sdi-navy-700),var(--sdi-brass-500));transition: width var(--sdi-duration-reveal) var(--sdi-ease-out)}.sdi-progress__meta{display: flex;justify-content: space-between;gap: var(--sdi-space-xs);color: var(--sdi-muted);font-size: var(--sdi-text-caption)}.sdi-accordion{border-top: 1px solid var(--sdi-line)}.sdi-accordion__item{border-bottom: 1px solid var(--sdi-line)}.sdi-accordion__summary{display: flex;align-items: center;justify-content: space-between;gap: var(--sdi-space-sm);padding: var(--sdi-space-sm) 0;color: var(--sdi-heading);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-body-lg);font-weight: var(--sdi-weight-semibold);cursor: pointer;list-style: none;transition: color var(--sdi-duration) var(--sdi-ease)}.sdi-accordion__summary::-webkit-details-marker{display: none}.sdi-accordion__summary:hover{color: var(--sdi-accent)}.sdi-accordion__icon{flex: 0 0 auto;width: 0.6em;height: 0.6em;border-right: 2px solid currentColor;border-bottom: 2px solid currentColor;transform: rotate(45deg);transition: transform var(--sdi-duration) var(--sdi-ease)}.sdi-accordion__item[open] .sdi-accordion__icon{transform: rotate(225deg)}.sdi-accordion__content{padding-bottom: var(--sdi-space-md);max-width: var(--sdi-measure)}.sdi-tabs__list{display: flex;flex-wrap: wrap;gap: var(--sdi-space-xs);margin: 0 0 var(--sdi-space-md);padding: 0;border-bottom: 1px solid var(--sdi-line);list-style: none}.sdi-tabs__tab{padding: var(--sdi-space-2xs) var(--sdi-space-xs);margin-bottom: -1px;background: none;border: 0;border-bottom: 2px solid transparent;color: var(--sdi-muted);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-body-sm);font-weight: var(--sdi-weight-semibold);cursor: pointer;transition: color var(--sdi-duration) var(--sdi-ease),border-color var(--sdi-duration) var(--sdi-ease)}.sdi-tabs__tab:hover{color: var(--sdi-heading)}.sdi-tabs__tab[aria-selected="true"]{color: var(--sdi-heading);border-bottom-color: var(--sdi-accent)}.sdi-breadcrumbs{font-size: var(--sdi-text-body-sm);color: var(--sdi-muted)}.sdi-breadcrumbs ol{display: flex;flex-wrap: wrap;gap: var(--sdi-space-3xs);margin: 0;padding: 0;list-style: none}.sdi-breadcrumbs li::after{content: "/";margin-left: var(--sdi-space-3xs);color: var(--sdi-line-strong)}.sdi-breadcrumbs li:last-child::after{content: none}.sdi-breadcrumbs a{display: inline-block;padding-block: 0.2rem;color: var(--sdi-muted);text-decoration: none}.sdi-breadcrumbs a:hover{color: var(--sdi-accent)}.pagination .nav-links{display: flex;flex-wrap: wrap;gap: var(--sdi-space-3xs)}.pagination .page-numbers{display: inline-flex;align-items: center;justify-content: center;min-width: 2.5rem;padding: var(--sdi-space-2xs) var(--sdi-space-xs);background: var(--sdi-surface);border: 1px solid var(--sdi-line);border-radius: var(--sdi-radius);color: var(--sdi-body);text-decoration: none;transition: border-color var(--sdi-duration) var(--sdi-ease),color var(--sdi-duration) var(--sdi-ease)}.pagination .page-numbers:hover{border-color: var(--sdi-primary);color: var(--sdi-primary)}.pagination .page-numbers.current{background: var(--sdi-primary);border-color: var(--sdi-primary);color: var(--sdi-on-invert)}.sdi-hero{position: relative;overflow: hidden;background: var(--sdi-navy-900);--sdi-heading: var(--sdi-on-invert);--sdi-body: var(--sdi-on-invert-muted);--sdi-muted: var(--sdi-on-invert-muted);--sdi-accent: var(--sdi-brass-500);--sdi-line: rgba(255,255,255,0.14);--sdi-line-interactive: rgba(255,255,255,0.45);--sdi-focus: var(--sdi-focus-invert);color: var(--sdi-body)}/* On a navy ground the solid navy button reads as a hole,so the hero's
   primary action takes the light treatment and the secondary goes outline. */
.sdi-hero .sdi-button { background: var(--sdi-on-invert); color: var(--sdi-navy-900); }
.sdi-hero .sdi-button:hover { background: var(--sdi-brass-500); color: var(--sdi-navy-900); }
.sdi-hero .sdi-button--secondary { background: transparent; border-color: rgba(255, 255, 255, 0.45); color: var(--sdi-on-invert); }
.sdi-hero .sdi-button--secondary:hover { background: rgba(255, 255, 255, 0.1); border-color: var(--sdi-on-invert); color: var(--sdi-on-invert); }
.sdi-hero__media { position: absolute; inset: 0; }

/*
 * The hero's media layer is a backdrop,so the slot inside it fills that * layer rather than holding its own aspect ratio. Without this the 16:9 box * is taller than the hero,and anything anchored to its bottom edge — the * pending-artwork chip — lands below the clip and is never seen. */ .sdi-hero__media .sdi-media{position: absolute;inset: 0;aspect-ratio: auto;max-width: none;border-radius: 0;background: none}.sdi-hero__media img{width: 100%;height: 100%;object-fit: cover}.sdi-hero__inner{position: relative;z-index: var(--sdi-z-base);display: flex;flex-direction: column;gap: var(--sdi-space-md);max-width: 42rem;padding-block: clamp(3.5rem,9vw,7rem)}.sdi-hero__title{margin: 0;color: var(--sdi-on-invert)}.sdi-hero__lead{margin: 0;max-width: 34rem;color: var(--sdi-on-invert-muted);font-size: var(--sdi-text-body-lg)}.sdi-hero :focus-visible{outline-color: var(--sdi-focus-invert)}.sdi-cta{display: grid;grid-template-columns: minmax(0,1fr) auto;align-items: center;gap: var(--sdi-space-lg);padding: clamp(1.75rem,4vw,2.75rem);background: var(--sdi-navy-900);border-radius: var(--sdi-radius-lg);color: var(--sdi-on-invert)}/* * The text shrinks;it does not force a wrap. * * At 1440px the body's 38rem basis plus the actions came to 1048px inside a
 * 1032px panel — sixteen pixels over, which wrapped the whole row and left
 * 468px of navy empty to the right of the buttons, on every page with a call
 * to action. Sixteen pixels of overflow should cost sixteen pixels of text
 * width, not half the panel.
 *
 * The 22rem basis is where wrapping becomes the right answer: below that the
 * text is too narrow to read beside a button row, and the tablet layout
 * stacks instead.
 */
.sdi-cta__body {
	max-width: 38rem;
	display: flex;
	flex-direction: column;
	gap: var(--sdi-space-2xs);
}

/* One column below tablet: the text needs the full width to stay readable,
   and the buttons then go full width beneath it. */
@media (max-width: 60rem) {
	.sdi-cta { grid-template-columns: 1fr; }
}
.sdi-cta__title { margin: 0; color: var(--sdi-on-invert); }
.sdi-cta__text { margin: 0; color: var(--sdi-on-invert-muted); }
.sdi-cta :focus-visible { outline-color: var(--sdi-focus-invert); }
.sdi-cta .sdi-button { background: var(--sdi-brass-500); color: var(--sdi-navy-900); }
.sdi-cta .sdi-button:hover { background: var(--sdi-on-invert); }
.sdi-cta .sdi-button--secondary { background: transparent; border-color: rgba(255,255,255,0.45); color: var(--sdi-on-invert); }

/* Ghost inside an inverted call to action. Without this it inherited the
   brass fill above and rendered as a second accent button — three actions,
   two of them shouting, and no hierarchy between them. */
.sdi-cta .sdi-button--ghost {
	background: transparent;
	border-color: transparent;
	color: var(--sdi-on-invert-muted);
}

.sdi-cta .sdi-button--ghost:hover { background: transparent; color: var(--sdi-on-invert); }

/* ══ Dashboard ═════════════════════════════════════════════════════════
 *
 * Deliberately image-free: information density, not photography.
 */

.sdi-dash-grid { display: grid; gap: var(--sdi-grid-gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }

.sdi-dash-card {
	display: flex;
	flex-direction: column;
	gap: var(--sdi-space-2xs);
	padding: var(--sdi-card-padding);
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius);
}

.sdi-dash-card__label {
	color: var(--sdi-muted);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-eyebrow);
	font-weight: var(--sdi-weight-semibold);
	letter-spacing: var(--sdi-tracking-eyebrow);
	text-transform: uppercase;
}

.sdi-dash-card__value {
	color: var(--sdi-heading);
	font-family: var(--sdi-font-display);
	font-size: var(--sdi-text-h2);
	font-weight: var(--sdi-weight-semibold);
	line-height: 1;
	font-variant-numeric: tabular-nums;
}

.sdi-dash-card__foot { color: var(--sdi-muted); font-size: var(--sdi-text-caption); }
.sdi-dash-card--accent { border-top: 3px solid var(--sdi-accent); }

/* ══ Dialog ════════════════════════════════════════════════════════════
 *
 * Native <dialog>: focus trapping, Escape and inertness come from the
 * platform rather than from script that has to be maintained.
 */

.sdi-dialog {
	max-width: min(34rem, calc(100vw - 2rem));
	padding: 0;
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius-lg);
	box-shadow: var(--sdi-shadow-lift);
	color: var(--sdi-body);
}

.sdi-dialog::backdrop { background: rgba(10, 32, 62, 0.55); }
.sdi-dialog__header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sdi-space-sm); padding: var(--sdi-space-md) var(--sdi-space-md) 0; }
.sdi-dialog__title { margin: 0; font-size: var(--sdi-text-h4); }
.sdi-dialog__body { padding: var(--sdi-space-sm) var(--sdi-space-md); }
.sdi-dialog__footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sdi-space-2xs); padding: 0 var(--sdi-space-md) var(--sdi-space-md); }

/* ══ Divider ═══════════════════════════════════════════════════════════ */

.sdi-divider { display: flex; align-items: center; gap: var(--sdi-space-sm); color: var(--sdi-line-strong); }
.sdi-divider::before, .sdi-divider::after { content: ""; height: 1px; flex: 1 1 auto; background: currentColor; }

/* ══ WordPress entry components ════════════════════════════════════════ */

.entry-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); gap: var(--sdi-grid-gap); margin-block: var(--sdi-space-xl); }

.entry--card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius);
	transition: border-color var(--sdi-duration) var(--sdi-ease), box-shadow var(--sdi-duration) var(--sdi-ease), transform var(--sdi-duration) var(--sdi-ease);
}

.entry--card:hover { border-color: var(--sdi-line-strong); box-shadow: var(--sdi-shadow-lift); transform: translateY(-2px); }
.entry--card:hover .entry__media img { transform: scale(var(--sdi-image-zoom)); }

.entry__media { display: block; overflow: hidden; aspect-ratio: var(--sdi-ratio-article); background: var(--sdi-surface-alt); }
.entry__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--sdi-duration-slow) var(--sdi-ease-out); }

.entry__body { display: flex; flex-direction: column; gap: var(--sdi-space-2xs); padding: var(--sdi-card-padding); flex: 1 1 auto; }
.entry__title { margin: 0; font-size: var(--sdi-text-h4); }
.entry__title a { color: var(--sdi-heading); }
.entry__title a:hover { color: var(--sdi-accent); }
.entry__meta, .entry-meta { color: var(--sdi-muted); font-size: var(--sdi-text-caption); }
.entry__excerpt { color: var(--sdi-body); font-size: var(--sdi-text-body-sm); }

/* ══ Legal document ════════════════════════════════════════════════════
 *
 * A last-updated date is the first thing somebody checks on a policy: it
 * tells them whether what they are reading is the version that applied when
 * they signed up. So it sits above the text rather than buried at the end.
 */

.sdi-legal__updated {
	margin: 0 0 var(--sdi-space-lg);
	color: var(--sdi-muted);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-body-sm);
}

/* ══ Search ════════════════════════════════════════════════════════════ */

.sdi-search { max-width: 34rem; }

.sdi-search__row { display: flex; flex-wrap: wrap; gap: var(--sdi-space-2xs); }

/* The field takes the room; the button keeps its own width. Below the wrap
   point both go full width rather than the button being squeezed to an
   ellipsis. */
.sdi-search__field { flex: 1 1 14rem; min-width: 0; }
.sdi-search .sdi-button { flex: 0 0 auto; }

/* ══ Resource list ═════════════════════════════════════════════════════
 *
 * A downloads or events list, where the thing being scanned is the title and
 * the thing being compared is the date or the file type. A card grid would
 * put those in a different place on every row; a list keeps them in one
 * column, so a reader can run down it.
 */

.sdi-resource-list {
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--sdi-line);
}

.sdi-resource {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sdi-space-2xs) var(--sdi-space-lg);
	padding-block: var(--sdi-space-md);
	border-bottom: 1px solid var(--sdi-line);
}

.sdi-resource__body { flex: 1 1 22rem; min-width: 0; }

.sdi-resource__title { margin: 0; font-size: var(--sdi-text-h5); }

/*
 * 24px minimum (WCAG 2.5.8). A resource title is the whole target — the
 * thing a reader taps to open a document — so the Inline exception does not
 * reach it, and at this size its line box is 20px. The same fix the standalone
 * link component carries, for the same reason.
 */
.sdi-resource__title a {
	display: inline-flex;
	align-items: center;
	min-height: 1.5rem;
	color: var(--sdi-heading);
	text-decoration: none;
}

.sdi-resource__title a:hover { color: var(--sdi-accent); }

.sdi-resource__summary {
	margin: var(--sdi-space-3xs) 0 0;
	max-width: var(--sdi-measure);
	color: var(--sdi-body);
	font-size: var(--sdi-text-body-sm);
}

/* The meta column. `white-space: nowrap` keeps "PDF, 1.2 MB" and a date on
   one line; at narrow widths the row wraps and it starts its own. */
.sdi-resource__meta {
	flex: 0 0 auto;
	margin: 0;
	color: var(--sdi-muted);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-caption);
	white-space: nowrap;
}

.archive-header { margin-bottom: var(--sdi-space-xl); }
.archive-title { margin-bottom: var(--sdi-space-2xs); }
.archive-description { color: var(--sdi-muted); max-width: var(--sdi-measure); }

.entry--single .entry-header { margin-bottom: var(--sdi-space-lg); }
.entry-thumbnail { margin: 0 0 var(--sdi-space-xl); overflow: hidden; border-radius: var(--sdi-radius); aspect-ratio: var(--sdi-ratio-hero); }
.entry-thumbnail img { width: 100%; height: 100%; object-fit: cover; }

.comments-area { max-width: var(--sdi-measure); margin-top: var(--sdi-space-2xl); padding-top: var(--sdi-space-lg); border-top: 1px solid var(--sdi-line); }
.comment-list { list-style: none; padding: 0; }
.no-results { max-width: var(--sdi-measure); }

/* ══ Navigation ════════════════════════════════════════════════════════ */

.primary-menu, .footer-menu { display: flex; flex-wrap: wrap; gap: var(--sdi-space-md); margin: 0; padding: 0; list-style: none; }
.primary-menu .menu-item { position: relative; }

.menu-item__link {
	display: inline-block;
	padding-block: var(--sdi-space-2xs);
	color: var(--sdi-heading);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-nav);
	font-weight: var(--sdi-weight-medium);
	text-decoration: none;
	background-image: linear-gradient(var(--sdi-accent), var(--sdi-accent));
	background-size: 0% 2px;
	background-position: 0 100%;
	background-repeat: no-repeat;
	transition: color var(--sdi-duration) var(--sdi-ease), background-size var(--sdi-duration) var(--sdi-ease-out);
}

.menu-item__link:hover { color: var(--sdi-accent); background-size: 100% 2px; }
.menu-item__link[aria-current] { color: var(--sdi-heading); background-size: 100% 2px; }

.menu-item__toggle, .nav-toggle {
	display: inline-flex;
	align-items: center;
	gap: var(--sdi-space-2xs);
	padding: var(--sdi-space-2xs);
	background: none;
	border: 1px solid transparent;
	border-radius: var(--sdi-radius);
	color: var(--sdi-heading);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-nav);
	cursor: pointer;
	transition: color var(--sdi-duration) var(--sdi-ease), border-color var(--sdi-duration) var(--sdi-ease);
}

.menu-item__toggle:hover, .nav-toggle:hover { color: var(--sdi-accent); }

.menu-item__toggle-icon, .nav-toggle__icon {
	display: block;
	width: 0.55em; height: 0.55em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--sdi-duration) var(--sdi-ease);
}

.nav-toggle { display: none; border-color: var(--sdi-line-interactive); padding-inline: var(--sdi-space-xs); }

/* Submenus collapse only when scripting is available to reopen them. */
.js .sub-menu {
	display: none;
	position: absolute;
	top: 100%; left: 0;
	z-index: var(--sdi-z-dropdown);
	min-width: 15rem;
	margin: 0;
	padding: var(--sdi-space-2xs);
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius);
	box-shadow: var(--sdi-shadow-lift);
	list-style: none;
}

/*
 * A third level opens beside its parent, not below it. Inside a dropdown
 * that is already absolutely positioned, `top: 100%` lays the panel over the
 * items that follow it — the walker numbers every level, so the rule can key
 * off any depth past the first rather than off a fixed number of them.
 */
.js .sub-menu:not(.sub-menu--depth-1) {
	top: calc(var(--sdi-space-2xs) * -1);
	left: calc(100% + var(--sdi-space-2xs));
}

.js .menu-item--has-disclosure.is-open > .sub-menu { display: block; animation: sdi-dropdown var(--sdi-duration) var(--sdi-ease-out); }
.js .menu-item--has-disclosure.is-open > .menu-item__toggle .menu-item__toggle-icon { transform: rotate(225deg); }

@keyframes sdi-dropdown {
	from { opacity: 0; transform: translateY(-6px); }
	to { opacity: 1; transform: translateY(0); }
}

.sub-menu .menu-item__link { display: block; padding: var(--sdi-space-2xs) var(--sdi-space-xs); background-size: 0 0; border-radius: var(--sdi-radius-sm); }
.sub-menu .menu-item__link:hover { background: var(--sdi-surface-alt); background-size: 0 0; }

.footer-navigation--legal .footer-menu { gap: var(--sdi-space-xs) var(--sdi-space-md); }

/*
 * The secondary menu sits in a footer column, where the shared horizontal
 * menu style made eight section links read as a wrapped paragraph. As a
 * grid they fill the column in tidy sub-columns instead.
 */
.site-footer__top .footer-navigation--secondary .footer-menu {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
	gap: var(--sdi-space-3xs) var(--sdi-space-md);
	align-content: start;
}
/* Nine legal links wrap into a dense block on a phone. Padding lifts each
   one to a 24px hit area without changing the visual rhythm. */
.footer-menu .menu-item a { display: inline-block; padding-block: 0.25rem; color: var(--sdi-on-invert-muted); font-size: var(--sdi-text-body-sm); text-decoration: none; transition: color var(--sdi-duration) var(--sdi-ease); }
.footer-menu .menu-item a:hover { color: var(--sdi-on-invert); }

/*
 * The footer widget area.
 *
 * WordPress puts its own default widgets — Archives, Categories, Recent
 * Posts — into the first sidebar a theme registers, on every fresh
 * install. So this markup appears whether or not anybody chose it, and
 * without these rules it appeared as browser-default headings and bullets
 * on a navy ground: serif, oversized, underlined, and nothing like the
 * rest of the footer.
 *
 * Styled to match the secondary menu beside it rather than invented anew,
 * because that is what it sits next to.
 */
.site-footer__widgets {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
	gap: var(--sdi-space-md) var(--sdi-space-lg);
	align-content: start;
}

.site-footer__widgets .widget {
	min-width: 0;
}

/*
 * Block widgets nest their content in group wrappers that carry margins of
 * their own. Flattened, so a widget's spacing comes from this grid rather * than from however many wrappers the block editor produced. */ .site-footer__widgets .wp-block-group,.site-footer__widgets .wp-block-group__inner-container{margin: 0}/* * Both kinds of widget title. * * `before_title` only reaches classic widgets. WordPress 5.8 and later put * **block** widgets in a sidebar by default,and those render their own * `<h2 class="wp-block-heading">` and ignore the registration entirely — so * styling `.widget__title` alone left a fresh install with two oversized * serif headings in the footer,which is exactly what shipped. */ .site-footer__widgets .widget__title,.site-footer__widgets h1,.site-footer__widgets h2,.site-footer__widgets h3,.site-footer__widgets h4{margin: 0 0 var(--sdi-space-2xs);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-eyebrow);font-weight: 600;letter-spacing: var(--sdi-tracking-eyebrow);text-transform: uppercase;color: var(--sdi-on-invert)}.site-footer__widgets ul{margin: 0;padding: 0;list-style: none}.site-footer__widgets li{margin: 0}.site-footer__widgets a{display: inline-block;padding-block: 0.25rem;color: var(--sdi-on-invert-muted);font-size: var(--sdi-text-body-sm);text-decoration: none;transition: color var(--sdi-duration) var(--sdi-ease)}.site-footer__widgets a:hover{color: var(--sdi-on-invert)}.site-footer__widgets p,.site-footer__widgets label{margin: 0 0 var(--sdi-space-2xs);color: var(--sdi-on-invert-muted);font-size: var(--sdi-text-body-sm)}.site-footer__widgets select,.site-footer__widgets input[type="search"],.site-footer__widgets input[type="text"]{width: 100%;max-width: 100%;padding: 0.5rem 0.625rem;border: 1px solid var(--sdi-line-interactive);border-radius: var(--sdi-radius-sm);background: var(--sdi-surface);color: var(--sdi-body);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-body-sm)}@media (max-width: 56.25rem){.js .nav-toggle{display: inline-flex}.js .primary-menu{display: none;flex-direction: column;gap: 0;width: 100%}.js .primary-navigation.is-open .primary-menu{display: flex}.js .primary-menu > .menu-item{border-bottom: 1px solid var(--sdi-line)}.primary-navigation{width: 100%}.js .site-header__inner{flex-wrap: nowrap;gap: var(--sdi-space-2xs)}.js .site-branding{min-width: 0}.js .site-title{font-size: var(--sdi-text-h5)}.js .site-header__actions{order: 2;margin-inline-start: auto;gap: var(--sdi-space-2xs)}/* "Member login" is a top-level item in the menu,so repeating it beside the toggle costs a row and says nothing new. */ .js .site-header__signin{display: none}.js .site-header .primary-navigation{order: 3;width: auto;margin-inline-start: 0}/* * With the toggle sharing the row,the open menu drops out of the header * as a full-width panel rather than being confined to the toggle's own
	 * width.
	 */
	.js .primary-navigation.is-open .primary-menu {
		position: absolute;
		inset-inline: 0;
		top: 100%;
		z-index: var(--sdi-z-dropdown);
		padding: var(--sdi-space-2xs) var(--sdi-gutter) var(--sdi-space-sm);
		background: var(--sdi-surface);
		border-bottom: 1px solid var(--sdi-line);
		box-shadow: var(--sdi-shadow-lift);
	}

	/* Inline rather than overlaid: an absolutely positioned panel near the
	   viewport edge is easy to push off-screen and hard to dismiss on touch. */
	.js .sub-menu { position: static; min-width: 0; border: 0; border-radius: 0; box-shadow: none; padding-left: var(--sdi-space-md); animation: none; }
	.js .menu-item--has-disclosure { display: grid; grid-template-columns: 1fr auto; align-items: center; }
	.js .menu-item--has-disclosure > .sub-menu { grid-column: 1 / -1; }

	.sdi-cta { flex-direction: column; align-items: flex-start; }
	.sdi-hero__inner { padding-block: clamp(2.5rem, 12vw, 4rem); }
}

@media (max-width: 30rem) {
	.sdi-button { width: 100%; }
	.sdi-cluster > .sdi-button { width: 100%; }
	.sdi-cluster { flex-direction: column; align-items: stretch; }
}

/* ══ Section headers ═══════════════════════════════════════════════════
 *
 * Every homepage section opens the same way: a small label, a title, and an
 * optional supporting line. Consistency here does more for a premium feel
 * than any individual flourish — a page where each section announces itself
 * differently reads as assembled rather than designed.
 */

.sdi-section__title {
	margin: var(--sdi-space-2xs) 0 0;
	font-size: var(--sdi-text-h2);
	letter-spacing: var(--sdi-tracking-tight);
}

.sdi-section__lead {
	margin: var(--sdi-space-sm) 0 0;
	max-width: var(--sdi-measure);
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-lg);
	line-height: var(--sdi-leading-normal);
}

.sdi-section__footnote,
.sdi-section__note {
	margin: var(--sdi-space-lg) 0 0;
	max-width: var(--sdi-measure);
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-sm);
}

.sdi-section--band {
	background: var(--sdi-surface);
	border-block: 1px solid var(--sdi-line);
}

.sdi-section--page-intro { padding-block: var(--sdi-section-padding-tight) 0; }

/*
 * Two sections of the same tone are one band, and a band should not pay for
 * two edges in the middle of itself.
 *
 * Where the tone changes, two paddings are what separates the bands and the
 * change of colour justifies the space. Where it does not, the reader sees
 * one continuous band with a 173px hole in it — measured at 24 boundaries
 * across 18 pages, including the homepage, and the largest single source of
 * dead vertical space left in the build.
 *
 * Collapsing the second section's top padding leaves exactly one section * padding at the boundary,which is the same rhythm as the space between a * section's content and its own edge.
 *
 * `--note` is excluded: it is a compact footnote band with its own hairline
 * and its own deliberate padding, and zeroing that would collapse the text
 * onto the rule.
 */
.sdi-section:not(.sdi-section--alt):not(.sdi-section--band)
	+ .sdi-section:not(.sdi-section--alt):not(.sdi-section--band):not(.sdi-section--note),
.sdi-section--alt + .sdi-section--alt:not(.sdi-section--note),
.sdi-section--band + .sdi-section--band:not(.sdi-section--note) {
	padding-block-start: 0;
}

/*
 * A footnote band, for the scholarship and programme disclaimers.
 *
 * These sat in a `--tight` section, which is 56px of air above and below one
 * line of small print: 42px of content inside 178px, on eleven pages. A
 * disclaimer is a footnote and should read as one — it does not want a
 * section's worth of importance,and the space around it was the largest * single piece of dead vertical space in the build. * * The hairline is what does the separating now,instead of the padding. */ .sdi-section--note{padding-block: var(--sdi-space-md);border-top: 1px solid var(--sdi-line)}.sdi-section--note .sdi-disclaimer{margin: 0}/* The section's own header owns its bottom margin; a grid or table follows. */
.sdi-section__header + .sdi-grid,
.sdi-section__header + .sdi-steps,
.sdi-section__header + .sdi-tiles,
.sdi-section__header + .sdi-table-wrap,
.sdi-section__header + .sdi-cluster { margin-top: var(--sdi-space-xl); }

.sdi-split__body .sdi-section__header { margin-bottom: 0; }

/* ══ Numbered steps ════════════════════════════════════════════════════ */

.sdi-steps {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
	gap: var(--sdi-grid-gap);
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: sdi-step;
}

.sdi-step {
	position: relative;
	padding-top: var(--sdi-space-md);
	border-top: 2px solid var(--sdi-line);
}

/* The accent rule marks progress across the row without needing a graphic. */
.sdi-step::before {
	content: "";
	position: absolute;
	top: -2px;
	left: 0;
	width: 2.5rem;
	height: 2px;
	background: var(--sdi-accent);
}

.sdi-step__number {
	display: block;
	color: var(--sdi-accent);
	font-family: var(--sdi-font-display);
	font-size: var(--sdi-text-h4);
	font-variant-numeric: tabular-nums;
	line-height: 1;
}

.sdi-step__title {
	margin: var(--sdi-space-2xs) 0 0;
	font-size: var(--sdi-text-h5);
}

.sdi-step__body {
	margin: var(--sdi-space-2xs) 0 0;
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-sm);
	line-height: var(--sdi-leading-normal);
}

/* ══ Category tiles ════════════════════════════════════════════════════ */

/*
 * A tile grid whose column count is chosen from the number of tiles rather
 * than from the available width.
 *
 * `auto-fit` at a 12rem minimum fits five columns in the container, so the
 * eight directory categories rendered five across and three stranded
 * beneath — the same fault the card grids had, in a component that was not
 * covered when those were fixed. The template asks for the column count and
 * the modifier applies it.
 */
.sdi-tiles {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
	gap: var(--sdi-space-sm);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sdi-tiles--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sdi-tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sdi-tiles--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* A tile is unreadable much under 10rem, so the fixed counts collapse
   rather than squeezing. Two across is the floor above phone width. */
@media (max-width: 60rem) {
	.sdi-tiles--4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 48rem) {
	.sdi-tiles--3,
	.sdi-tiles--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 30rem) {
	.sdi-tiles--2,
	.sdi-tiles--3,
	.sdi-tiles--4 { grid-template-columns: 1fr; }
}

.sdi-tile { display: flex; }

.sdi-tile__link {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--sdi-space-3xs);
	padding: var(--sdi-space-md);
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius);
	color: var(--sdi-heading);
	text-decoration: none;
	transition:
		border-color var(--sdi-duration) var(--sdi-ease),
		box-shadow var(--sdi-duration) var(--sdi-ease),
		transform var(--sdi-duration) var(--sdi-ease-out);
}

.sdi-tile__link:hover {
	border-color: var(--sdi-line-strong);
	box-shadow: var(--sdi-shadow-lift);
	transform: translateY(-2px);
}

.sdi-tile__name { font-weight: var(--sdi-weight-semibold); }
.sdi-tile__count { color: var(--sdi-muted); font-size: var(--sdi-text-caption); }

/* ══ Data table ════════════════════════════════════════════════════════
 *
 * The scholarship tiers. A table because it is tabular data — four rows of
 * points against award levels — and because a screen reader user needs the
 * row and column relationships that a grid of cards throws away.
 */

.sdi-table-wrap {
	overflow-x: auto;
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius);
}

.sdi-table {
	width: 100%;
	/*
	 * base.css gives every block element a bottom margin for flowing prose.
	 * A table inside a wrapper that owns its spacing does not want it, and
	 * it showed as 24px of dead space under the last row, inside the
	 * wrapper's own border. */ margin: 0;border-collapse: collapse;font-variant-numeric: tabular-nums}.sdi-table th,.sdi-table td{padding: var(--sdi-space-sm) var(--sdi-space-md);text-align: left;border-bottom: 1px solid var(--sdi-line)}.sdi-table tbody tr:last-child th,.sdi-table tbody tr:last-child td{border-bottom: 0}.sdi-table thead th{background: var(--sdi-surface-alt);color: var(--sdi-heading);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-caption);font-weight: var(--sdi-weight-semibold);letter-spacing: var(--sdi-tracking-wide);text-transform: uppercase;white-space: nowrap}/* * Below the breakpoint the longest header ("Award level you may apply for") * held the table at 813px inside a 390px viewport — technically scrollable,* but most of a second screen away. Wrapping the headers and tightening the * cells turns that into a short nudge. */ @media (max-width: 48rem){.sdi-table thead th{white-space: normal}.sdi-table th,.sdi-table td{padding: var(--sdi-space-xs) var(--sdi-space-sm)}.sdi-table__figure{font-size: var(--sdi-text-body)}}/* * A date is one value and must not be broken across lines. Wrapping the * headers (above) is a gain;wrapping "11 September 2026" into three stacked * lines is not — it took every row of the points ledger to 97px on a phone * and turned ten entries into a thousand pixels of scrolling. * * Held on one line the site's full date format takes 182px of a 348px table,
 * which pushed the change and balance columns — the two a member opens the
 * ledger to read — off the right edge. So `table_date()` renders the same
 * timestamp twice and the narrow view shows the shorter form. One of the two
 * is always displayed, never neither.
 */
.sdi-table td > time { white-space: nowrap; }
.sdi-table td > time .sdi-date__short { display: none; }

@media (max-width: 48rem) {
	.sdi-table td > time .sdi-date__long { display: none; }
	.sdi-table td > time .sdi-date__short { display: inline; }
}

/*
 * On a phone the gutters are what is left to give. Four columns at 16px each
 * side spend 128px on padding alone, which was a third of the visible table.
 * Halving it keeps the cells legible and brings the points ledger down to a
 * nudge of horizontal scroll instead of a column-and-a-half.
 */
@media (max-width: 30rem) {
	.sdi-table th,
	.sdi-table td { padding: var(--sdi-space-xs) var(--sdi-space-2xs); }
}

/* A hairline edge so a table that scrolls looks like it scrolls. */
.sdi-table-wrap {
	background-image:
		linear-gradient(to right, var(--sdi-surface) 30%, rgba(255, 255, 255, 0)),
		linear-gradient(to left, var(--sdi-surface) 30%, rgba(255, 255, 255, 0)),
		linear-gradient(to right, rgba(10, 32, 62, 0.10), rgba(10, 32, 62, 0)),
		linear-gradient(to left, rgba(10, 32, 62, 0.10), rgba(10, 32, 62, 0));
	background-position: left center, right center, left center, right center;
	background-repeat: no-repeat;
	background-size: 2.5rem 100%, 2.5rem 100%, 0.9rem 100%, 0.9rem 100%;
	background-attachment: local, local, scroll, scroll;
}

.sdi-table tbody th { color: var(--sdi-heading); font-weight: var(--sdi-weight-semibold); }
.sdi-table td { color: var(--sdi-body); }

.sdi-table__figure {
	color: var(--sdi-heading);
	font-family: var(--sdi-font-display);
	font-size: var(--sdi-text-h5);
	font-weight: var(--sdi-weight-semibold);
	white-space: nowrap;
}

/* ══ Lists ═════════════════════════════════════════════════════════════ */

.sdi-list {
	display: flex;
	flex-direction: column;
	gap: var(--sdi-space-2xs);
	margin: var(--sdi-space-md) 0 0;
	padding: 0;
	list-style: none;
}

.sdi-list li {
	position: relative;
	padding-left: var(--sdi-space-md);
	font-size: var(--sdi-text-body-sm);
	line-height: var(--sdi-leading-normal);
}

.sdi-list--benefits li::before,
.sdi-list--checks li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.5em;
	width: 0.4rem;
	height: 0.4rem;
	background: var(--sdi-accent);
	border-radius: var(--sdi-radius-pill);
}

/* A drawn tick, so the list reads as confirmation rather than as bullets. */
.sdi-list--checks li::before {
	top: 0.32em;
	width: 0.36rem;
	height: 0.62rem;
	background: none;
	border: solid var(--sdi-accent);
	border-width: 0 2px 2px 0;
	border-radius: 0;
	transform: rotate(45deg);
}

/* The counterpart list: what something does NOT do.
 *
 * Drawn as a cross rather than a tick, because the two lists sit side by side
 * on the eligibility page and a reader skimming the marks has to be able to
 * tell them apart without reading either heading. The mark is built from two
 * rotated rules on a single pseudo-element so nothing depends on an icon font
 * or an image loading.
 *
 * Colour alone never carries the meaning — each list has its own heading, and
 * the shapes differ — so this stays legible to a reader who cannot separate
 * the two hues (WCAG 1.4.1). */
.sdi-list--crosses li {
	position: relative;
	padding-left: var(--sdi-space-md);
	font-size: var(--sdi-text-body-sm);
	line-height: var(--sdi-leading-normal);
}

.sdi-list--crosses li::before,
.sdi-list--crosses li::after {
	content: "";
	position: absolute;
	left: 0;
	top: 0.62em;
	width: 0.6rem;
	height: 2px;
	background: var(--sdi-warning);
	border-radius: 1px;
}

.sdi-list--crosses li::before { transform: rotate(45deg); }
.sdi-list--crosses li::after { transform: rotate(-45deg); }

/* ══ Callout ═══════════════════════════════════════════════════════════ */

.sdi-callout {
	margin-top: var(--sdi-space-lg);
	padding: var(--sdi-space-md);
	background: var(--sdi-info-surface);
	border-left: 3px solid var(--sdi-info);
	border-radius: 0 var(--sdi-radius) var(--sdi-radius) 0;
}

.sdi-callout p { margin: 0; color: var(--sdi-body); font-size: var(--sdi-text-body-sm); }

.sdi-callout--info { background: var(--sdi-info-surface); border-left-color: var(--sdi-info); }

/*
 * Actions need air after whatever they follow, and so do an alert and a
 * panel.
 *
 * The left-hand side of this was a list of the block types these had been
 * seen to follow — callout, disclaimer, table, tiles, grid, list, accordion,
 * alert, steps — and it went stale in three separate page groups: each new
 * block type landed flush against the buttons beneath it, was spotted in a
 * screenshot, and was added to the list. Stated as "anything", that side
 * cannot go stale again.
 *
 * The right-hand side is still a list, and the donation form panel joined it
 * the day it was written. That one is safe to enumerate because it is no
 * longer guarded by somebody remembering to look: `check-visual.js` measures
 * every adjacent pair on every page at three viewports, and it is what
 * caught the panel. A tighter gap is still available to anything that wants
 * one, by saying so.
 */
* + .sdi-cluster,
* + .sdi-alert,
* + .sdi-portal__panel,
* + .sdi-search,
* + .sdi-table-wrap { margin-top: var(--sdi-space-lg); }

/* ══ Disclaimer ════════════════════════════════════════════════════════
 *
 * Set below body copy but never below the contrast floor. A disclaimer is
 * the one piece of small print that has to be readable.
 */

.sdi-disclaimer {
	margin: var(--sdi-space-md) 0 0;
	max-width: var(--sdi-measure);
	color: var(--sdi-muted);
	font-size: var(--sdi-text-caption);
	line-height: var(--sdi-leading-normal);
}

/* ══ Button variants added for the page templates ══════════════════════ */

.sdi-button--block { width: 100%; justify-content: center; }

.sdi-button--compact {
	padding: 0.5em 1em;
	font-size: var(--sdi-text-caption);
}

/* ══ Prose ═════════════════════════════════════════════════════════════
 *
 * Editor-written content on a template that is otherwise composed of
 * sections. Constrained to the reading measure so a front-page introduction
 * does not run the full width of a 1440px screen.
 */

.sdi-prose { max-width: var(--sdi-measure); }
.sdi-prose > * + * { margin-top: var(--sdi-space-md); }

/* ══ Hero actions ══════════════════════════════════════════════════════ */

.sdi-hero__actions { margin-top: var(--sdi-space-lg); }

/* ══ Plan grid ═════════════════════════════════════════════════════════
 *
 * Two plans, capped so they do not stretch to fill a wide viewport: a
 * pricing card 40rem wide reads as a banner, not as a choice.
 */

/*
 * The plan cards span the content width, like everything else in the section.
 *
 * They were capped at 56rem, which left 224px of nothing to their right
 * while the comparison table below spanned the full width. Centring the cap
 * fixed the dead space and introduced a worse fault: the cards no longer
 * shared a left edge with their own section heading, 112px to their left.
 *
 * Content aligns with the heading that introduces it. Two cards across the
 * full width is 544px each, which is wide for a plan card and still the
 * right answer — the alternative is a block that floats free of the column
 * everything else on the page sits in.
 */
.sdi-grid--plans { max-width: none; }

/*
 * The amount and its caveat are one unit, so they are wrapped rather than
 * left as two siblings of the card body — the body's own gap put 44px * between a price and the note explaining it,which read as unrelated. */ .sdi-price-block{display: flex;flex-direction: column;gap: var(--sdi-space-3xs)}.sdi-price-block .sdi-price{margin: 0}.sdi-price__caveat{margin: 0;color: var(--sdi-muted);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-caption)}.sdi-card--membership .sdi-card__footer{padding-top: var(--sdi-space-md)}/* ══ Page header ═══════════════════════════════════════════════════════ * * The opening of an inner page. Deliberately not a hero: a hero on every * page is how a site ends up with five near-identical navy bands and no * sense of where the reader is. This is quieter,and it lets the page's
 * first real section do the work.
 */

.sdi-page-header {
	padding-block: var(--sdi-section-padding-tight);
	background: var(--sdi-surface);
	border-bottom: 1px solid var(--sdi-line);
}

.sdi-page-header__title {
	margin: var(--sdi-space-2xs) 0 0;
	max-width: 20ch;
	font-size: var(--sdi-text-h1);
	letter-spacing: var(--sdi-tracking-tight);
}

.sdi-page-header__lead {
	margin: var(--sdi-space-sm) 0 0;
	max-width: var(--sdi-measure);
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-lg);
	line-height: var(--sdi-leading-normal);
}

/* ══ Comparison marks ══════════════════════════════════════════════════
 *
 * A drawn tick or dash, with a text equivalent beside it in the markup. A
 * bare glyph is silent to a screen reader and ambiguous to everyone else
 * once the column header has scrolled off the top.
 */

.sdi-table__mark { text-align: center; }

.sdi-mark {
	display: inline-block;
	vertical-align: middle;
}

.sdi-mark--yes {
	width: 0.45rem;
	height: 0.8rem;
	border: solid var(--sdi-success);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg) translate(-0.1rem, -0.05rem);
}

.sdi-mark--no {
	width: 0.7rem;
	height: 2px;
	background: var(--sdi-line-interactive);
}

.sdi-table__price {
	display: block;
	margin-top: 0.15rem;
	color: var(--sdi-muted);
	font-weight: var(--sdi-weight-regular);
	letter-spacing: var(--sdi-tracking-normal);
	text-transform: none;
}

.sdi-table--comparison th[scope="row"] { font-weight: var(--sdi-weight-regular); }

/*
 * The plan columns take a fixed share, so the ticks sit near the benefit
 * they answer instead of being pushed to the far edge of a 1120px table
 * with 700px of empty benefit column between.
 */
.sdi-table--comparison { table-layout: fixed; }
.sdi-table--comparison th:not(:first-child) { width: 22%; text-align: center; }
.sdi-table--comparison thead th:first-child { width: 56%; }

@media (max-width: 48rem) {
	.sdi-table--comparison th:not(:first-child) { width: 25%; }
	.sdi-table--comparison thead th:first-child { width: 50%; }
}

/* ══ Sign-in and registration ══════════════════════════════════════════
 *
 * Narrow and quiet. Someone on these pages is trying to get in or to join,
 * and every other thing on screen is between them and that.
 */

.sdi-auth { padding-block: var(--sdi-section-padding); }

/*
 * The registration page routes rather than collecting, so it carries less
 * than the sign-in page does. Left at full container width its single panel
 * stretched to 1120px and read as a band rather than as something to act on.
 */
.sdi-auth--wide .sdi-auth__header,
.sdi-auth--wide .sdi-auth__panel,
.sdi-auth--wide .sdi-auth__intro,
.sdi-auth--wide .sdi-auth__aside { max-width: 44rem; }

.sdi-auth__header { margin-bottom: var(--sdi-space-lg); }

.sdi-auth__title {
	margin: var(--sdi-space-2xs) 0 0;
	font-size: var(--sdi-text-h2);
	letter-spacing: var(--sdi-tracking-tight);
}

.sdi-auth__panel {
	padding: var(--sdi-card-padding);
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line);
	border-radius: var(--sdi-radius);
	box-shadow: var(--sdi-shadow);
}

.sdi-auth__lead { margin: 0 0 var(--sdi-space-md); color: var(--sdi-body); }

.sdi-auth__intro { margin-bottom: var(--sdi-space-lg); }

.sdi-auth__plans { margin-bottom: var(--sdi-space-md); }

.sdi-auth__aside {
	margin-top: var(--sdi-space-md);
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-sm);
}

.sdi-auth__aside p { margin: 0 0 var(--sdi-space-2xs); }
.sdi-auth__switch { color: var(--sdi-muted); }

/*
 * WordPress core's own login form markup. The theme's field styles are
 * keyed to elements rather than classes, so the inputs are already styled;
 * what is left is the layout core does not provide.
 */

#sdi-login-form p { margin: 0 0 var(--sdi-space-md); }
#sdi-login-form label { display: block; margin-bottom: var(--sdi-space-3xs); font-family: var(--sdi-font-ui); font-size: var(--sdi-text-label); font-weight: var(--sdi-weight-semibold); }

#sdi-login-form .login-remember { display: flex; align-items: center; gap: var(--sdi-space-2xs); }
#sdi-login-form .login-remember label { display: flex; align-items: center; gap: var(--sdi-space-2xs); margin: 0; font-weight: var(--sdi-weight-regular); }

/* 24px minimum: core renders a bare checkbox, which is 13px on most
   platforms and fails WCAG 2.5.8 on touch. */
#sdi-login-form .login-remember input[type="checkbox"] { width: 1.5rem; height: 1.5rem; accent-color: var(--sdi-accent); }

#sdi-login-form .login-submit { margin-bottom: 0; }

#sdi-login-form .login-submit input[type="submit"],
#sdi-login-form #wp-submit {
	width: 100%;
	padding: 0.8em 1.4em;
	background: var(--sdi-primary);
	color: var(--sdi-on-invert);
	border: 1px solid transparent;
	border-radius: var(--sdi-radius);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-button);
	font-weight: var(--sdi-weight-semibold);
	cursor: pointer;
	transition: background var(--sdi-duration) var(--sdi-ease);
}

#sdi-login-form .login-submit input[type="submit"]:hover,
#sdi-login-form #wp-submit:hover { background: var(--sdi-primary-hover); }

/* ══ Member portal ═════════════════════════════════════════════════════
 *
 * Deliberately image-free and dense. Somebody in their portal is checking a
 * balance, a status or a date; photography there costs load time and pushes
 * the thing they came for below the fold.
 */

.sdi-portal { padding-block: var(--sdi-section-padding-tight) var(--sdi-section-padding); }

.sdi-portal__header { margin-bottom: var(--sdi-space-lg); }

.sdi-portal__title {
	margin: var(--sdi-space-2xs) 0 0;
	font-size: var(--sdi-text-h2);
	letter-spacing: var(--sdi-tracking-tight);
}

.sdi-portal__layout { display: grid; gap: var(--sdi-space-xl); }

@media (min-width: 60rem) {
	.sdi-portal__layout { grid-template-columns: 14rem 1fr; align-items: start; }

	/* Sticky under the header, which is itself sticky: the offset keeps the
	   nav clear of it rather than sliding underneath. */
	.sdi-portal__nav { position: sticky; top: 5.5rem; }
}

.sdi-portal__nav-list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sdi-space-3xs);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 60rem) {
	.sdi-portal__nav-list { flex-direction: column; flex-wrap: nowrap; }
}

.sdi-portal__nav-link {
	display: block;
	padding: var(--sdi-space-2xs) var(--sdi-space-sm);
	border-radius: var(--sdi-radius);
	color: var(--sdi-body);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-nav);
	font-weight: var(--sdi-weight-medium);
	text-decoration: none;
	transition: background var(--sdi-duration) var(--sdi-ease), color var(--sdi-duration) var(--sdi-ease);
}

.sdi-portal__nav-link:hover { background: var(--sdi-surface-alt); color: var(--sdi-heading); }

/*
 * The current view is marked by weight and an accent rule as well as by
 * background. Colour alone would fail 1.4.1 — and would disappear entirely
 * in forced-colours mode.
 */
.sdi-portal__nav-link.is-current {
	background: var(--sdi-primary);
	color: var(--sdi-on-invert);
	font-weight: var(--sdi-weight-semibold);
}


.sdi-portal__main { min-width: 0; }

/*
 * Two columns, not the shared auto-fit. In the portal's narrower main column * auto-fit put three cards on one row and orphaned the fourth;a 2x2 block * reads as one set of figures rather than a row plus a straggler. */ @media (min-width: 40rem){.sdi-portal__section .sdi-dash-grid{grid-template-columns: repeat(2,minmax(0,1fr))}}.sdi-portal__section{display: flex;flex-direction: column;gap: var(--sdi-space-lg)}.sdi-portal__section-header{display: flex;flex-wrap: wrap;align-items: baseline;justify-content: space-between;gap: var(--sdi-space-sm);padding-bottom: var(--sdi-space-sm);border-bottom: 1px solid var(--sdi-line)}.sdi-portal__section-title{margin: 0;font-size: var(--sdi-text-h3)}.sdi-portal__figure{margin: 0;display: flex;align-items: baseline;gap: var(--sdi-space-2xs)}.sdi-portal__figure-value{color: var(--sdi-heading);font-family: var(--sdi-font-display);font-size: var(--sdi-text-h3);font-variant-numeric: tabular-nums;font-weight: var(--sdi-weight-semibold)}.sdi-portal__figure-label{color: var(--sdi-muted);font-size: var(--sdi-text-caption)}.sdi-portal__panel{padding: var(--sdi-card-padding);background: var(--sdi-surface);border: 1px solid var(--sdi-line);border-radius: var(--sdi-radius)}.sdi-portal__panel-title{margin: 0 0 var(--sdi-space-sm);font-size: var(--sdi-text-h5)}.sdi-portal__panel > p:last-child{margin-bottom: 0}.sdi-portal__empty{padding: var(--sdi-space-xl) var(--sdi-card-padding);background: var(--sdi-surface);border: 1px dashed var(--sdi-line-interactive);border-radius: var(--sdi-radius);text-align: center}.sdi-portal__empty-title{margin: 0 0 var(--sdi-space-2xs);color: var(--sdi-heading);font-weight: var(--sdi-weight-semibold)}.sdi-portal__empty p:last-child{margin: 0;color: var(--sdi-muted);font-size: var(--sdi-text-body-sm)}.sdi-portal__note{display: block;color: var(--sdi-muted);font-size: var(--sdi-text-caption)}.sdi-dash-card__value--empty{color: var(--sdi-muted)}.sdi-dash-card__value--text{font-size: var(--sdi-text-h5);line-height: var(--sdi-leading-snug)}.sdi-table__numeric{text-align: right;font-variant-numeric: tabular-nums}.sdi-delta{font-variant-numeric: tabular-nums;font-weight: var(--sdi-weight-semibold);white-space: nowrap}.sdi-delta--up{color: var(--sdi-success)}.sdi-delta--down{color: var(--sdi-error)}.sdi-detail-list{margin: 0;display: flex;flex-direction: column;gap: var(--sdi-space-sm)}.sdi-detail-list__row{display: grid;grid-template-columns: minmax(8rem,12rem) 1fr;gap: var(--sdi-space-sm);align-items: baseline}@media (max-width: 30rem){.sdi-detail-list__row{grid-template-columns: 1fr;gap: var(--sdi-space-3xs)}}/* * Stacked in a narrow column whatever the viewport is. The two-column row * needs roughly 20rem to work;in the listing sidebar it had about nine for * the value,which broke "2 August 2026" across three lines. A container * query would express this directly — this is the same rule scoped to the * one place that is narrow by construction. */ .sdi-listing__aside .sdi-detail-list__row{grid-template-columns: 1fr;gap: var(--sdi-space-3xs)}.sdi-listing__aside .sdi-detail-list{gap: var(--sdi-space-md)}.sdi-detail-list dt{margin: 0;color: var(--sdi-muted);font-size: var(--sdi-text-body-sm)}.sdi-detail-list dd{margin: 0;color: var(--sdi-heading);font-weight: var(--sdi-weight-medium)}/* A term link is the whole value,not a link inside a sentence,so 2.5.8's
   Inline exception does not reach it. */
.sdi-detail-list dd a {
	display: inline-flex;
	align-items: center;
	min-height: 1.5rem;
	color: var(--sdi-accent);
}

/* ══ Read-only value ═══════════════════════════════════════════════════
 *
 * A username that cannot be changed. Rendered as text rather than a disabled
 * input: a greyed-out field still looks like something you could click into,
 * and discovering otherwise takes a support ticket.
 */

.sdi-static-value {
	margin: 0;
	padding: 0.7em 0;
	color: var(--sdi-heading);
	font-family: var(--sdi-font-ui);
	font-weight: var(--sdi-weight-medium);
}

/* ══ Copyable field ════════════════════════════════════════════════════ */

.sdi-copyfield { margin: var(--sdi-space-md) 0 0; }
.sdi-copyfield .sdi-input { font-family: var(--sdi-font-mono); font-size: var(--sdi-text-body-sm); }

/* ══ Portal progress meta ══════════════════════════════════════════════ */

.sdi-progress__meta {
	display: flex;
	justify-content: space-between;
	gap: var(--sdi-space-sm);
	color: var(--sdi-muted);
	font-size: var(--sdi-text-caption);
}

/* ══ Directory search ══════════════════════════════════════════════════ */

.sdi-directory-search-band {
	padding-block: var(--sdi-space-lg);
	background: var(--sdi-surface);
	border-bottom: 1px solid var(--sdi-line);
}

.sdi-directory-search {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sdi-space-2xs);
	max-width: 44rem;
}

/*
 * The field takes the slack and the button keeps its intrinsic width. A
 * fixed split would leave either a stubby field on a wide screen or a
 * squeezed button on a narrow one.
 */
.sdi-directory-search__field { flex: 1 1 16rem; }
.sdi-directory-search__submit { flex: 0 0 auto; }

/* ══ Chips ═════════════════════════════════════════════════════════════
 *
 * Locations and sub-category filters. Lighter than a tile because there are
 * more of them and they are a way through rather than a destination.
 */

.sdi-chip-list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sdi-space-2xs);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sdi-chip-list--filters { margin-bottom: var(--sdi-space-lg); }

.sdi-chip {
	display: inline-flex;
	align-items: center;
	gap: var(--sdi-space-3xs);
	min-height: 1.5rem;
	padding: 0.4em 0.9em;
	background: var(--sdi-surface);
	border: 1px solid var(--sdi-line-interactive);
	border-radius: var(--sdi-radius-pill);
	color: var(--sdi-heading);
	font-family: var(--sdi-font-ui);
	font-size: var(--sdi-text-body-sm);
	text-decoration: none;
	transition: background var(--sdi-duration) var(--sdi-ease), border-color var(--sdi-duration) var(--sdi-ease);
}

.sdi-chip:hover { background: var(--sdi-surface-alt); border-color: var(--sdi-primary); }

.sdi-chip__count {
	color: var(--sdi-muted);
	font-size: var(--sdi-text-caption);
	font-variant-numeric: tabular-nums;
}

/* ══ Listing card ══════════════════════════════════════════════════════ */

.sdi-card__media-link { display: block; }

.sdi-card__location {
	display: flex;
	align-items: center;
	gap: var(--sdi-space-3xs);
	margin: 0;
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-sm);
}

/*
 * A drawn pin rather than an icon font: one fewer request, and it inherits
 * currentColor so it follows the text it sits beside.
 */
.sdi-card__location-icon {
	flex: 0 0 auto;
	width: 0.7rem;
	height: 0.7rem;
	border: 1.5px solid currentColor;
	border-radius: 50% 50% 50% 0;
	transform: rotate(-45deg);
}

.sdi-card__excerpt { margin: var(--sdi-space-2xs) 0 0; color: var(--sdi-body); font-size: var(--sdi-text-body-sm); }

/* ══ Single listing ════════════════════════════════════════════════════ */

.sdi-listing__location {
	display: flex;
	align-items: center;
	gap: var(--sdi-space-3xs);
	margin: var(--sdi-space-sm) 0 0;
	color: var(--sdi-muted);
	font-size: var(--sdi-text-body-lg);
}

.sdi-listing__layout { display: grid; gap: var(--sdi-space-xl); align-items: start; }

@media (min-width: 60rem) {
	.sdi-listing__layout { grid-template-columns: minmax(0, 1fr) 20rem; }

	/* The detail panel follows the reader down a long description. */
	.sdi-listing__aside { position: sticky; top: 5.5rem; }
}

.sdi-listing__main { min-width: 0; }
.sdi-listing__media { margin-bottom: var(--sdi-space-lg); }

.sdi-listing__aside { display: flex; flex-direction: column; gap: var(--sdi-space-md); }

/* ══ Stacked steps ═════════════════════════════════════════════════════
 *
 * The submission page runs its three steps down a column beside the
 * requirements list rather than across the page.
 */

.sdi-steps--stacked { grid-template-columns: 1fr; gap: var(--sdi-space-md); }

/* Four steps across rather than three and an orphan on the next row. */
/*
 * Four steps across, or two rows of two — never three and a stray. A
 * sequence that drops its last step onto a row of its own reads as though
 * the fourth were an afterthought rather than part of the process.
 */
.sdi-steps--four { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 64rem) {
	.sdi-steps--four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 30rem) {
	.sdi-steps--four { grid-template-columns: 1fr; }
}

.sdi-submit__panel { margin-top: var(--sdi-space-xl); }

/* ══ Footer signup ═════════════════════════════════════════════════════
 *
 * Rendered only when a provider has attached a real form to
 * `sdi_theme_newsletter_form`. With none attached the footer has no signup
 * in it at all, so these rules style whatever the provider echoes rather
 * than a field the theme owns — hence the descendant selectors on input and
 * button, which are the only two elements every provider has in common.
 */

.site-footer__signup {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sdi-space-sm) var(--sdi-space-lg);
	margin-bottom: var(--sdi-space-lg);
	padding-bottom: var(--sdi-space-lg);
	border-bottom: 1px solid var(--sdi-line);
}

.site-footer__signup-title {
	margin: 0;
	font-size: var(--sdi-text-h5);
	color: var(--sdi-heading);
}

.site-footer__signup-form { flex: 1 1 20rem; min-width: 0; }

/*
 * A provider echoes its own markup, and the plainest thing it can echo is an
 * unstyled `<input>` and `<button>`. Left alone, the button renders in the
 * browser's default grey — #efefef against a navy footer,which is how the * polish audit found this. Styling the bare elements means whatever arrives * looks like the rest of the site;a provider that ships its own classes * simply overrides these. */ .site-footer__signup-form input[type="email"],.site-footer__signup-form input[type="text"]{min-height: 2.75rem;padding: var(--sdi-space-2xs) var(--sdi-space-xs);background: var(--sdi-surface);color: var(--sdi-body);border: 1px solid var(--sdi-line-interactive);border-radius: var(--sdi-radius-sm);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-body-sm)}.site-footer__signup-form button,.site-footer__signup-form input[type="submit"]{min-height: 2.75rem;padding: var(--sdi-space-2xs) var(--sdi-space-sm);background: var(--sdi-accent);color: var(--sdi-navy-900);border: 0;border-radius: var(--sdi-radius-sm);font-family: var(--sdi-font-ui);font-size: var(--sdi-text-body-sm);font-weight: var(--sdi-weight-semibold);cursor: pointer;transition: background var(--sdi-duration) var(--sdi-ease)}.site-footer__signup-form button:hover,.site-footer__signup-form input[type="submit"]:hover{background: var(--sdi-on-invert)}/* ══ Elementor-built pages ═════════════════════════════════════════════ * * A page laid out in Elementor supplies its own structure,so the theme * gets out of the way: no reading measure,no container,no section * padding. Without this the theme's 68ch prose column squeezed a full-width
 * hero into 692px of a 1440px screen and every section below it inherited
 * the squeeze.
 *
 * The theme's own section components still work inside an Elementor * container — `.sdi-container` keeps its max-width and gutters — so a page * can mix SDI section widgets with Elementor's own.
 */

.sdi-elementor-content { margin: 0; }
.sdi-elementor-content > .entry-content { max-width: none; }

/*
 * An SDI section widget is a full-bleed band. Elementor wraps each widget in
 * a div inside a boxed container, so the band is told to ignore that box and
 * span the viewport, while its inner `.sdi-container` still holds the
 * content to the site's measure and gutters. */ .elementor-widget[class*="elementor-widget-sdi-"]{width: 100%}.elementor-widget[class*="elementor-widget-sdi-"] > .elementor-widget-container > .sdi-section,.elementor-widget[class*="elementor-widget-sdi-"] > .elementor-widget-container > .sdi-hero{width: 100vw;max-width: 100vw;margin-inline: calc(50% - 50vw)}/* * Elementor's own widgets, in the theme's voice. * * The page layouts are built from Heading,Text Editor,Button,Icon List and * Accordion widgets. Left alone they render in whatever Elementor's Kit says,
 * and a Kit that has not had `sdi-kit-settings.json` imported still has an
 * answer: Roboto. Every heading on a converted page came out in Elementor's * default brand font beside the theme's own serif ones, and read as two
 * different sites stitched together.
 *
 * ## Why these selectors are the shape they are
 *
 * Elementor writes `.elementor-widget-heading .elementor-heading-title` for
 * the Kit's global typography — two classes. A `:where()` rule,which is what * this was first written as,has no specificity at all and lost to it * silently. So each rule here carries three classes,which beats the Kit's
 * two.
 *
 * Three and not more, because a font picked on one widget in the panel is
 * written as `.elementor-{page} .elementor-element.elementor-element-{id}
 * .elementor-heading-title` — four classes. Whatever an editor chooses still
 * wins. This sets the default; it does not lock anything.
 */

.elementor-widget.elementor-widget-heading .elementor-heading-title:is(h1, h2, h3, h4, h5, h6),
.elementor-widget.elementor-widget-n-accordion .e-n-accordion-item-title-text {
	font-family: var(--sdi-font-display);
	letter-spacing: -0.01em;
}

/*
 * An eyebrow is a Heading widget rendered as a div, so it is deliberately not
 * in the rule above: small caps in a serif face read as a mistake.
 */
.elementor-widget.elementor-widget-heading .elementor-heading-title:is(div, span, p),
.elementor-widget.elementor-widget-text-editor .elementor-widget-container,
.elementor-widget.elementor-widget-icon-list .elementor-icon-list-text,
.elementor-widget.elementor-widget-button .elementor-button {
	font-family: var(--sdi-font-body);
}

/* The theme's own link treatment,for a link inside Elementor's prose. */
.elementor-widget.elementor-widget-text-editor .elementor-widget-container a,
.elementor-widget.elementor-widget-heading .elementor-heading-title a {
	color: inherit;
	text-decoration-color: var(--sdi-brass-500);
	text-underline-offset: 0.18em;
}

.elementor-widget.elementor-widget-heading .elementor-heading-title a:hover { color: var(--sdi-brass-700); }

/*
 * Elementor's Posts widget,on the news band. Its card is Elementor's, its
 * edges are the theme's,so it sits in the same family as the containers * beside it rather than looking imported. */ .elementor-widget.elementor-widget-posts .elementor-post{border: 1px solid var(--sdi-line);border-radius: var(--sdi-radius-lg);background: var(--sdi-surface);overflow: hidden}.elementor-widget.elementor-widget-posts .elementor-post__title,.elementor-widget.elementor-widget-posts .elementor-post__title a{font-family: var(--sdi-font-display)}/* * Cards built from Elementor containers. * * The lift is a class rather than Elementor hover settings because it moves * three properties together — a container's hover controls cover colour but
 * not transform, so half of this could not be expressed in the panel.
 *
 * `.sdi-e-card` is an ordinary CSS class on the container, visible and
 * removable in Advanced → CSS Classes, so a card that should sit still can.
 */
.sdi-e-card {
	transition:
		transform var(--sdi-duration-fast) var(--sdi-ease-out),
		box-shadow var(--sdi-duration-fast) var(--sdi-ease-out),
		border-color var(--sdi-duration-fast) var(--sdi-ease-out);
}

.sdi-e-card:hover {
	transform: translateY(-4px);
	border-color: var(--sdi-brass-500);
	box-shadow: 0 12px 28px rgb(10 32 62 / 12%);
}

/* A card that is a link should say so on hover, wherever the pointer is. */
.sdi-e-card:hover .elementor-widget-heading .elementor-heading-title a { color: var(--sdi-brass-700); }

/* Buttons lift with the same timing, so the page has one physics. */
.elementor-widget.elementor-widget-button .elementor-button {
	transition:
		transform var(--sdi-duration-fast) var(--sdi-ease-out),
		box-shadow var(--sdi-duration-fast) var(--sdi-ease-out),
		background-color var(--sdi-duration-fast) var(--sdi-ease-out),
		color var(--sdi-duration-fast) var(--sdi-ease-out);
}

.elementor-widget.elementor-widget-button .elementor-button:hover {
	transform: translateY(-2px);
	box-shadow: 0 8px 20px rgb(10 32 62 / 18%);
}

/* Icon-list rows warm up under the pointer where the row is a link. */
.elementor-widget.elementor-widget-icon-list .elementor-icon-list-item > a {
	transition: color var(--sdi-duration-fast) var(--sdi-ease-out);
}

.elementor-widget.elementor-widget-icon-list .elementor-icon-list-item > a:hover { color: var(--sdi-brass-700); }

/*
 * Nobody who has asked for less motion gets any of it. Elementor's own * entrance animations are covered too,which its CSS does not do itself. */ @media (prefers-reduced-motion: reduce){.sdi-e-card,.sdi-e-card:hover,.elementor-widget.elementor-widget-button .elementor-button,.elementor-widget.elementor-widget-button .elementor-button:hover{transform: none !important;transition: none !important}.elementor-invisible{visibility: visible !important}.animated{animation: none !important}}/* * The header menu collapses earlier than Elementor allows. * * Eight primary items,a logo and two account buttons come to about 1240px. * Elementor's Nav Menu collapses to its hamburger at a breakpoint chosen from
 * the active ones, and `laptop` is explicitly excluded from that list, so the
 * widest it offers is tablet — 1024px. Between 1025px and about 1240px the bar
 * therefore had more in it than would fit and the account buttons dropped to a
 * second row: not broken, but not what a small laptop should show.
 *
 * The cutoff is 1300px rather than the 1240px the arithmetic needs, because
 * the arithmetic depends on how long the client makes the menu labels. A
 * breakpoint that holds only for the labels shipped today is one that breaks
 * the first time somebody renames a page.
 *
 * These two rules extend Elementor's own tablet behaviour up to 1300px,and * only inside this header. They mirror the rules in * `elementor-pro/assets/css/widget-nav-menu.min.css` exactly — hide the * horizontal menu,stop hiding the toggle — so the widget behaves as it * already knows how to,one breakpoint wider. * * Remove the `.sdi-e-header` class from the header container and Elementor's
 * own 1024px breakpoint is back.
 */
@media (min-width: 1025px) and (max-width: 1300px) {

	.sdi-e-header .elementor-nav-menu--dropdown-tablet .elementor-nav-menu--main { display: none; }

	.sdi-e-header .elementor-nav-menu--dropdown-tablet .elementor-menu-toggle { display: flex; }
}