/**
 * @file
 * tpemis_portal app-shell + token bridge (#854 / app-shell layout).
 *
 * Two jobs:
 *  1. Token bridge - map the tpemis_ui design-system tokens (--tp-*) onto the
 *     Olivero CSS variables the base theme already cascades from, so the whole
 *     theme adopts the brand palette without rewriting Olivero's CSS. Olivero
 *     derives its entire primary colour scale from three HSL root variables, so
 *     overriding those three recolours links, buttons and accents brand-wide.
 *  2. App-shell - a sleek, app-like page frame (slim top nav, clean content
 *     canvas, designed footer) that replaces Olivero's region-heavy chrome so
 *     the portal stops looking like stock Drupal. Drupal clutter (breadcrumb,
 *     local-task tabs) is suppressed on the applicant-facing portal.
 *
 * Token values resolve from tpemis_ui/tokens (base sheet + active brand
 * overlay); this file only references them, so a brand change needs no edit
 * here.
 */

/* 1. Token bridge: recolour Olivero from the brand tokens. ------------------ */
:root {
  /* Olivero computes --color--primary-* from these three; hue + saturation
     come straight from the brand overlay. Lightness is unitless here because
     Olivero multiplies it by 1% in calc(); it mirrors
     --tp-color-brand-primary-lightness (26%). */
  --color--primary-hue: var(--tp-color-brand-primary-hue, 217);
  --color--primary-saturation: var(--tp-color-brand-primary-saturation, 60%);
  --color--primary-lightness: 26;
}

/* 2. App-shell frame. ------------------------------------------------------- */
body {
  background: var(--tp-color-surface-subtle, #f4f6f9);
  color: var(--tp-color-text-default, #1a2230);
  font-family: var(--tp-font-family-sans, system-ui, sans-serif);
}

.tp-shell {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* Slim, clean top navigation (replaces Olivero's gradient header). A thin brand
   accent sits along the very top edge (design reference). */
.tp-topnav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--tp-color-surface-default, #fff);
  border-top: 3px solid var(--tp-color-primary, #1b3a6b);
  border-bottom: 1px solid var(--tp-color-border-default, #e3e8ef);
  box-shadow: 0 1px 3px rgba(16, 24, 40, 0.04);
}
.tp-topnav__inner {
  display: flex;
  align-items: center;
  gap: var(--tp-spacing-4, 1rem);
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--tp-spacing-5, 1.5rem);
  min-height: 64px;
}
/* Hamburger: hidden on desktop, shown on mobile (see media query). */
.tp-topnav__hamburger {
  display: none;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.tp-topnav__hamburger-bar,
.tp-topnav__hamburger-bar::before,
.tp-topnav__hamburger-bar::after {
  display: block;
  width: 22px;
  height: 2px;
  margin: 0 auto;
  background: var(--tp-color-text-default, #1a2230);
}
/* content only applies to pseudo-elements, not the real bar element. */
.tp-topnav__hamburger-bar::before,
.tp-topnav__hamburger-bar::after {
  content: "";
}
.tp-topnav__hamburger-bar::before {
  transform: translateY(-7px);
}
.tp-topnav__hamburger-bar::after {
  transform: translateY(5px);
}
.tp-topnav__brand {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}
/* Reset the carried-over Olivero branding block into a compact lockup. */
.tp-topnav__brand .site-branding,
.tp-topnav__brand .block-system-branding-block {
  display: flex;
  align-items: center;
  gap: var(--tp-spacing-3, 0.75rem);
  margin: 0;
  padding: 0;
}
.tp-topnav__brand img {
  height: 40px;
  width: auto;
}
.tp-topnav__brand .site-branding__name,
.tp-topnav__brand .site-branding__name a {
  font-size: var(--tp-font-size-lg, 1.125rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
  text-decoration: none;
  line-height: 1.1;
}
.tp-topnav__brand .site-branding__slogan {
  font-size: var(--tp-font-size-xs, 0.75rem);
  color: var(--tp-color-text-muted, #5b6473);
}

/* Primary menu sits centre/left of the actions, horizontal and quiet. */
.tp-topnav__menu {
  flex: 1 1 auto;
  display: flex;
  justify-content: center;
}
.tp-topnav__menu ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-spacing-5, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.tp-topnav__menu a {
  color: var(--tp-color-text-muted, #5b6473);
  font-weight: var(--tp-font-weight-medium, 500);
  text-decoration: none;
}
.tp-topnav__menu a:hover,
.tp-topnav__menu a.is-active {
  color: var(--tp-color-primary, #1b3a6b);
}

.tp-topnav__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--tp-spacing-3, 0.75rem);
}
.tp-topnav__signin {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--tp-spacing-4, 1rem);
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-primary, #1b3a6b);
  color: #fff;
  font-weight: var(--tp-font-weight-bold, 700);
  text-decoration: none;
}
.tp-topnav__signin:hover {
  background: var(--tp-color-brand-primary-light, #2a6496);
}

/* Account dropdown (design system: dropdown-menu). The "My account" button
   opens a panel with account actions, the Secretariat staff menu (when the user
   has access) and log out. Mobile renders it as an action-menu sheet. */
.tp-account {
  position: relative;
}
.tp-account__trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-spacing-2, 0.5rem);
  min-height: 40px;
  padding: 0 var(--tp-spacing-4, 1rem);
  border: 1px solid var(--tp-color-primary, #1b3a6b);
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-primary, #1b3a6b);
  color: #fff;
  font-family: inherit;
  font-weight: var(--tp-font-weight-bold, 700);
  font-size: var(--tp-font-size-md, 1rem);
  cursor: pointer;
}
.tp-account__trigger:hover {
  background: var(--tp-color-brand-primary-light, #2a6496);
}
.tp-account__chevron {
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
  transition: transform 0.15s ease;
}
.tp-account__trigger[aria-expanded="true"] .tp-account__chevron {
  transform: rotate(-135deg) translateY(-2px);
}
.tp-account__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 200;
  min-width: 240px;
  padding: var(--tp-spacing-2, 0.5rem);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #e3e8ef);
  border-radius: var(--tp-border-radius-lg, 12px);
  box-shadow: 0 12px 32px rgba(16, 24, 40, 0.16);
}
.tp-account__menu[hidden] {
  display: none;
}
.tp-account__group-label {
  margin: 0;
  padding: var(--tp-spacing-2, 0.5rem) var(--tp-spacing-3, 0.75rem) var(--tp-spacing-1, 0.25rem);
  font-size: var(--tp-font-size-xs, 0.75rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--tp-color-text-muted, #8a93a3);
}
.tp-account__item,
.tp-account__nav a {
  display: flex;
  align-items: center;
  gap: var(--tp-spacing-3, 0.75rem);
  padding: var(--tp-spacing-2, 0.5rem) var(--tp-spacing-3, 0.75rem);
  border-radius: var(--tp-border-radius-md, 8px);
  color: var(--tp-color-text-default, #1a2230);
  font-size: var(--tp-font-size-sm, 0.9375rem);
  text-decoration: none;
}
.tp-account__item:hover,
.tp-account__item:focus-visible,
.tp-account__nav a:hover,
.tp-account__nav a:focus-visible {
  background: var(--tp-color-surface-subtle, #f4f6f9);
  outline: none;
}
.tp-account__item-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-account__sep {
  height: 1px;
  margin: var(--tp-spacing-2, 0.5rem) 0;
  background: var(--tp-color-border-default, #eef1f5);
}
/* The Secretariat menu renders as a Drupal menu inside the panel. */
.tp-account__nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (max-width: 600px) {
  /* Action-menu style: a sheet anchored under the bar, full bleed with gutters. */
  .tp-account__menu {
    position: fixed;
    left: var(--tp-spacing-3, 0.75rem);
    right: var(--tp-spacing-3, 0.75rem);
    top: 60px;
    min-width: 0;
  }
}

/* Main content canvas: centred, generous whitespace. */
.tp-main {
  flex: 1 0 auto;
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: var(--tp-spacing-7, 2.5rem) var(--tp-spacing-5, 1.5rem) var(--tp-spacing-8, 3rem);
}
/* Let content fill the main column: neutralise Olivero's content-medium/narrow
   inner max-width so regions/blocks span the full width of the content column
   (the interior prose card keeps its own readable measure separately). */
.tp-main .layout--content-medium,
.tp-main .layout--pass--content-medium > *,
.tp-main .layout--content-narrow,
.tp-main .layout--pass--content-narrow > * {
  max-width: none;
  margin-inline: 0;
}
/* Olivero also places every block into a narrow grid column of the 14-column
   .region--content grid (grid-column 3/13, ~840px), which leaves large empty
   margins left and right on big screens while the header/footer use the full
   ~1200px. Span all content-region blocks (the main content block, the public
   notice, etc.) across the whole region grid so every block matches the
   header/footer width and the page reads consistently. */
.tp-main .region--content > .block {
  grid-column: 1 / -1;
}
/* Tighter side padding on small screens so borders/padding stop eating space. */
@media (max-width: 768px) {
  .tp-main {
    padding: var(--tp-spacing-4, 1rem) var(--tp-spacing-2, 0.5rem) var(--tp-spacing-6, 2rem);
  }
}

/* Standard page-heading band (.tp-page-hero): a full-bleed gradient strip with
   the breadcrumb trail and the page title, mirroring the account-profile hero.
   Rendered above .tp-main on every front-end page except the front page, the
   profile and the auth pages; on these pages the in-content page title block is
   hidden (the band carries the title). Token-driven so it tracks the brand. */
.tp-page-hero {
  background:
    radial-gradient(1200px 360px at 85% -20%, rgba(255, 255, 255, 0.10), transparent),
    linear-gradient(135deg, var(--tp-color-primary, #1b3a6b) 0%, #2c2a6b 60%, #3b2f8f 100%);
  color: #fff;
}
.tp-page-hero__inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--tp-spacing-7, 2.5rem) var(--tp-spacing-5, 1.5rem);
}
/* Navigation row: Back control + breadcrumb on one line. The back button sits
   inline at the start, before the breadcrumb (before "Home"). */
.tp-page-hero__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tp-spacing-3, 0.75rem);
}

/* Global app-style Back control in the heading band. Hidden by default;
   back-button.js adds .is-visible only when there is a same-origin page to
   return to, so it never appears as a dead-end on the first screen. A
   compact translucent light pill that reads on the dark gradient and sits
   inline with the breadcrumb. */
.tp-page-hero__back {
  display: none;
  align-items: center;
  gap: var(--tp-spacing-1, 0.25rem);
  margin: 0;
  padding: var(--tp-spacing-1, 0.25rem) var(--tp-spacing-3, 0.75rem);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--tp-border-radius-pill, 999px);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: var(--tp-font-size-sm, 0.875rem);
  font-weight: var(--tp-font-weight-medium, 500);
  line-height: 1.4;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.tp-page-hero__back.is-visible {
  display: inline-flex;
}
.tp-page-hero__back:hover {
  background: rgba(255, 255, 255, 0.22);
  border-color: rgba(255, 255, 255, 0.6);
}
.tp-page-hero__back:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.tp-page-hero__back-icon {
  font-size: 1.1em;
  line-height: 1;
}

.tp-page-hero__crumb {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-spacing-2, 0.5rem);
  align-items: center;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: rgba(255, 255, 255, 0.7);
}
.tp-page-hero__crumb a {
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
}
.tp-page-hero__crumb a:hover {
  text-decoration: underline;
}
.tp-page-hero__title {
  margin: var(--tp-spacing-3, 0.75rem) 0 0;
  /* Scales down further on small screens (lower floor) so a long page title
     does not dominate the mobile viewport. */
  font-size: clamp(1.4rem, 5vw, 2.5rem);
  line-height: 1.15;
  color: #fff;
}
/* On hero pages the band carries the title, so hide the in-content title block
   and tighten the main canvas top padding under the band. */
.tp-has-page-hero .block-page-title-block {
  display: none;
}
.tp-has-page-hero .tp-main {
  padding-top: var(--tp-spacing-6, 2rem);
}
@media (max-width: 768px) {
  .tp-page-hero__inner {
    padding: var(--tp-spacing-5, 1.5rem) var(--tp-spacing-4, 1rem);
  }
}

/* Global footer (design.tpgroupsl.com/tpemis/u/usl): up to three link columns
   (Academics, Admissions, Contact), an accreditation strip, and a legal bottom
   bar. Content is config-driven (tp_footer); see layout/footer.html.twig. */
.tp-footer {
  margin-top: auto;
  background: var(--tp-color-surface-default, #fff);
  border-top: 1px solid var(--tp-color-border-default, #e3e8ef);
  font-family: var(--tp-font-family-sans, system-ui, sans-serif);
}
.tp-footer__main {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--tp-spacing-8, 3rem) var(--tp-spacing-5, 1.5rem);
}
.tp-footer__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--tp-spacing-7, 2.5rem);
}
.tp-footer__col-head {
  margin: 0 0 var(--tp-spacing-3, 0.75rem);
  font-size: var(--tp-font-size-xs, 0.75rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--tp-color-text-muted, #8a93a3);
}
.tp-footer__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--tp-spacing-2, 0.5rem);
}
.tp-footer__list a {
  color: var(--tp-color-secondary, #2a6496);
  font-size: var(--tp-font-size-sm, 0.9375rem);
  text-decoration: none;
}
.tp-footer__list a:hover {
  text-decoration: underline;
}
.tp-footer__contact-item {
  color: var(--tp-color-text-muted, #5b6473);
  font-size: var(--tp-font-size-sm, 0.9375rem);
}
/* Accreditation strip. */
.tp-footer__accred {
  background: var(--tp-color-accent-subtle, #fdf6e9);
  border-top: 1px solid var(--tp-color-border-default, #eef1f5);
}
.tp-footer__accred-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--tp-spacing-6, 2rem);
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--tp-spacing-3, 0.875rem) var(--tp-spacing-5, 1.5rem);
}
.tp-footer__accred-item {
  font-size: var(--tp-font-size-xs, 0.8125rem);
  color: var(--tp-color-text-default, #5b6473);
}
/* Legal bottom bar. */
.tp-footer__legal {
  border-top: 1px solid var(--tp-color-border-default, #eef1f5);
}
.tp-footer__legal-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tp-spacing-3, 0.75rem);
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--tp-spacing-4, 1.25rem) var(--tp-spacing-5, 1.5rem);
}
.tp-footer__copy {
  margin: 0;
  font-size: var(--tp-font-size-xs, 0.8125rem);
  color: var(--tp-color-text-muted, #8a93a3);
}
.tp-footer__legal-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-spacing-5, 1.25rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.tp-footer__legal-links a {
  font-size: var(--tp-font-size-xs, 0.8125rem);
  color: var(--tp-color-text-muted, #5b6473);
  text-decoration: none;
}
.tp-footer__legal-links a:hover {
  color: var(--tp-color-primary, #1b3a6b);
}
@media (max-width: 900px) {
  .tp-footer__cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .tp-footer__legal-inner {
    flex-direction: column;
    align-items: flex-start;
  }
}
@media (max-width: 480px) {
  .tp-footer__cols {
    grid-template-columns: 1fr;
  }
}

/* 3. Suppress stock-Drupal clutter on the applicant portal. ----------------- */
/* Breadcrumb and local-task/action chrome read as "admin Drupal" on a public
   portal; the page title is hidden on the front page (the hero owns it). */
.tp-main .breadcrumb,
.tp-main nav.tabs,
.tp-main .block-local-tasks-block,
.tp-main .block-local-actions-block,
.path-frontpage .tp-main .block-page-title-block {
  display: none;
}
/* The front page is a node with an empty body - all marketing lives in the hero
   section above - so its main block renders as an empty card. Hide it and drop
   the now-empty main region's padding so there is no blank gap above the footer.
   Scoped to the system main block, so any blocks placed in the content region
   still render. */
.path-frontpage .tp-main .block-system-main-block {
  display: none;
}
.path-frontpage .tp-main {
  padding-block: 0;
}
/* Core contextual links (the admin "Quick edit / Configure block / Remove
   block / Edit menu" overlay) float over their block. In the slim sticky header
   the overlay covers the nav and actions for every admin pageview, so suppress
   it here. The header blocks/menus remain editable via Structure > Block layout
   and Structure > Menus. */
.tp-topnav .contextual {
  display: none !important;
}

/* 4. Auth pages (login/register/reset): clean, centred card. ---------------- */
/* The auth-card owns the heading and content, so strip the stock-Drupal page
   title and the deadline/content blocks and let the card fill a clean canvas
   below the nav (body.tp-auth-page set in tpemis_portal_preprocess_html). */
.tp-auth-page .tp-main {
  max-width: none;
  padding: 0;
}
.tp-auth-page .tp-main .block-page-title-block,
.tp-auth-page .tp-main .block-block-content {
  display: none;
}
.tp-auth-page .tp-auth {
  /* Fill the viewport below the 64px nav so the card sits centred. */
  min-height: calc(100dvh - 65px);
}

/* Form controls inside the auth card are styled site-wide by tpemis-forms.css
   (#884), scoped to .tp-main which includes the auth card. */

/* Neutralise inherited Olivero nav/branding CSS (navigation-base dependency
   and the carried menu template) so the menu is a flat horizontal row inside
   the slim bar rather than Olivero's dropdown header system. Scoped to the top
   nav; !important is needed to beat Olivero's high-specificity selectors. */
.tp-topnav__brand .site-branding,
.tp-topnav__brand .block-system-branding-block,
.tp-topnav__menu .primary-nav,
.tp-topnav__menu .primary-nav__menu,
.tp-topnav__menu nav {
  position: static !important;
  inset: auto !important;
  background: none !important;
  box-shadow: none !important;
  margin: 0 !important;
  padding: 0 !important;
  max-width: none !important;
  width: auto !important;
  /* Olivero gives .site-branding a 180px min-height (its tall header) which
     inflates the slim bar - collapse it so the row is ~64px. */
  min-height: 0 !important;
}
/* The branding inner wrapper carries vertical padding from Olivero; collapse it
   so the logo + name lockup sits compactly in the bar. */
.tp-topnav__brand .site-branding__inner {
  min-height: 0 !important;
  padding-block: 0 !important;
}
/* Stop the branding wrappers stretching to Olivero's inflated row height; center
   them at their own content height so the bar collapses to ~64px. */
.tp-topnav__brand,
.tp-topnav__brand .site-branding,
.tp-topnav__brand .site-branding__inner {
  align-self: center !important;
  height: auto !important;
}
/* Olivero adds ::before/::after pseudos to .site-branding and its inner that
   reserve the tall header height - remove them so the bar collapses to its
   content. */
.tp-topnav__brand .site-branding::before,
.tp-topnav__brand .site-branding::after,
.tp-topnav__brand .site-branding__inner::before,
.tp-topnav__brand .site-branding__inner::after {
  display: none !important;
}
/* Olivero pads the nav link inner span (36px top/bottom) to fill its tall
   header; collapse it so menu items match the slim bar. */
.tp-topnav__menu .primary-nav__menu-link-inner {
  padding: 0 !important;
  min-height: 0 !important;
}
.tp-topnav__menu .primary-nav__menu {
  display: flex !important;
  flex-wrap: wrap;
  gap: var(--tp-spacing-5, 1.5rem);
  list-style: none;
}
.tp-topnav__menu .primary-nav__menu-item {
  margin: 0 !important;
}
.tp-topnav__menu .primary-nav__menu-item,
.tp-topnav__menu .primary-nav__menu-link,
.tp-topnav__menu a {
  min-height: 0 !important;
}
.tp-topnav__menu .primary-nav__menu-link,
.tp-topnav__menu a {
  padding: 0 !important;
  border: 0 !important;
  font-size: var(--tp-font-size-md, 1rem) !important;
  color: var(--tp-color-text-muted, #5b6473) !important;
  background: none !important;
}
.tp-topnav__menu .primary-nav__menu-link::before,
.tp-topnav__menu .primary-nav__menu-link::after {
  display: none !important;
}
.tp-topnav__menu a:hover {
  color: var(--tp-color-primary, #1b3a6b) !important;
}

/* The public portal top bar shows only the main navigation. The primary_menu
   region also carries admin/staff blocks - the site search form and the
   Secretariat staff menu - that are visible only to privileged users; left in
   the flat single-row bar they render expanded and break the header (the bar
   grows tall and shoves the brand down). Keep them out of the public top nav;
   staff reach those tools via the admin toolbar/dashboard. */
.tp-topnav__menu > #block-tpemis-portal-search-form-narrow,
.tp-topnav__menu > #block-tpemis-portal-secretariatmenu-bar {
  display: none !important;
}

/* 5. Front-page hero. ------------------------------------------------------- */
.tp-hero {
  background:
    radial-gradient(1200px 400px at 85% -10%, rgba(255, 255, 255, 0.10), transparent),
    linear-gradient(135deg, var(--tp-color-brand-primary, #1b3a6b) 0%, #2c2a6b 60%, #3b2f8f 100%);
  color: #fff;
}
.tp-hero__inner {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: var(--tp-spacing-7, 2.5rem);
  align-items: center;
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--tp-spacing-8, 3rem) var(--tp-spacing-5, 1.5rem);
}
.tp-hero__eyebrow {
  display: inline-block;
  margin: 0 0 var(--tp-spacing-3, 0.75rem);
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  font-size: var(--tp-font-size-sm, 0.875rem);
  font-weight: var(--tp-font-weight-bold, 700);
  letter-spacing: 0.02em;
}
.tp-hero__title {
  margin: 0 0 var(--tp-spacing-4, 1rem);
  font-size: clamp(2rem, 4vw, 3.25rem);
  line-height: 1.05;
  font-weight: var(--tp-font-weight-bold, 700);
  /* Explicit: a global h1 rule sets a dark colour that would otherwise win over
     the inherited white on the dark hero. */
  color: #fff;
}
.tp-hero__subtitle {
  margin: 0 0 var(--tp-spacing-6, 2rem);
  max-width: 40ch;
  font-size: var(--tp-font-size-lg, 1.125rem);
  color: rgba(255, 255, 255, 0.82);
}
.tp-hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-spacing-3, 0.75rem);
}
.tp-hero__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0 var(--tp-spacing-5, 1.5rem);
  border-radius: var(--tp-border-radius-md, 8px);
  font-weight: var(--tp-font-weight-bold, 700);
  text-decoration: none;
}
.tp-hero__btn--primary {
  background: var(--tp-color-brand-accent, #e8a020);
  color: #fff;
}
.tp-hero__btn--primary:hover,
.tp-hero__btn--primary:focus-visible {
  background: var(--tp-color-brand-accent-light, #f5c15a);
  /* Keep the label white over the global a:hover colour, which would otherwise
     drop contrast on the dark accent background. */
  color: #fff;
}
.tp-hero__btn--ghost {
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.35);
}
.tp-hero__btn--ghost:hover {
  background: rgba(255, 255, 255, 0.18);
}
.tp-hero__meta {
  margin: var(--tp-spacing-6, 2rem) 0 0;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: rgba(255, 255, 255, 0.65);
}
.tp-hero__visual {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  min-height: 260px;
  padding: var(--tp-spacing-5, 1.5rem);
  border-radius: var(--tp-border-radius-lg, 16px);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.12));
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.tp-hero__visual-label {
  position: relative;
  z-index: 1;
  font-size: var(--tp-font-size-xs, 0.75rem);
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.7);
}
/* With a real campus image, the box becomes a photo frame: the image covers it
   and a bottom scrim keeps the label legible. */
.tp-hero__visual--image {
  position: relative;
  overflow: hidden;
  padding: var(--tp-spacing-4, 1rem);
  background: none;
}
.tp-hero__visual-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tp-hero__visual--image::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(16, 24, 40, 0.55));
}
.tp-hero__visual--image .tp-hero__visual-label {
  color: #fff;
}
@media (max-width: 900px) {
  .tp-hero__inner {
    grid-template-columns: 1fr;
  }
  .tp-hero__visual {
    min-height: 160px;
  }
}

/* 6. Front-page content sections (countdown + pick-a-path). ----------------- */
.tp-front__inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--tp-spacing-7, 2.5rem) var(--tp-spacing-5, 1.5rem);
}

/* Applications-open card with countdown. */
.tp-deadline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tp-spacing-5, 1.5rem);
  margin-block-end: var(--tp-spacing-8, 3rem);
  padding: var(--tp-spacing-5, 1.5rem) var(--tp-spacing-6, 2rem);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #e3e8ef);
  border-radius: var(--tp-border-radius-lg, 16px);
  box-shadow: 0 8px 30px rgba(16, 24, 40, 0.06);
}
.tp-deadline__status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 var(--tp-spacing-1, 0.25rem);
  font-size: var(--tp-font-size-sm, 0.875rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--tp-color-brand-accent, #e8a020);
}
.tp-deadline__dot {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--tp-color-brand-accent, #e8a020);
}
.tp-deadline__close {
  margin: 0 0 var(--tp-spacing-1, 0.25rem);
  font-size: var(--tp-font-size-lg, 1.125rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-deadline__note {
  margin: 0;
  max-width: 46ch;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-deadline__clock {
  display: flex;
  gap: var(--tp-spacing-3, 0.75rem);
}
.tp-deadline__unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 64px;
  padding: var(--tp-spacing-3, 0.75rem) var(--tp-spacing-2, 0.5rem);
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-surface-subtle, #f4f6f9);
}
.tp-deadline__unit span {
  font-size: var(--tp-font-size-2xl, 1.5rem);
  font-weight: var(--tp-font-weight-bold, 700);
  font-variant-numeric: tabular-nums;
  color: var(--tp-color-text-default, #1a2230);
}
.tp-deadline__unit small {
  font-size: var(--tp-font-size-xs, 0.75rem);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--tp-color-text-muted, #5b6473);
}

/* Section headings (centred by default; --left variant for data sections). */
.tp-section-head {
  margin: var(--tp-spacing-8, 3rem) 0 var(--tp-spacing-6, 2rem);
  text-align: center;
}
.tp-section-head--left {
  text-align: left;
}
.tp-section-head__eyebrow {
  margin: 0 0 var(--tp-spacing-2, 0.5rem);
  font-size: var(--tp-font-size-sm, 0.875rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--tp-color-brand-accent, #e8a020);
}
.tp-section-head__title {
  margin: 0 0 var(--tp-spacing-2, 0.5rem);
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-section-head__lede {
  margin: 0 auto;
  max-width: 60ch;
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-section-head--left .tp-section-head__lede {
  margin-inline: 0;
}
/* Visible "sample / verify before paying" notice (not just a code comment). */
.tp-note {
  display: inline-block;
  margin: var(--tp-spacing-2, 0.5rem) 0 0;
  padding: 0.35rem 0.75rem;
  border-radius: var(--tp-border-radius-sm, 6px);
  background: color-mix(in srgb, var(--tp-color-warning, #b7791f) 14%, transparent);
  color: var(--tp-color-warning, #8a5a00);
  font-size: var(--tp-font-size-sm, 0.875rem);
}

/* Pick-a-path channel cards. */
.tp-paths {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--tp-spacing-4, 1rem);
}
.tp-path {
  display: flex;
  flex-direction: column;
  gap: var(--tp-spacing-2, 0.5rem);
  padding: var(--tp-spacing-5, 1.5rem);
  border-radius: var(--tp-border-radius-lg, 16px);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #e3e8ef);
  text-decoration: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.tp-path:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 30px rgba(16, 24, 40, 0.10);
}
.tp-path--muted {
  opacity: 0.7;
}
.tp-path__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.tp-path__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--tp-border-radius-md, 8px);
  background: color-mix(in srgb, var(--tp-color-brand-accent, #e8a020) 18%, transparent);
  color: var(--tp-color-brand-accent, #e8a020);
  font-weight: var(--tp-font-weight-bold, 700);
}
.tp-path__badge {
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: var(--tp-font-size-xs, 0.75rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.tp-path__badge--rec,
.tp-path__badge--pop {
  background: var(--tp-color-brand-accent, #e8a020);
  color: #fff;
}
.tp-path__badge--phase {
  background: var(--tp-color-surface-subtle, #eef1f5);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-path__title {
  margin: var(--tp-spacing-2, 0.5rem) 0 0;
  font-size: var(--tp-font-size-lg, 1.125rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-path__kicker {
  margin: 0;
  font-size: var(--tp-font-size-xs, 0.75rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--tp-color-brand-accent, #e8a020);
}
.tp-path__text {
  margin: 0;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-path__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-spacing-2, 0.5rem);
}
.tp-tag {
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--tp-color-brand-accent, #e8a020) 14%, transparent);
  color: var(--tp-color-brand-accent, #e8a020);
  font-size: var(--tp-font-size-xs, 0.75rem);
}
.tp-tag--muted {
  background: var(--tp-color-surface-subtle, #eef1f5);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-path__go {
  margin-top: auto;
  padding-top: var(--tp-spacing-2, 0.5rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-brand-accent, #e8a020);
}
.tp-path__go--off {
  color: var(--tp-color-text-muted, #8a93a3);
}

/* Partner banks. */
.tp-banks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--tp-spacing-4, 1rem);
}
.tp-bank {
  display: flex;
  gap: var(--tp-spacing-3, 0.75rem);
  padding: var(--tp-spacing-4, 1rem);
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #e3e8ef);
}
.tp-bank__icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-surface-subtle, #eef1f5);
  font-size: 1.1rem;
}
.tp-bank__name {
  margin: 0;
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-bank__addr {
  margin: 0;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-bank__acct {
  margin: var(--tp-spacing-1, 0.25rem) 0 0;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-bank__acct code {
  font-family: var(--tp-font-family-mono, ui-monospace, monospace);
}

/* Payment rails. */
.tp-rails__group {
  margin: var(--tp-spacing-5, 1.5rem) 0 var(--tp-spacing-2, 0.5rem);
  font-size: var(--tp-font-size-xs, 0.75rem);
  font-weight: var(--tp-font-weight-bold, 700);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--tp-color-text-muted, #8a93a3);
}
.tp-rails {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--tp-spacing-3, 0.75rem);
}
.tp-rail {
  display: flex;
  align-items: center;
  gap: var(--tp-spacing-3, 0.75rem);
  padding: var(--tp-spacing-3, 0.75rem) var(--tp-spacing-4, 1rem);
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #e3e8ef);
}
.tp-rail__badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--tp-border-radius-md, 8px);
  background: color-mix(in srgb, var(--tp-color-brand-accent, #e8a020) 16%, transparent);
  color: var(--tp-color-brand-accent, #e8a020);
  font-size: var(--tp-font-size-xs, 0.75rem);
  font-weight: var(--tp-font-weight-bold, 700);
}
.tp-rail__name {
  margin: 0;
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-rail__type {
  margin: 0;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}

/* Stats. */
.tp-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--tp-spacing-4, 1rem);
}
.tp-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--tp-spacing-1, 0.25rem);
  padding: var(--tp-spacing-6, 2rem) var(--tp-spacing-4, 1rem);
  border-radius: var(--tp-border-radius-lg, 16px);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #e3e8ef);
}
.tp-stat__value {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-stat__label {
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}

/* Admission-criteria callout. */
.tp-callout {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tp-spacing-4, 1rem);
  margin-top: var(--tp-spacing-8, 3rem);
  padding: var(--tp-spacing-5, 1.5rem) var(--tp-spacing-6, 2rem);
  border-radius: var(--tp-border-radius-lg, 16px);
  background: color-mix(in srgb, var(--tp-color-brand-accent, #e8a020) 12%, var(--tp-color-surface-default, #fff));
  border: 1px solid color-mix(in srgb, var(--tp-color-brand-accent, #e8a020) 30%, transparent);
}
.tp-callout__title {
  margin: 0;
  font-size: var(--tp-font-size-lg, 1.125rem);
  font-weight: var(--tp-font-weight-bold, 700);
  color: var(--tp-color-text-default, #1a2230);
}
.tp-callout__sub {
  margin: 0;
  font-size: var(--tp-font-size-sm, 0.875rem);
  color: var(--tp-color-text-muted, #5b6473);
}
.tp-callout__btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
  padding: 0 var(--tp-spacing-5, 1.5rem);
  border-radius: var(--tp-border-radius-md, 8px);
  background: var(--tp-color-surface-default, #fff);
  border: 1px solid var(--tp-color-border-default, #d4dae3);
  color: var(--tp-color-text-default, #1a2230);
  font-weight: var(--tp-font-weight-bold, 700);
  text-decoration: none;
}

/* Mobile: compact single-row header (hamburger + brand + account) and a proper
   full-width vertical dropdown panel (JS sets .is-open / aria-expanded). */
@media (max-width: 768px) {
  .tp-topnav__inner {
    flex-wrap: wrap;
    align-items: center;
    gap: var(--tp-spacing-3, 0.75rem);
    min-height: 56px;
    padding-block: var(--tp-spacing-2, 0.5rem);
  }
  .tp-topnav__hamburger {
    display: block;
    order: 0;
    flex: 0 0 auto;
  }
  .tp-topnav__brand {
    order: 1;
    /* Shrink (truncate the name) rather than grow: growing to fill the row
       pushed the account button onto a second line. flex-grow 0 keeps the row
       single; the account button is pushed to the right edge via margin below. */
    flex: 0 1 auto;
    min-width: 0;
  }
  /* Olivero pins .site-branding to a 142px min-width (its tall-header lockup),
     which for a ~41px crest forced the account button onto a second row. Drop
     the min-width and let the branding shrink to its content so the row stays
     single. !important beats Olivero's navigation-base specificity. */
  .tp-topnav__brand .site-branding,
  .tp-topnav__brand .site-branding__inner {
    flex: 0 1 auto !important;
    min-width: 0 !important;
  }
  /* Keep the brand compact so the row fits: smaller crest, no slogan, and a
     smaller site name so the logo + name + My account stay on one line. */
  .tp-topnav__brand img {
    height: 32px;
  }
  .tp-topnav__brand .site-branding__slogan {
    display: none;
  }
  .tp-topnav__brand .site-branding__name,
  .tp-topnav__brand .site-branding__name a {
    font-size: var(--tp-font-size-sm, 0.875rem);
  }
  .tp-topnav__actions {
    order: 2;
    flex: 0 0 auto;
    /* Sit at the right edge of the single-line row. */
    margin-inline-start: auto;
  }
  /* Make the row truly single-line: the brand must be allowed to shrink and
     clip its (long) name rather than push the account button to a second row. */
  .tp-topnav__brand .site-branding__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Dropdown: full-width vertical panel below the bar; collapsed by default. */
  .tp-topnav__menu {
    order: 3;
    flex-basis: 100%;
    display: none;
    margin-top: var(--tp-spacing-2, 0.5rem);
    border-top: 1px solid var(--tp-color-border-default, #e3e8ef);
  }
  .tp-topnav__menu.is-open {
    display: block;
  }
  .tp-topnav__menu .primary-nav__menu,
  .tp-topnav__menu nav > ul {
    flex-direction: column !important;
    align-items: stretch;
    gap: 0 !important;
    width: 100%;
  }
  .tp-topnav__menu .primary-nav__menu-item,
  .tp-topnav__menu li {
    width: 100%;
    margin: 0 !important;
  }
  .tp-topnav__menu a {
    display: block !important;
    width: 100%;
    padding: var(--tp-spacing-3, 0.75rem) var(--tp-spacing-1, 0.25rem) !important;
    border-bottom: 1px solid var(--tp-color-border-default, #eef1f5);
  }
  /* Progressive enhancement: Drupal adds .js to <html> when JS runs, so with
     JS off reveal the menu and hide the (now non-functional) hamburger. */
  html:not(.js) .tp-topnav__menu {
    display: block;
  }
  html:not(.js) .tp-topnav__hamburger {
    display: none;
  }
}

/* Very small screens: drop the site name entirely so the crest (logo) and the
   My account button sit comfortably on one line with the hamburger. The crest
   alone still identifies the site. */
@media (max-width: 430px) {
  .tp-topnav__brand .site-branding__name {
    display: none;
  }
}
