/* =========================================================================
   MITCON Biopharma — UI layer ("Warm Clinic")
   Type scale, section rhythm and every component primitive the site uses.
   Colours, radii and shadows all come from theme.css; nothing here
   hardcodes a brand value.

   House rules:
     1. Warm cream is the ground, white is the card, pine carries meaning.
        Sunshine yellow appears two or three times a page as a highlight —
        never as a fifth colour in a grid.
     2. Sections alternate SHAPE, not just background. No page should show
        the same card grid twice in a row.
     3. Generous radius + soft warm shadow. This should feel approachable,
        not corporate.
     4. Type comes from the scale below. No arbitrary rem values in views.

   The bottom block restyles the legacy class names (.card, .section-title,
   .page-hero …) that the inner pages already use, so they inherit this
   system without their markup being rewritten.
   ========================================================================= */

/* ============================ TYPE SCALE ============================
   Measured off mitconskills.com: display headings are Montserrat 50px/60px
   at weight 400 — large but LIGHT. The weight is the point. Setting them
   bold is what made this site read as a brochure next to the sister site.
   Body is Poppins 16px/25px, meta 14px/21.9px.
   ==================================================================== */
.u-display {
    font-family: 'Montserrat', sans-serif; font-weight: 400;
    font-size: clamp(2.05rem, 3.9vw, 2.95rem); line-height: 1.2;
    letter-spacing: -.01em; color: var(--ink); margin: 0;
}
/* Measured on the reference: the hero headline is 50px at weight 500, while
   section headings sit at 38px and stay at 400. Ten section headings in this
   project use .u-display, which is the hero size, so they are pulled back to
   the section scale here rather than by editing every view. */
h1.u-display, .mc-hero h1, .faq-hero h1 { font-weight: 500; }
h2.u-display {
    font-size: clamp(1.6rem, 2.8vw, 2.25rem); line-height: 1.25; font-weight: 400;
}
.u-h2 {
    font-family: 'Montserrat', sans-serif; font-weight: 400;
    font-size: clamp(1.6rem, 2.8vw, 2.25rem); line-height: 1.25;
    letter-spacing: -.01em; color: var(--ink); margin: 0;
}
.u-h3 {
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    font-size: 1.19rem; line-height: 1.42; color: var(--ink); margin: 0;
}
.u-lead  { font-size: 1.06rem;  line-height: 1.62; color: var(--body); margin: 0; }
.u-body  { font-size: 1rem;     line-height: 1.56; color: var(--body); margin: 0; }
.u-small { font-size: .875rem;  line-height: 1.56; color: var(--muted); margin: 0; }
.u-micro {
    font-size: .76rem; font-weight: 700; letter-spacing: .13em;
    text-transform: uppercase; color: var(--muted); margin: 0;
}
.u-measure { max-width: 62ch; }

/* The key phrase in a headline. Clay against the pine heading carries the
   emphasis on its own — a highlighter bar behind the text sat over the
   descenders and read as clutter at display sizes. */
.u-mark { color: var(--clay); }

/* ============================ EYEBROW ============================ */
/* The sister site's section label is a small sky-blue caption with a dot,
   not a filled chip. Dropping the pill is most of what lightens the page. */
.u-eyebrow {
    display: inline-flex; align-items: center; gap: 9px;
    background: transparent; color: var(--accent-text);
    /* Tracking eases off as the size goes up: .18em was set for 14px text and
       at 17px it pushes the longer labels uncomfortably wide. */
    font-size: 1rem; font-weight: 500; letter-spacing: .15em;
    text-transform: uppercase; padding: 0;
    margin-bottom: 18px;
}
.u-eyebrow.on-dark { background: transparent; color: var(--brand-light); }
/* A tracked uppercase label broken over two lines reads badly, and at 320px
   half of them were. Size and tracking both ease back so each stays on one. */
@media (max-width: 575.98px) {
    .u-eyebrow { font-size: .9rem; letter-spacing: .1em; margin-bottom: 15px; }
}
/* The longest label on the site, "Welcome to MITCON Biopharma", still needed
   one more step down to hold a single line on a 320px screen. */
@media (max-width: 359.98px) {
    .u-eyebrow { font-size: .82rem; letter-spacing: .07em; }
}

/* ============================ SECTION RHYTHM ============================ */
/* DESIGN.md puts section padding at 64-88px on desktop and 40-56px on mobile.
   This was 72-124px, so every section ran tall and the page read as a long
   scroll of near-identical gaps. Changed deliberately, with the whole page
   re-checked afterwards, as that note asks. */
.u-sec       { padding: clamp(44px, 6vw, 88px) 0; }
.u-sec.tight { padding: clamp(36px, 4.5vw, 64px) 0; }
.u-sec.paper { background: var(--surface-alt); }
.u-sec.white { background: var(--surface); }
.u-sec.tintd { background: var(--brand-tint); }
.u-sec.ink   { background: var(--grad-ink); color: var(--on-dark); }
.u-sec.ink .u-display, .u-sec.ink .u-h2, .u-sec.ink .u-h3 { color: #fff; }
.u-sec.ink .u-lead, .u-sec.ink .u-body, .u-sec.ink .u-small { color: var(--on-dark); }
.u-sec.ink .u-mark { color: var(--accent); }
.u-sec.ink .u-mark::after { display: none; }

/* ---- Shared surface texture -------------------------------------------
   The hero's dot field is what gives that first screen its material, and it
   was the only thing on the page that had it — which is exactly why the hero
   read as a different surface from everything under it. The light sections
   now carry the same field: same dot, same 26px grid, weaker, and masked so
   it dissolves as it falls. The dark section is deliberately left out.

   Content sits on its own layer above it; the texture is inert to the
   pointer so nothing underneath it can swallow a click. */
.u-sec.white, .u-sec.paper, .u-keynums, .u-accred { position: relative; }
.u-sec.white::before,
.u-sec.paper::before,
.u-keynums::before,
.u-accred::before {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background-image: radial-gradient(rgba(var(--rgb-accent), .10) 1.3px, transparent 1.3px);
    background-size: 26px 26px;
    -webkit-mask-image: linear-gradient(#000, transparent 64%);
    mask-image: linear-gradient(#000, transparent 64%);
}
/* The inner pages predate .u-sec and set their background inline on a
   .py-5 section instead. Matching on that attribute is not pretty, but it
   reaches them without editing fifteen view files, and the exclusion keeps
   the dark bands out. If the exclusion ever misses one the cost is small:
   sky blue at .10 over near-black is barely visible, not broken. */
section.py-5:not([style*="grad-ink"]) { position: relative; }
section.py-5:not([style*="grad-ink"])::before {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background-image: radial-gradient(rgba(var(--rgb-accent), .10) 1.3px, transparent 1.3px);
    background-size: 26px 26px;
    -webkit-mask-image: linear-gradient(#000, transparent 64%);
    mask-image: linear-gradient(#000, transparent 64%);
}

.u-sec > .container,
.u-keynums > .container,
.u-accred > .container,
section.py-5 > .container { position: relative; z-index: 1; }

/* Two sections of the same shade meeting back to back read as one long
   block. A hairline is enough to tell them apart without inventing a
   third background. */
.u-sec.white + .u-sec.white,
.u-sec.paper + .u-sec.paper { border-top: 1px solid var(--line); }

.u-head        { margin-bottom: clamp(40px, 5vw, 64px); }
.u-head.center { text-align: center; }
.u-head.center .u-measure { margin-left: auto; margin-right: auto; }
.u-head .u-lead { margin-top: 18px; }

/* ============================ CARD ============================ */
.u-card {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: 30px 28px; height: 100%;
    transition: transform .28s cubic-bezier(.2,.7,.3,1), box-shadow .28s, border-color .28s;
}
.u-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--brand-pale); }

/* Grid that holds the numbered cards. */
.u-numgrid { display: grid; gap: 18px; }
@media (min-width: 768px) { .u-numgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 992px) { .u-numgrid { grid-template-columns: repeat(3, 1fr); } }

/* Numbered feature card — the index is the graphic, no icon blobs. */
.u-numcard {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: 30px 28px; height: 100%;
    position: relative; overflow: hidden;
    transition: transform .28s cubic-bezier(.2,.7,.3,1), box-shadow .28s, border-color .28s;
}
.u-numcard:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--brand-pale); }
.u-numcard .idx {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: var(--r-pill);
    background: var(--accent); color: var(--ink);
    font-family: 'Montserrat', sans-serif; font-size: .92rem; font-weight: 700;
    margin-bottom: 20px; font-variant-numeric: tabular-nums;
}
.u-numcard .u-h3 { margin-bottom: 10px; }

/* ============================ MODULE ROW ============================ */
.u-modules {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); overflow: hidden;
}
.u-module {
    display: grid; grid-template-columns: 62px 1fr; gap: 4px 18px;
    padding: 26px; border-bottom: 1px solid var(--line-soft);
    transition: background .22s;
}
.u-module:last-child { border-bottom: 0; }
.u-module:hover { background: var(--surface-alt); }
.u-module .idx {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: var(--r-pill);
    background: var(--brand-pale); color: var(--brand);
    font-family: 'Montserrat', sans-serif; font-size: .82rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.u-module:hover .idx { background: var(--accent); color: var(--ink); }
.u-module .u-h3 { margin-bottom: 6px; }
@media (min-width: 992px) {
    .u-module { grid-template-columns: 62px minmax(0, 19rem) 1fr; align-items: center; }
    .u-module .u-h3 { margin-bottom: 0; }
}

/* ============================ STAT ============================ */
.u-stats { display: grid; gap: 14px; }
@media (min-width: 576px) { .u-stats { grid-template-columns: repeat(2, 1fr); } }
.u-stat {
    background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .16);
    border-radius: var(--r-md); padding: 24px 22px;
}
.u-stat .n {
    font-family: 'Montserrat', sans-serif; font-weight: 500; line-height: 1;
    font-size: clamp(1.45rem, 2.4vw, 1.95rem); color: var(--accent);
}
.u-stat .l { font-size: .92rem; line-height: 1.6; color: var(--on-dark); margin-top: 10px; }

/* ============================ STEPPER ============================ */

/* ---- Track card ----
   Each track sits on its own white card against the section's blue-grey, so
   three tracks read as three things rather than one long ruled list. */
.u-track {
    margin-bottom: 20px;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: clamp(20px, 2.6vw, 28px);
}
.u-track:last-child { margin-bottom: 0; }

.u-track-name {
    display: inline-flex; align-items: center; gap: 10px; margin-bottom: 22px;
    background: transparent; border: 0; border-radius: 0; padding: 0;
    font-family: 'Montserrat', sans-serif; font-weight: 600;
    color: var(--ink); font-size: 1rem;
}
/* One colour per track, so the eye can tell them apart at a glance. */
.u-track-name i {
    width: 34px; height: 34px; border-radius: var(--r-md);
    display: grid; place-items: center; font-size: .95rem;
}
.u-track.tone-blue   .u-track-name i { background: var(--brand-pale); color: var(--brand); }
.u-track.tone-teal   .u-track-name i { background: var(--rx-mint);    color: var(--rx-teal); }
.u-track.tone-indigo .u-track-name i { background: #E6E8F7;           color: #3B3F8F; }

/* Each stage is a card now. The connector is the gap between them plus the
   arrow on the card edge, so the old absolute dot-and-line is gone. */
.u-steps { display: grid; gap: 12px; }
/* The gap is a named value because the connector between two cards is
   positioned from it: half of it, to the left of the second card. */
@media (min-width: 768px) {
    .u-steps { --step-gap: 24px; grid-template-columns: repeat(4, 1fr); gap: var(--step-gap); }
}

.u-step {
    position: relative; padding: 16px 16px 18px;
    background: var(--rx-bg); border: 1px solid var(--line);
    border-radius: var(--r-md);
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-step::after { content: none; }   /* ::before is the step node, below */
.u-step:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--rx-teal); }

/* The stage name IS the node on the rail — it used to be a chip inside the
   card, which would have said ENTRY twice once the node carried the word
   too. Real text in the markup rather than CSS content, so it is still read
   out in order: Entry, Grow, Lead, Senior. Geometry is in the pathway block
   further down, with the rail it sits on. */
.u-step .stage {
    display: inline-block; margin: 0 0 10px; padding: 7px 15px; white-space: nowrap;
    border-radius: var(--r-pill); border: 2px solid var(--rx-line);
    background: var(--surface); color: var(--muted);
    font-size: .64rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    transition: background-color .45s ease, border-color .45s ease,
                color .45s ease, box-shadow .45s ease;
}
.u-step .role {
    font-family: 'Montserrat', sans-serif; font-weight: 600; color: var(--ink);
    font-size: 1rem; line-height: 1.35; margin-top: 0;
}
.u-step .yr { font-size: .84rem; color: var(--muted); margin-top: 6px; }

/* The last stage is the destination, so it carries the dark fill. */
.u-step.is-last { background: var(--rx-navy); border-color: var(--rx-navy); }
.u-step.is-last .role  { color: #fff; }
.u-step.is-last .yr    { color: var(--rx-mint); }
.u-step.is-last:hover  { border-color: var(--rx-teal); }


/* ---- Pathway motion ----------------------------------------------------
   The old version drew a connecting line segment by segment. There is no
   line any more — the stages are cards — so the progression is carried by
   the cards themselves arriving left to right. Entry first, Senior last,
   which is the order the row is meant to be read in. */
.u-step { transition: transform .45s cubic-bezier(.3, .9, .4, 1), opacity .45s ease,
                      box-shadow .25s, border-color .25s; }
html.rv .u-track .u-step { opacity: 0; transform: translate3d(0, 14px, 0); }
html.rv .u-track.rv-in .u-step { opacity: 1; transform: none; }
html.rv .u-track.rv-in .u-step:nth-child(1) { transition-delay: .05s; }
html.rv .u-track.rv-in .u-step:nth-child(2) { transition-delay: .17s; }
html.rv .u-track.rv-in .u-step:nth-child(3) { transition-delay: .29s; }
html.rv .u-track.rv-in .u-step:nth-child(4) { transition-delay: .41s; }

/* Hover owns transform too, so the arrival delay has to be cleared or the
   lift would wait for it. */
.u-step:hover { transition-delay: 0s; }

.u-track { transition: box-shadow .25s, border-color .25s; }
.u-track:hover { box-shadow: var(--shadow-md); border-color: var(--rx-teal); }

@media (prefers-reduced-motion: reduce) {
    html.rv .u-track .u-step,
    html.rv .u-track.rv-in .u-step { opacity: 1; transform: none; transition: none; }
    .u-step:hover { transform: none; }
}

/* ============================ FACT LIST ============================ */
.u-facts { margin: 0; }
.u-fact {
    display: flex; justify-content: space-between; align-items: baseline; gap: 20px;
    padding: 13px 0; border-bottom: 1px solid rgba(255, 255, 255, .14);
}
.u-fact:last-child { border-bottom: 0; padding-bottom: 0; }
.u-fact dt {
    font-size: .88rem; color: var(--brand-light); font-weight: 400; margin: 0;
    flex: 0 0 auto; white-space: nowrap;
}
/* The longest value here is the eligibility list, which is wider than the
   half the row would give it. min-width lets it take what it needs and wrap
   inside its own block rather than shoving the label off the left edge. */
.u-fact dd {
    font-size: .97rem; color: #fff; font-weight: 600; margin: 0;
    text-align: right; min-width: 0;
}

/* ============================ QUOTE ============================ */
.u-quote {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: 32px 30px; height: 100%;
    display: flex; flex-direction: column;
    transition: transform .28s cubic-bezier(.2,.7,.3,1), box-shadow .28s, border-color .28s;
}
.u-quote:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--brand-pale); }
.u-quote .mark {
    width: 40px; height: 40px; border-radius: var(--r-pill);
    background: var(--accent); color: var(--ink);
    display: flex; align-items: center; justify-content: center;
    font-family: 'Montserrat', sans-serif; font-size: 1.5rem; line-height: 1;
    padding-top: .32em; margin-bottom: 18px;
}
.u-quote .said { font-size: .94rem; line-height: 1.82; color: var(--text); flex: 1; }
.u-quote .who {
    display: flex; align-items: center; gap: 13px; margin-top: 22px;
    padding-top: 20px; border-top: 1px solid var(--line-soft);
}
.u-avatar {
    width: 46px; height: 46px; min-width: 46px; border-radius: var(--r-pill);
    object-fit: cover; background: var(--brand); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: .92rem;
}
.u-journey { font-size: .79rem; color: var(--muted); margin-top: 3px; }
.u-journey .to { color: var(--clay); font-weight: 600; }

/* ============================ TILE / LOGO WALL ============================ */
.u-logos { display: grid; gap: 14px; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 576px) { .u-logos { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 992px) { .u-logos { grid-template-columns: repeat(4, 1fr); } }
.u-logo {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-md); padding: 24px 16px; text-align: center;
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
    gap: 8px; min-height: 162px;
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-logo:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--brand-pale); }
.u-logo img {
    max-width: 100%; max-height: 40px; object-fit: contain;
    filter: grayscale(1); opacity: .7; transition: .25s;
}
.u-logo:hover img { filter: none; opacity: 1; }
.u-logo .mono { font-family: 'Montserrat', sans-serif; font-weight: 500; color: var(--ink); font-size: .9rem; }
.u-logo .co { font-size: .74rem; color: var(--muted); line-height: 1.5; }
.u-logo .seal {
    width: 40px; height: 40px; border-radius: var(--r-pill);
    background: var(--brand-pale); color: var(--brand);
    display: flex; align-items: center; justify-content: center;
    font-family: 'Montserrat', sans-serif; font-weight: 500; font-size: 1rem;
}
.u-chip {
    display: inline-block; background: var(--accent-pale); color: var(--clay);
    font-weight: 700; font-size: .72rem; padding: 4px 11px;
    border-radius: var(--r-pill); margin-top: auto;
}

/* ============================ POST CARD ============================ */
.u-post {
    display: flex; flex-direction: column; height: 100%; text-decoration: none;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); overflow: hidden;
    transition: transform .28s cubic-bezier(.2,.7,.3,1), box-shadow .28s, border-color .28s;
}
.u-post:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--brand-pale); }
.u-post .shot { height: 176px; background: var(--grad-ink); position: relative; overflow: hidden; }
.u-post .shot img { width: 100%; height: 100%; object-fit: cover; }
.u-post .shot .watermark {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 3rem; color: rgba(255, 255, 255, .15);
}
.u-post .tag {
    position: absolute; left: 16px; top: 16px;
    background: var(--accent); color: var(--ink);
    font-size: .68rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    padding: 6px 12px; border-radius: var(--r-pill);
}
.u-post .inner { padding: 24px; display: flex; flex-direction: column; flex: 1; }
.u-post .u-h3 { margin-bottom: 10px; transition: color .2s; }
.u-post:hover .u-h3 { color: var(--clay); }
.u-post .more { margin-top: auto; padding-top: 18px; font-size: .82rem; font-weight: 700; color: var(--brand); }

/* ============================ TRUST STRIP ============================ */
.u-trust { background: var(--surface); border-bottom: 1px solid var(--line); }
.u-trust ul { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
@media (min-width: 768px) { .u-trust ul { grid-template-columns: repeat(3, 1fr); } }
.u-trust li {
    padding: 20px 22px; display: flex; align-items: center; gap: 13px;
    font-size: .94rem; color: var(--body); border-bottom: 1px solid var(--line-soft);
}
@media (min-width: 768px) {
    .u-trust li { border-bottom: 0; border-right: 1px solid var(--line-soft); }
    .u-trust li:last-child { border-right: 0; }
}
.u-trust li i {
    width: 36px; height: 36px; min-width: 36px; border-radius: var(--r-pill);
    background: var(--brand-pale); color: var(--brand);
    display: flex; align-items: center; justify-content: center; font-size: .9rem;
}

/* ============================ BUTTONS ============================ */
/* mitconskills.com sets every action in 14px uppercase with 3px tracking.
   It is the most recognisable single detail of that site's chrome. */
.u-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 10px;
    font-family: 'Montserrat', sans-serif;
    font-size: .875rem; font-weight: 600; padding: 15px 30px;
    text-transform: uppercase; letter-spacing: .19em;
    border-radius: var(--r-pill); border: 2px solid transparent;
    text-decoration: none; cursor: pointer;
    transition: background .3s, border-color .3s, color .3s, transform .3s, box-shadow .3s;
}
.u-btn:hover { transform: translateY(-2px); }
.u-btn-solid { background: var(--brand); color: #fff; }
.u-btn-solid:hover { background: var(--brand-dark); color: #fff; box-shadow: var(--shadow-md); }
.u-btn-sun { background: var(--accent); color: var(--ink); }
.u-btn-sun:hover { background: var(--accent-dark); color: var(--ink); box-shadow: var(--shadow-md); }
.u-btn-green { background: var(--green); color: var(--ink); }
.u-btn-green:hover { background: var(--green-dark); color: var(--ink); box-shadow: var(--shadow-md); }
.u-btn-clay { background: var(--clay); color: #fff; }
.u-btn-clay:hover { background: var(--clay-dark); color: #fff; box-shadow: var(--shadow-md); }
.u-btn-outline { background: transparent; color: var(--brand); border-color: var(--brand); }
.u-btn-outline:hover { background: var(--brand); color: #fff; }
.u-btn-ink { background: var(--ink); color: #fff; }
.u-btn-ink:hover { background: var(--ink-2); color: #fff; box-shadow: var(--shadow-md); }
.u-btn-light { background: #fff; color: var(--ink); }
.u-btn-light:hover { background: var(--surface-alt); color: var(--ink); }
.u-btn-ghost { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .45); }
.u-btn-ghost:hover { background: rgba(255, 255, 255, .14); color: #fff; }

/* =========================================================================
   LEGACY CLASS BRIDGE
   The inner pages were written against these names. Restyling them here
   means every one of those pages picks up the system without its markup
   being touched.
   ========================================================================= */

.page-hero {
    position: relative; overflow: hidden;
    background: radial-gradient(720px 400px at 88% -20%, rgba(var(--rgb-accent),.12), transparent 62%),
                radial-gradient(540px 430px at -6% 120%, rgba(var(--rgb-brand),.07), transparent 58%),
                var(--grad-banner);
    border-bottom: 1px solid var(--line);
    padding: clamp(56px, 7vw, 92px) 0 clamp(40px, 5vw, 60px);
    color: var(--text); margin-top: 0;
}

/* ---- Making the band read as a surface --------------------------------
   The band was a title and a breadcrumb on a near-white wash, left-aligned,
   with the whole right half empty — on a wide screen that is most of it.
   Two layers fill that half without putting anything near the type.

   Both are masked to start past the middle, so the side the text lives on
   stays clean and nothing lands behind a letter: the contrast of the
   headline and the breadcrumb is the same as it was. */
.page-hero::before {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    display: none;
    background-image: radial-gradient(rgba(var(--rgb-accent), .22) 1.2px, transparent 1.2px);
    background-size: 24px 24px;
    -webkit-mask-image: linear-gradient(100deg, transparent 52%, #000 100%);
            mask-image: linear-gradient(100deg, transparent 52%, #000 100%);
}
/* Three thin rings, off the right edge and cropped by the band — the
   asymmetry is the point. They echo the node field on the homepage hero
   rather than introducing a new motif. */
.page-hero::after {
    content: ""; position: absolute; z-index: 0; pointer-events: none;
    display: none;
    right: clamp(-180px, -6vw, -60px); top: 50%;
    width: clamp(320px, 34vw, 560px); aspect-ratio: 1;
    translate: 0 -50%;
    border-radius: 50%;
    background:
        radial-gradient(circle, transparent 0 45.4%, rgba(var(--rgb-accent), .16) 45.4% 46%, transparent 46%),
        radial-gradient(circle, transparent 0 62.0%, rgba(var(--rgb-brand),  .11) 62.0% 62.5%, transparent 62.5%),
        radial-gradient(circle, transparent 0 78.6%, rgba(var(--rgb-accent), .10) 78.6% 79%, transparent 79%);
}
/* Both only from 992px up. The emptiness they answer is the right half of a
   wide band; on a phone the heading already fills the width, and a 320px
   ring would sit straight on top of it. */
@media (min-width: 992px) {
    .page-hero::before,
    .page-hero::after { display: block; }
}
.page-hero > .container { position: relative; z-index: 1; }

/* ---- One order, whatever the markup says ----
   Eight of these pages write the heading first and the breadcrumb under it;
   the other eight do the reverse and add a line of standfirst. Ordering the
   column here settles it for all nineteen without editing nineteen files,
   and without moving anything in the reading order that matters — the
   breadcrumb is a nav landmark either way. */
.page-hero > .container { display: flex; flex-direction: column; align-items: flex-start; }
.page-hero nav[aria-label="breadcrumb"] { order: 1; margin: 0 0 10px !important; }
.page-hero h1 { order: 2; }
.page-hero > .container > p { order: 3; }

.page-hero h1 {
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    font-size: clamp(1.9rem, 3.6vw, 2.7rem); line-height: 1.14;
    letter-spacing: -.025em; color: var(--ink);
    max-width: 22ch; text-wrap: balance;   /* no single word left on its own line */
}

/* The eight pages with no standfirst carried the same height as the eight
   that have one, which is where most of the emptiness came from. */
.page-hero:not(:has(> .container > p)) {
    padding: clamp(44px, 5.2vw, 68px) 0 clamp(32px, 3.6vw, 46px);
}
.page-hero .breadcrumb { background: transparent; padding: 0; }
.page-hero .breadcrumb-item a { color: var(--clay-dark); text-decoration: none; font-weight: 500; }
.page-hero .breadcrumb-item a:hover { text-decoration: underline; }
.page-hero .breadcrumb-item.active { color: var(--body); }
.page-hero .breadcrumb-item + .breadcrumb-item::before { color: var(--muted-2); }

.section-title {
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    font-size: clamp(1.55rem, 2.7vw, 2.2rem); line-height: 1.18;
    letter-spacing: -.02em; color: var(--ink);
}
.section-divider {
    width: 56px; height: 4px; border-radius: var(--r-pill);
    background: var(--accent); margin-top: 16px; margin-bottom: 16px;
}

/* ---- Divider draw (trial) ----------------------------------------------
   Opt-in through .is-draw, so this is live in exactly one place until it has
   been looked at. Everything is scoped under html.rv: without JavaScript the
   bar is simply there at full width, never a zero-width stub.

   The bar draws itself as its block arrives, then a single light passes over
   it. Once, not looping — a bar that keeps shining next to a heading is the
   thing that pulls attention off the section. */
.section-divider.is-draw { position: relative; overflow: hidden; }
html.rv .section-divider.is-draw { width: 0; }
html.rv .rv-in .section-divider.is-draw,
html.rv .rv-in.section-divider.is-draw {
    width: 56px;
    transition: width .6s cubic-bezier(.3, .9, .4, 1) .15s;
}
.section-divider.is-draw::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .9), transparent);
    transform: translateX(-100%);
}
html.rv .rv-in .section-divider.is-draw::after { animation: sd-sheen 1s ease .8s 1 both; }
@keyframes sd-sheen { to { transform: translateX(120%); } }

@media (prefers-reduced-motion: reduce) {
    html.rv .section-divider.is-draw,
    html.rv .rv-in .section-divider.is-draw { width: 56px; transition: none; }
    html.rv .rv-in .section-divider.is-draw::after { animation: none; }
}
.section-subtitle { font-size: 1.02rem; line-height: 1.75; color: var(--body); max-width: 62ch; }
.text-center .section-subtitle { margin-inline: auto; }

/* Bootstrap card, warmed up */
.card {
    background: var(--surface); border: 1px solid var(--line) !important;
    border-radius: var(--r-lg) !important; box-shadow: none;
    transition: transform .28s cubic-bezier(.2,.7,.3,1), box-shadow .28s, border-color .28s;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--brand-pale) !important; }
.card-body { padding: 26px; }

/* Bootstrap buttons, mapped onto the system */
.btn { border-radius: var(--r-pill); font-weight: 600; padding: 12px 24px; border-width: 2px; }
.btn-sm { padding: 8px 18px; font-size: .84rem; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-primary:hover, .btn-primary:focus { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }
.btn-outline-primary { color: var(--brand); border-color: var(--brand); background: transparent; }
.btn-outline-primary:hover { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-outline-secondary { color: var(--ink); border-color: var(--line); background: transparent; }
.btn-outline-secondary:hover { background: var(--surface-alt); border-color: var(--brand); color: var(--brand); }
.btn-outline-danger { color: var(--danger); border-color: var(--danger); }
.btn-outline-danger:hover { background: var(--danger); border-color: var(--danger); color: #fff; }

/* Forms */
.form-control, .form-select {
    border-radius: var(--r-md); border: 1.5px solid var(--line);
    padding: 12px 16px; font-size: .92rem; background: var(--surface); color: var(--text);
    transition: border-color .2s, box-shadow .2s;
}
.form-control:focus, .form-select:focus {
    border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-wash); background: var(--surface);
}
.form-label { font-weight: 600; font-size: .88rem; color: var(--ink); }

/* Badges & pagination */
.badge { border-radius: var(--r-pill); font-weight: 600; padding: 6px 12px; }
.pagination { gap: 6px; flex-wrap: wrap; justify-content: center; }
.page-link {
    border-radius: var(--r-pill) !important; border: 1px solid var(--line);
    color: var(--brand); padding: 9px 16px; font-size: .88rem;
}
/* Eight page numbers plus Prev/Next run past a phone, so tighten and wrap. */
@media (max-width: 575.98px) {
    .pagination { gap: 5px; }
    .page-link { padding: 7px 12px; font-size: .82rem; }
}
.page-link:hover { background: var(--brand-pale); border-color: var(--brand-pale); color: var(--brand); }
.page-item.active .page-link { background: var(--brand); border-color: var(--brand); color: #fff; }
.page-item.disabled .page-link { color: var(--muted-2); background: transparent; }

/* Accordion (FAQ page) */
.accordion-item { border: 1px solid var(--line); border-radius: var(--r-md) !important; overflow: hidden; margin-bottom: 12px; }
.accordion-button { background: var(--surface); color: var(--ink); font-weight: 600; font-size: .98rem; padding: 18px 22px; }
.accordion-button:not(.collapsed) { background: var(--brand-pale); color: var(--brand); box-shadow: none; }
.accordion-button:focus { box-shadow: 0 0 0 4px var(--brand-wash); border-color: var(--brand); }
.accordion-body { padding: 20px 22px; color: var(--body); font-size: .94rem; line-height: 1.8; }

/* Site footer. Lives here (not in the layout) so it stays in step with
   the rest of the system. */
footer {
    background: var(--grad-ink);
    color: var(--on-dark);
    padding: clamp(52px, 6vw, 76px) 0 0;
}
footer h5 {
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    color: #fff; font-size: 1.02rem; margin-bottom: 18px;
}
footer p { color: rgba(255, 255, 255, .72); }
footer a { color: rgba(255, 255, 255, .78); text-decoration: none; font-size: .88rem; transition: color .2s, padding-left .2s; }
footer a:hover { color: var(--accent); padding-left: 3px; }
footer ul { margin: 0; }
footer li { line-height: 1.7; }
footer hr { border-color: rgba(255, 255, 255, .16); opacity: 1; }
footer .footer-bottom,
footer .border-top {
    border-top: 1px solid rgba(255, 255, 255, .16) !important;
    margin-top: clamp(34px, 4vw, 48px);
    padding: 22px 0;
    font-size: .84rem;
    color: rgba(255, 255, 255, .62);
}

/* Tables (admin) */
.table th {
    background: var(--surface-alt); color: var(--ink); font-weight: 700;
    font-size: .76rem; text-transform: uppercase; letter-spacing: .06em;
    border-bottom: 1px solid var(--line);
}
.table td { font-size: .9rem; vertical-align: middle; border-color: var(--line-soft); color: var(--text); }

@media (prefers-reduced-motion: reduce) {
    .u-btn, .u-card, .u-numcard, .u-quote, .u-post, .u-logo, .u-module, .card { transition: none; }
    .u-btn:hover, .u-card:hover, .u-numcard:hover, .u-quote:hover,
    .u-post:hover, .u-logo:hover, .card:hover { transform: none; }
}

/* =========================================================================
   MARQUEE — auto-scrolling rails
   Used by the hiring-partner logo rail and the placed-student portrait rail.
   The track holds the same run twice; translating it by exactly -50% makes
   the loop seamless. Hover and reduced-motion both pause it.
   ========================================================================= */
.u-marquee { position: relative; overflow: hidden; }
.u-marquee::before,
.u-marquee::after {
    content: ""; position: absolute; top: 0; bottom: 0; width: clamp(28px, 6vw, 88px);
    z-index: 2; pointer-events: none;
}
.u-marquee::before { left: 0;  background: linear-gradient(90deg, var(--mq-fade, var(--surface)), transparent); }
.u-marquee::after  { right: 0; background: linear-gradient(270deg, var(--mq-fade, var(--surface)), transparent); }
.u-marquee.on-alt  { --mq-fade: var(--surface-alt); }

.u-marquee-track {
    display: flex; width: max-content;
    animation: u-marquee var(--mq-speed, 42s) linear infinite;
}
.u-marquee:hover .u-marquee-track,
.u-marquee:focus-within .u-marquee-track { animation-play-state: paused; }
.u-marquee-run { display: flex; align-items: stretch; gap: clamp(12px, 2vw, 22px); padding-right: clamp(12px, 2vw, 22px); }

@keyframes u-marquee { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }

/* Hiring-partner tile inside a marquee */
.u-mq-logo {
    flex: 0 0 auto; width: 210px; min-height: 148px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
    padding: 20px 18px; text-align: center;
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-mq-logo:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--accent); }
.u-mq-logo img {
    max-height: 72px; max-width: 164px; object-fit: contain;
    transition: transform .25s;
}
.u-mq-logo:hover img { transform: scale(1.06); }
.u-mq-logo .seal {
    width: 62px; height: 62px; border-radius: 50%; display: grid; place-items: center;
    background: var(--brand-pale); color: var(--brand); font-weight: 800; font-size: 1.5rem;
}
.u-mq-logo .co { font-size: .86rem; font-weight: 600; color: var(--text); line-height: 1.35; }

/* Placed-student portrait card inside a marquee */
.u-mq-student {
    flex: 0 0 auto; width: 232px;
    display: flex; flex-direction: column; align-items: center; text-align: center;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
    padding: 26px 18px 22px;
}
.u-mq-student .face {
    width: 116px; height: 116px; border-radius: 50%; overflow: hidden; margin-bottom: 14px;
    display: grid; place-items: center; background: var(--grad-hero);
    color: #fff; font-weight: 800; font-size: 2.1rem;
    border: 4px solid var(--surface); box-shadow: 0 0 0 2px var(--accent), var(--shadow-md);
}
.u-mq-student .face img { width: 100%; height: 100%; object-fit: cover; }
.u-mq-student .nm  { font-weight: 700; font-size: 1.04rem; color: var(--ink); }
.u-mq-student .rl  { font-size: .88rem; color: var(--body); margin: 4px 0 2px; }
.u-mq-student .cmp { font-size: .9rem; font-weight: 600; color: var(--teal-text); }
.u-mq-student .pkg {
    margin-top: 9px; background: var(--green-pale); color: var(--green-text);
    font-weight: 700; font-size: .72rem; padding: 3px 12px; border-radius: var(--r-pill);
}
.u-mq-student .loc { font-size: .72rem; color: var(--muted-2); margin-top: 6px; }

@media (max-width: 575.98px) {
    .u-mq-student { width: 190px; padding: 20px 14px 18px; }
    .u-mq-student .face { width: 92px; height: 92px; font-size: 1.7rem; }
    .u-mq-logo { width: 164px; min-height: 124px; padding: 16px 14px; }
    .u-mq-logo img { max-height: 56px; max-width: 126px; }
}


/* =========================================================================
   PLACED-STUDENT CARDS — a colour block with the name on a plate below
   ========================================================================= */
.u-pcards {
    display: flex; flex-wrap: nowrap; align-items: stretch;
    list-style: none; margin: 0; padding: 0;
    will-change: transform;
}
/* The rail clips, and the plate used to end exactly on that clip line: the
   shadow was cut off entirely and the last line of the company name was one
   rounding error away from being shaved. The bottom padding is the room the
   shadow needs (12px offset + 28px blur) plus a little air. */
.u-pcards > li {
    flex: 0 0 25%; min-width: 0;
    padding: 4px clamp(7px, 1.1vw, 13px) 34px;
}

/* A square portrait retains the supplied crop; labels sit below the face. */
.u-pcard {
    height: 100%; display: flex; flex-direction: column;
    padding: 20px 14px 0; background: var(--surface);
    border: 1px solid rgba(var(--rgb-ink), .09);
    border-radius: var(--r-md);
    box-shadow: 0 8px 24px rgba(var(--rgb-ink), .06);
}
.u-pcard .shot {
    flex: 0 0 auto; position: relative;
    width: min(100%, 210px); aspect-ratio: 1;
    margin-inline: auto; overflow: hidden;
    display: grid; place-items: center;
    border-radius: 50%; background: var(--surface-2);
    color: var(--brand); font-size: 2.5rem; font-weight: 600;
}
.u-pcard .face {
    display: block; width: 100%; height: 100%; object-fit: contain;
    /* The poster's decorative arc is outside this original-photo aperture. */
    clip-path: circle(46% at 50% 50%);
}
.u-pcard .plate {
    position: relative; margin: 0; padding: 16px 4px 22px;
    text-align: center; flex: 1 0 auto;
}
.u-pcard .nm {
    font-family: 'Montserrat', sans-serif; font-weight: 600;
    font-size: 1.02rem; line-height: 1.3; color: var(--ink);
}
.u-pcard .rl  { font-size: .86rem; color: var(--accent-text); margin-top: 5px; line-height: 1.35; }
.u-pcard .cmp { font-size: .82rem; color: var(--muted); margin-top: 3px; line-height: 1.35; }

/* Placement portraits: restrained feedback without moving the text layout. */
.u-pcards > li { padding-top: 14px; }
.u-pcard {
    position: relative;
    transition: transform .28s ease, box-shadow .28s ease, border-color .28s ease;
}
.u-pcard .shot {
    box-shadow: 0 0 0 1px rgba(var(--rgb-ink), .05);
    transition: box-shadow .28s ease;
}
.u-pcard .face { transition: transform .38s ease; }
.u-pcard .nm { transition: color .25s ease; }
.u-pcard .cmp {
    display: inline-block; margin-top: 10px; padding: 5px 10px;
    border-radius: 10px; background: var(--surface-2);
    transition: background-color .25s ease, color .25s ease;
}
@media (hover: hover) and (pointer: fine) {
    .u-pcard:hover {
        transform: translateY(-7px);
        border-color: var(--accent);
        box-shadow: 0 16px 30px rgba(var(--rgb-ink), .12);
    }
    .u-pcard:hover .shot { box-shadow: 0 0 0 4px var(--brand-pale); }
    .u-pcard:hover .face { transform: scale(1.035); }
    .u-pcard:hover .nm { color: var(--accent-text); }
    .u-pcard:hover .cmp { background: var(--brand-pale); color: var(--brand); }
}
@media (prefers-reduced-motion: reduce) {
    .u-pcard, .u-pcard .shot, .u-pcard .face, .u-pcard .nm, .u-pcard .cmp { transition: none; }
    .u-pcard:hover, .u-pcard:hover .face { transform: none; }
}

@media (max-width: 991.98px) { .u-pcards > li { flex-basis: 50%; } }
@media (max-width: 575.98px) { .u-pcards > li { flex-basis: 100%; } }

/* With motion off the rail is a plain wrapped grid and nothing slides. */
@media (prefers-reduced-motion: reduce) {
    .u-pcards { flex-wrap: wrap; justify-content: center; transform: none !important; }
    .u-pcards > li { flex: 0 0 auto; width: clamp(220px, 24vw, 280px); padding: 10px; }
}

/* =========================================================================
   HIRING-PARTNER CAROUSEL — two rows that step sideways as one
   ========================================================================= */
/* Each slide is a column of two tiles, which is what lets two rows and a
   horizontal step share one track: four columns on screen is eight partners,
   and a step moves a whole column rather than half a row. */
.u-plogos {
    /* One source of truth for the mark's size: the tile sizes off it too, so
       the breathing room stays equal on all four sides at every width. */
    --plogo: clamp(100px, 13vw, 164px);
    display: flex; flex-wrap: nowrap; align-items: stretch;
    list-style: none; margin: 0; padding: 0;
    will-change: transform;
}
.u-plogos > li {
    flex: 0 0 25%; min-width: 0;
    display: flex; flex-direction: column; gap: clamp(12px, 1.5vw, 18px);
    padding: 4px clamp(6px, .9vw, 11px) 10px;
}
.u-plogos .tile {
    flex: 1 0 auto;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 13px; padding: 18px 16px;
    /* Capping the tile to hug the mark pushed the air out between the tiles
       instead, which just moved the problem — they read as small and far
       apart. The enhanced files are 400px native, so the mark itself can
       carry the tile now: the logo grows and the tile fills its column. */
    width: 100%; margin-inline: auto;
    background: var(--surface-2); border-radius: var(--r-md);
    text-align: center;
}
/* With the name gone the mark is the whole tile, so it gets the room. Every
   file here is at least 164px tall natively (median 200), which is what caps
   this at 112: past that the shortest one would start to soften. */
/* ---- Flip ----
   The tile turns over on hover to show the name. Both faces are absolutely
   positioned, so the tile needs a height of its own — content can no longer
   give it one. backface-visibility is what keeps the front from showing
   through the back mid-turn. */
.u-plogos .tile { perspective: 900px; height: calc(var(--plogo) + 52px); }
.u-plogos .flip {
    position: relative; width: 100%; height: 100%;
    transform-style: preserve-3d;
    transition: transform .6s cubic-bezier(.3, .9, .4, 1);
}
.u-plogos .tile:hover .flip,
.u-plogos .tile:focus-within .flip { transform: rotateY(180deg); }
.u-plogos .face {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.u-plogos .back {
    transform: rotateY(180deg);
    padding: 10px 12px; text-align: center;
    font-size: .88rem; font-weight: 600; line-height: 1.35;
    color: var(--ink); overflow-wrap: anywhere;
}

.u-plogos .tile img {
    height: var(--plogo); max-width: 100%; object-fit: contain;
}

/* Without motion the tile does not turn; the name is already in the alt. */
@media (prefers-reduced-motion: reduce) {
    .u-plogos .flip,
    .u-plogos .tile:hover .flip,
    .u-plogos .tile:focus-within .flip { transform: none; transition: none; }
}
.u-plogos .seal {
    display: grid; place-items: center;
    width: var(--plogo); height: var(--plogo);
    border-radius: var(--r-pill); background: var(--brand-pale);
    color: var(--brand); font-weight: 700; font-size: 1.25rem;
}

/* Fewer columns means a wider column, and a wide column around a square mark
   is exactly the dead space this was meant to remove. So the count drops one
   step at a time instead of halving: four, three, two. */
@media (max-width: 991.98px) { .u-plogos > li { flex-basis: 33.3333%; } }
@media (max-width: 575.98px) { .u-plogos > li { flex-basis: 50%; } }

@media (prefers-reduced-motion: reduce) {
    .u-plogos { flex-wrap: wrap; justify-content: center; transform: none !important; }
    .u-plogos > li { flex: 0 0 auto; width: clamp(160px, 20vw, 210px); }
}
/* =========================================================================
   ACCREDITATION STRIP — government approvals & skill-council recognitions
   ========================================================================= */
.u-accred { background: var(--surface); border-bottom: 1px solid var(--line); padding: clamp(26px, 3.4vw, 42px) 0; }
.u-accred .cap {
    text-align: center; font-size: .72rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; color: var(--muted); margin-bottom: 22px;
}

/* Three at a time, sliding one across every second. The rail clips, the track
   carries the movement, and the list is rendered twice so the loop never
   shows a gap — the second set is a clone, hidden from assistive tech. Three
   up instead of five gives each mark roughly 1.8x the width it had, which is
   the whole point of the carousel. */
/* Scrollable on its own, so with JavaScript off every item is still
   reachable instead of clipped behind a transform that never runs. The
   engine adds .js-driven once it takes the rail over. */
.u-carousel .rail { overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.u-carousel .rail::-webkit-scrollbar { display: none; }
.u-carousel .rail.js-driven { overflow-x: hidden; }

/* Previous / pause / next sit together under the rail. The gallery pager
   uses the same row, so both are styled from one rule rather than two. */
.u-carousel .ctl, .u-gal .ctl {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    margin-top: 14px;
}
.u-carousel .ctl .pause, .u-gal .ctl .pause { margin: 0; }
.u-carousel .nav, .u-gal .nav {
    display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: var(--r-pill); border: 1px solid var(--line);
    background: var(--surface); color: var(--body);
    font-size: 1rem; line-height: 1; cursor: pointer;
    transition: background .3s, color .3s, border-color .3s;
}
.u-carousel .nav:hover, .u-gal .nav:hover { background: var(--brand); color: #fff; border-color: var(--brand); }
.u-carousel .nav:focus-visible,
.u-gal .nav:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.u-accred ul {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-wrap: nowrap; align-items: stretch;
    will-change: transform;
}
.u-accred li {
    flex: 0 0 33.3333%; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 16px; padding: 0 clamp(14px, 2.6vw, 36px);
}
.u-accred img,
.u-accred .mark {
    /* Capped at 124px: the LSSSDC file is only 210x110 native and anything
       taller starts upscaling it into softness. Raise this if a larger
       official asset turns up. */
    width: 100%; height: clamp(90px, 10vw, 124px);
    transition: transform .25s ease;
}
.u-accred img { object-fit: contain; }
.u-accred li:hover img,
.u-accred li:hover .mark { transform: translateY(-4px); }
.u-accred .mark {
    display: grid; place-items: center;
    font-weight: 800; font-size: clamp(1.3rem, 2.6vw, 1.9rem); letter-spacing: .04em;
    color: var(--brand);
}
.u-accred .nm {
    font-size: .86rem; color: var(--muted); letter-spacing: .04em;
    text-align: center; max-width: 100%; line-height: 1.45;
}

/* Content that moves on its own needs a stop that works for keyboard and
   touch, not only for a hovering mouse. */
.u-carousel .pause, .u-gal .pause {
    display: flex; align-items: center; justify-content: center;
    /* 44px is the documented minimum touch target; it was 34. */
    margin: 14px auto 0; width: 44px; height: 44px;
    border-radius: var(--r-pill); border: 1px solid var(--line);
    background: var(--surface); color: var(--body);
    font-size: .95rem; line-height: 1; cursor: pointer;
    transition: background .3s, color .3s, border-color .3s;
}
.u-carousel .pause:hover, .u-gal .pause:hover { background: var(--brand); color: #fff; border-color: var(--brand); }
.u-carousel .pause:focus-visible,
.u-gal .pause:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* Three across a phone would make every mark smaller than it was before the
   carousel, which defeats the purpose. */
@media (max-width: 767.98px) { .u-accred li { flex-basis: 50%; } }
@media (max-width: 479.98px) { .u-accred li { flex-basis: 100%; } }

/* With motion turned off the carousel is simply a list: it wraps, nothing
   moves, and the control has nothing left to control. */
@media (prefers-reduced-motion: reduce) {
    .u-accred ul { flex-wrap: wrap; justify-content: center; transform: none !important; }
    .u-accred li { flex: 0 0 auto; width: clamp(132px, 15vw, 172px); padding: 12px; }
    .u-accred img, .u-accred .mark { height: clamp(74px, 8vw, 96px); }
    .u-carousel .pause { display: none; }
}
/* =========================================================================
   TEAM — people cards
   ========================================================================= */
.u-team {
    display: grid; gap: clamp(18px, 2.4vw, 28px);
    /* The max keeps a single-member team from stretching into one wide slab. */
    grid-template-columns: repeat(auto-fit, minmax(210px, 264px));
    justify-content: center;
}
.u-person {
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
    padding: 28px 20px 24px; text-align: center; transition: transform .25s, box-shadow .25s;
}
.u-person:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.u-person .face {
    width: 104px; height: 104px; border-radius: 50%; overflow: hidden; margin: 0 auto 16px;
    display: grid; place-items: center; background: var(--grad-hero);
    color: #fff; font-weight: 800; font-size: 2rem;
    box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--accent-pale);
}
.u-person .face img { width: 100%; height: 100%; object-fit: cover; }
.u-person .nm  { font-weight: 700; font-size: 1rem; color: var(--ink); }
.u-person .dg  { font-size: .9rem; color: var(--teal-text); font-weight: 600; margin-top: 3px; }
.u-person .dp  { font-size: .75rem; color: var(--muted); margin-top: 2px; }
.u-person .bio { font-size: .9rem; color: var(--body); margin-top: 12px; line-height: 1.6; }
.u-person .lnk { display: inline-flex; margin-top: 12px; color: var(--brand); font-size: 1.05rem; }
.u-person .lnk:hover { color: var(--teal-text); }

@media (prefers-reduced-motion: reduce) {
    .u-marquee-track { animation: none; }
    .u-marquee-run:nth-child(2) { display: none; }
    .u-marquee { overflow-x: auto; }
    .u-person { transition: none; }
    .u-person:hover { transform: none; }
}

/* =========================================================================
   KEY NUMBERS — the four headline figures under the hero
   ========================================================================= */
.u-keynums { background: var(--surface); border-bottom: 1px solid var(--line); }
.u-keynums ul {
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 0;
    margin: 0; padding: 0; list-style: none;
}
@media (min-width: 768px) { .u-keynums ul { grid-template-columns: repeat(4, 1fr); } }
.u-keynums li {
    padding: clamp(24px, 3vw, 34px) 18px;
    border-bottom: 1px solid var(--line-soft); border-right: 1px solid var(--line-soft);
}
.u-keynums li:nth-child(2n) { border-right: 0; }
@media (min-width: 768px) {
    .u-keynums li { border-bottom: 0; border-right: 1px solid var(--line-soft); }
    .u-keynums li:nth-child(2n) { border-right: 1px solid var(--line-soft); }
    .u-keynums li:last-child { border-right: 0; }
}
/* The figure and its icon read as one unit: the icon sits in a tinted chip
   beside the number instead of floating above it, and the label hangs off the
   number's own left edge. Centring that whole group keeps the band
   symmetrical without centring three separate lines, which is what made the
   old stack hard to scan. The label also moves off --muted onto --body,
   because at .92rem it was the hardest thing on the page to read. */
.u-keynums .fig {
    display: flex; align-items: center; justify-content: center;
    gap: 14px; text-align: left;
}
.u-keynums li i {
    flex: 0 0 auto; width: 46px; height: 46px;
    border-radius: var(--r-md); background: var(--brand-pale);
    color: var(--accent-text); font-size: 1.2rem;
    display: flex; align-items: center; justify-content: center;
}
.u-keynums .n {
    font-family: 'Montserrat', sans-serif; font-weight: 600;
    font-size: clamp(1.8rem, 3.4vw, 2.5rem); line-height: 1;
    letter-spacing: -.02em; color: var(--brand);
}
.u-keynums .l {
    font-size: .9rem; font-weight: 500; color: var(--body);
    margin-top: 6px; line-height: 1.3;
}
/* Side by side needs room: below 1200px the four cells are too narrow and
   the label breaks onto a second line, so the icon goes back on top. */
@media (max-width: 1199.98px) {
    .u-keynums .fig { flex-direction: column; gap: 10px; text-align: center; }
    /* Narrower side padding buys the longest label a single line. */
    .u-keynums li { padding-inline: 12px; }
    .u-keynums li i { width: 40px; height: 40px; font-size: 1.05rem; }
}

/* =========================================================================
   RESEARCH PROJECT BASED TRAINING — the biotechnology companion block
   ========================================================================= */
.u-rpt {
    margin-top: clamp(32px, 4vw, 52px);
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-xl); overflow: hidden;
}
/* Dark header: it carries the section's weight so the body can stay quiet. */
.u-rpt-head {
    background: var(--rx-navy); border-bottom: 0;
    padding: clamp(24px, 3vw, 34px) clamp(22px, 3.4vw, 38px);
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px;
}
.u-rpt-head h3 {
    font-family: 'Montserrat', sans-serif; font-weight: 500; color: #fff;
    font-size: clamp(1.15rem, 2.3vw, 1.5rem); margin: 0;
}
.u-rpt-head .u-eyebrow { color: var(--rx-mint); }
.u-rpt-head .dur {
    background: var(--rx-mint); color: var(--rx-navy); border-radius: var(--r-pill);
    padding: 8px 17px; font-size: .82rem; font-weight: 700; white-space: nowrap;
}

.u-rpt-body { padding: clamp(24px, 3vw, 34px) clamp(22px, 3.4vw, 38px); }
.u-rpt-lbl {
    font-size: .8rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    color: var(--rx-teal); margin: 0 0 14px;
}

/* Five short programme names: chips, not a column. */
.u-rpt-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.u-rpt-chip {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--rx-mint); color: var(--rx-navy);
    border-radius: var(--r-pill); padding: 9px 16px;
    font-size: .88rem; font-weight: 600;
}
.u-rpt-chip i { font-size: .78rem; color: var(--rx-teal); }

/* Three across, so the five domains plus the key-feature card fill two full
   rows with nothing left hanging. */
.u-rpt-grid { display: grid; gap: 14px; grid-template-columns: 1fr; }
@media (min-width: 576px) { .u-rpt-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .u-rpt-grid { grid-template-columns: repeat(3, 1fr); } }

.u-rpt-card {
    background: var(--rx-bg); border: 1px solid var(--line);
    border-radius: var(--r-md); padding: 20px 18px;
    display: flex; flex-direction: column; gap: 8px;
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-rpt-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--rx-teal); }
.u-rpt-card .ic {
    width: 40px; height: 40px; border-radius: var(--r-md);
    background: var(--rx-mint); color: var(--rx-teal);
    display: grid; place-items: center; font-size: 1.05rem;
}
.u-rpt-card b { font-family: 'Montserrat', sans-serif; font-weight: 600; color: var(--ink); font-size: 1rem; line-height: 1.3; }
.u-rpt-card .tx { font-size: .9rem; color: var(--body); line-height: 1.6; }

/* The key feature is the one card that should read as a statement. */
.u-rpt-card.is-key { background: var(--rx-navy); border-color: var(--rx-navy); }
.u-rpt-card.is-key b { color: #fff; }
.u-rpt-card.is-key .tx { color: var(--rx-mint); }
.u-rpt-card.is-key .ic { background: rgba(255, 255, 255, .14); color: var(--rx-mint); }
.u-rpt-card.is-key:hover { border-color: var(--rx-teal); }

.u-rpt-foot {
    padding: 0 clamp(22px, 3.4vw, 38px) clamp(24px, 3vw, 34px);
}
.u-btn-rx { background: var(--rx-teal); color: #fff; }
.u-btn-rx:hover { background: var(--rx-navy); color: #fff; box-shadow: var(--shadow-md); }

/* The long form on the Courses page still uses the two-column body. */
.u-rpt-col { padding: clamp(22px, 3vw, 34px) clamp(22px, 3.4vw, 38px); }
.u-rpt-col + .u-rpt-col { border-top: 1px solid var(--line-soft); }
@media (min-width: 768px) {
    .u-rpt .u-rpt-body:has(.u-rpt-col) { display: grid; gap: 0; padding: 0; grid-template-columns: 1fr 1.25fr; }
    .u-rpt-col + .u-rpt-col { border-top: 0; border-left: 1px solid var(--line-soft); }
}
.u-rpt-col h4 {
    font-size: .8rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    color: var(--rx-teal); margin-bottom: 16px;
}
.u-rpt-col ul { list-style: none; margin: 0; padding: 0; }
.u-rpt-col li { display: grid; grid-template-columns: 20px 1fr; gap: 10px; padding: 9px 0; font-size: .97rem; color: var(--body); line-height: 1.6; }
.u-rpt-col li i { color: var(--rx-teal); font-size: .82rem; margin-top: .32em; }
.u-rpt-col li b { color: var(--ink); font-weight: 700; display: block; }
.u-rpt-note b { color: var(--ink); }

/* =========================================================================
   RESPONSIVE GUARDS
   ========================================================================= */

/* A `g-5` row carries -24px side margins while .container only pads 12px,
   so on phones the row box hangs 12px past the viewport on each side.
   Matching the gutter to the container padding removes that. */
@media (max-width: 575.98px) {
    .row.g-5, .row.gx-5, .row.g-4, .row.gx-4 { --bs-gutter-x: 1.5rem; }
}

/* Long unbroken strings (emails, URLs, company names) must not push a card
   wider than its column on a narrow screen. */
.u-mq-logo .co,
.u-mq-student .nm,
.u-mq-student .cmp,
.u-person .nm,
.u-accred .nm { overflow-wrap: anywhere; }

/* =========================================================================
   SKILL-SET GRID — the six modules as square cards rather than a row list
   ========================================================================= */
.u-modgrid { display: grid; gap: clamp(16px, 2vw, 24px); grid-template-columns: 1fr; }
@media (min-width: 576px) { .u-modgrid { grid-template-columns: repeat(2, 1fr); } }
/* Six boxes read best as two rows of three, not four-then-two. */
@media (min-width: 992px) { .u-modgrid { grid-template-columns: repeat(3, 1fr); } }
.u-modbox {
    position: relative; isolation: isolate;
    display: flex; flex-direction: column;
    aspect-ratio: 1 / 1;                 /* square; released when text needs room */
    min-height: 262px;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: 28px 24px;
    transition: transform .26s, box-shadow .26s, border-color .26s;
}
.u-modbox::after {
    content: ""; position: absolute; inset: auto 0 0 0; height: 3px;
    background: var(--grad-sun); border-radius: 0 0 var(--r-lg) var(--r-lg);
    transform: scaleX(0); transform-origin: left; transition: transform .3s;
}
.u-modbox:hover { transform: translateY(-6px); box-shadow: var(--shadow-lg); border-color: var(--accent-pale); }
.u-modbox:hover::after { transform: scaleX(1); }

.u-modbox .idx {
    position: absolute; top: 18px; right: 22px;
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    font-size: 3.1rem; line-height: 1; color: rgba(var(--rgb-accent), .30);
    font-variant-numeric: tabular-nums; z-index: -1;
    transition: color .26s;
}
.u-modbox:hover .idx { color: rgba(var(--rgb-accent), .52); }

.u-modbox .ic {
    width: 54px; height: 54px; min-height: 54px; border-radius: var(--r-md);
    display: grid; place-items: center;
    background: var(--brand-pale); color: var(--brand); font-size: 1.3rem;
    transition: background .26s, color .26s;
}
.u-modbox:hover .ic { background: var(--brand); color: #fff; }

/* The body sits in the middle so a short topic list does not leave the
   bottom half of the square empty. */
.u-modbox .bd { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 18px 0; }
.u-modbox .u-h3 { margin-bottom: 10px; }
.u-modbox .u-body { font-size: .97rem; line-height: 1.68; }

.u-modbox .tag {
    margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line-soft);
    font-size: .72rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; color: var(--muted);
    transition: color .26s;
}
.u-modbox:hover .tag { color: var(--teal-text); }

@media (max-width: 400px) {
    /* A square is too cramped for the longest topic lists on a small phone. */
    .u-modbox { aspect-ratio: auto; min-height: 0; }
}

/* Course category heading (Clinical Research / Biotechnology, side by side) */
.course-cat-head {
    display: flex; align-items: center; gap: 12px;
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    color: var(--ink); font-size: 1.12rem;
    margin: 0 0 20px; padding-bottom: 14px;
    border-bottom: 1px solid var(--line);
}
.course-cat-head .ic {
    width: 40px; height: 40px; min-width: 40px; border-radius: var(--r-md);
    display: grid; place-items: center; font-size: 1.05rem;
}

/* Light variant of the stat grid — used where a band is no longer dark, so
   the page carries two navy blocks (hero, closing CTA) instead of three. */
.u-stats.on-light .u-stat {
    background: var(--surface); border: 1px solid var(--line);
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-stats.on-light .u-stat:hover {
    transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--accent);
}
.u-stats.on-light .u-stat .n { color: var(--brand); }
.u-stats.on-light .u-stat .l { color: var(--body); }

/* =========================================================================
   PAGE CHROME — reading progress and back-to-top
   Both lost their styles in an earlier refactor; the button was rendering as
   a default grey browser button in the page flow under the footer.
   ========================================================================= */
#readProgress {
    position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 1040;
    background: var(--grad-sun);
    transform: scaleX(0); transform-origin: left;
    pointer-events: none;
}

#backToTop {
    position: fixed; right: clamp(16px, 3vw, 28px); bottom: clamp(16px, 3vw, 28px);
    z-index: 1035;
    width: 46px; height: 46px; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--brand); color: #fff;
    border: 0; font-size: 1.05rem; line-height: 1;
    box-shadow: var(--shadow-lg);
    opacity: 0; visibility: hidden; transform: translateY(12px);
    transition: opacity .25s, transform .25s, visibility .25s, background .2s;
}
#backToTop.is-on { opacity: 1; visibility: visible; transform: none; }
#backToTop:hover { background: var(--teal-text); }
#backToTop:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
    #readProgress { display: none; }
    #backToTop { transition: none; }
}

/* =========================================================================
   INTERACTION POLISH — lift on hover across the repeating card types
   ========================================================================= */
.u-numcard, .u-post, .u-logo, .u-quote, .u-person, .card {
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-numcard:hover, .u-post:hover, .u-logo:hover, .u-quote:hover, .card:hover {
    transform: translateY(-4px); box-shadow: var(--shadow-md);
}
.u-btn { transition: transform .3s, background .3s, color .3s, box-shadow .3s, border-color .3s; }
.u-btn:hover { transform: translateY(-2px); }
.u-btn:active { transform: translateY(0); }

/* Keyboard users get the same affordance as the mouse. */
.u-post:focus-visible, .u-btn:focus-visible, .u-modbox:focus-within {
    outline: 3px solid var(--accent); outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
    .u-numcard, .u-post, .u-logo, .u-quote, .u-person, .card, .u-btn, .u-modbox, .u-mq-logo { transition: none; }
    .u-numcard:hover, .u-post:hover, .u-logo:hover, .u-quote:hover, .card:hover,
    .u-btn:hover, .u-modbox:hover, .u-mq-logo:hover { transform: none; }
}

/* =========================================================================
   LIVE SURFACES
   The page was reading like a printed document: everything was legible but
   nothing answered the pointer. These are the responses — a sheen that
   tracks the cursor, a sweep across solid buttons, swipeable rails on
   touch, and a thumb-reachable action bar. All of it is suppressed under
   prefers-reduced-motion at the bottom of this block.
   ========================================================================= */

/* ---- Pointer sheen ------------------------------------------------------
   The listener in layouts/app.blade.php writes --mx/--my as percentages of
   the hovered card. The defaults keep the gradient centred, so a card that
   is reached by keyboard rather than pointer still looks deliberate.
   .u-modbox is deliberately absent: it already owns its ::after. */
.u-post, .u-numcard, .u-quote, .u-person, .u-mq-logo, .card,
.u-pcard, .u-ccard, .u-rpt-card, .u-step, .u-stat {
    position: relative; isolation: isolate;
}
.u-post::after, .u-numcard::after, .u-quote::after,
.u-person::after, .u-mq-logo::after, .card::after,
.u-pcard::after, .u-ccard::after, .u-rpt-card::after,
.u-step::after, .u-stat::after {
    content: ""; position: absolute; inset: 0; z-index: 3;
    border-radius: inherit; pointer-events: none;
    opacity: 0; transition: opacity .35s ease;
    background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
                rgba(var(--rgb-accent), .18), rgba(var(--rgb-accent), 0) 62%);
}
.u-post:hover::after, .u-numcard:hover::after, .u-quote:hover::after,
.u-person:hover::after, .u-mq-logo:hover::after, .card:hover::after,
.u-pcard:hover::after, .u-ccard:hover::after, .u-rpt-card:hover::after,
.u-step:hover::after, .u-stat:hover::after { opacity: 1; }

/* The pathway stage resets both its pseudo-elements further up so the
   connector chevron only ever belongs to the card that follows another.
   The sheen has to win that reset, which it does on source order — keep
   this block below the .u-step rules if either is ever moved. */
.u-step::after { content: ""; }

/* On the dark band the white-on-navy stat panels take the same glow; the
   sky accent reads as light falling on them rather than as a tint. */

/* ---- Button shine -------------------------------------------------------
   One pass of light across a solid button on hover. The band is skewed and
   wider than the gap it crosses, so it reads as a sweep, not a moving bar. */
.u-btn { position: relative; overflow: hidden; }
.u-btn-solid::before, .u-btn-sun::before, .u-btn-green::before,
.u-btn-clay::before, .u-btn-ink::before {
    content: ""; position: absolute; top: 0; bottom: 0; left: -140%;
    width: 60%; transform: skewX(-22deg); pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .34), transparent);
}
.u-btn-solid:hover::before, .u-btn-sun:hover::before, .u-btn-green:hover::before,
.u-btn-clay:hover::before, .u-btn-ink:hover::before { animation: u-shine .7s ease forwards; }
@keyframes u-shine { to { left: 160%; } }

/* The sweep sits under the label, so anything the button renders is lifted. */
.u-btn > * { position: relative; z-index: 1; }

/* ---- Section label ------------------------------------------------------
   The reference marks each section label with a small asterisk, not a dot.
   It breathes on opacity alone: scaling a text glyph reads as a wobble. */
.u-eyebrow::before {
    content: "\2217"; width: auto; height: auto; flex: 0 0 auto;
    border-radius: 0; background: none;
    font-size: 1.15em; line-height: 1; transform: translateY(.06em);
    animation: u-pulse 2.4s ease-in-out infinite;
}
@keyframes u-pulse { 0%, 100% { opacity: .4; } 50% { opacity: 1; } }

/* ---- Swipe rails --------------------------------------------------------
   Below the grid breakpoint a Bootstrap row of cards becomes a snapping
   horizontal rail. Phones get a gesture instead of a very long scroll, and
   the partial second card on screen is what tells the thumb to swipe. */
@media (max-width: 991.98px) {
    .u-rail {
        display: flex; flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch; scrollbar-width: none;
        /* Cancel the negative row gutters; the rail does its own spacing. */
        margin-left: 0; margin-right: 0;
        padding-bottom: 6px;
    }
    .u-rail::-webkit-scrollbar { display: none; }
    .u-rail > * { flex: 0 0 86%; max-width: 86%; scroll-snap-align: start; }
    /* A rail is swiped, not scrolled past, so the entry animation would fire
       for off-screen cards and leave them blank. */
    .u-rail > [data-aos],
    .u-rail > * { opacity: 1 !important; transform: none !important; }
}
@media (max-width: 575.98px) {
    .u-rail > * { flex: 0 0 90%; max-width: 90%; }
}

/* ---- Testimonial carousel ----------------------------------------------
   The swipe rail above is a phone affordance that switches off at 992px.
   .is-carousel keeps it on at every width, so the same snap points, the same
   momentum and the same dots serve the mouse, the thumb and the arrow keys —
   there is no second scroller to keep in step with the first.

   Widths are set here rather than left to Bootstrap's columns, because a
   flex rail ignores col-lg-4 anyway: three in view on a desktop, two on a
   tablet, one on a phone, each with a sliver of the next showing so the
   thing reads as having more in it. */
.u-rail.is-carousel {
    display: flex; flex-wrap: nowrap; overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
    margin-left: 0; margin-right: 0; padding-bottom: 6px;
}
/* No scroll-behavior: smooth here on purpose. The script already asks for
   smooth on a step and auto on a wrap, and a blanket CSS rule would animate
   the wrap too — a long slide back past every card the visitor just saw. It
   would also override itself when motion is turned off. */
.u-rail.is-carousel::-webkit-scrollbar { display: none; }
.u-rail.is-carousel > * {
    flex: 0 0 90%; max-width: 90%; scroll-snap-align: start;
    opacity: 1 !important; transform: none !important;
}
@media (min-width: 576px)  { .u-rail.is-carousel > * { flex-basis: 62%; max-width: 62%; } }
@media (min-width: 768px)  { .u-rail.is-carousel > * { flex-basis: 48%; max-width: 48%; } }
@media (min-width: 992px)  { .u-rail.is-carousel > * { flex-basis: 33.3333%; max-width: 33.3333%; } }

/* Quotes run to different lengths; stretched cards keep the row even. */
.u-tcar .u-rail.is-carousel > * { display: flex; }
.u-tcar .u-quote { width: 100%; }

/* The controls are the ones the logo strip and the gallery already use. */
.u-tcar .ctl { margin-top: 20px; }
.u-tcar .nav, .u-tcar .pause {
    display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: var(--r-pill); border: 1px solid var(--line);
    background: var(--surface); color: var(--body);
    font-size: 1rem; line-height: 1; cursor: pointer; margin: 0;
    transition: background .3s, color .3s, border-color .3s;
}
.u-tcar .nav:hover, .u-tcar .pause:hover {
    background: var(--brand); color: #fff; border-color: var(--brand);
}
.u-tcar .nav:focus-visible, .u-tcar .pause:focus-visible {
    outline: 3px solid var(--accent); outline-offset: 3px;
}

/* The rail's own dots are a phone-only thing by default; this carousel runs
   everywhere, so they do too. */
.u-tcar + .u-raildots, .u-tcar .u-raildots { display: flex; }

@media (prefers-reduced-motion: reduce) {
    /* Nothing moves on its own and nothing animates its way across, so the
       rail is just a row that wraps and the controls have no job left. */
    .u-rail.is-carousel { flex-wrap: wrap; overflow-x: visible; scroll-snap-type: none; }
    .u-rail.is-carousel > * { flex-basis: 100%; max-width: 100%; }
    @media (min-width: 992px) { .u-rail.is-carousel > * { flex-basis: 33.3333%; max-width: 33.3333%; } }
    .u-tcar .ctl { display: none; }
}

/* Dots under a rail, present only while the rail is a rail. */
.u-raildots { display: none; gap: 7px; justify-content: center; margin-top: 18px; }
@media (max-width: 991.98px) { .u-raildots { display: flex; } }
.u-raildots i {
    width: 7px; height: 7px; border-radius: 50%; background: var(--line);
    transition: width .25s, background .25s;
}
.u-raildots i.on { width: 22px; background: var(--brand); }

/* ---- Thumb bar ----------------------------------------------------------
   Phones are held one-handed. The three things anyone actually wants from a
   course site sit where the thumb already is. */
.u-thumbbar { display: none; }
@media (max-width: 991.98px) {
    .u-thumbbar {
        display: grid; grid-template-columns: repeat(3, 1fr);
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 1038;
        background: rgba(255, 255, 255, .92);
        backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
        border-top: 1px solid var(--line);
        padding-bottom: env(safe-area-inset-bottom, 0px);
        box-shadow: 0 -6px 20px rgba(var(--rgb-brand), .08);
    }
    .u-thumbbar a {
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        gap: 3px; padding: 10px 6px 9px; text-decoration: none;
        color: var(--body); font-size: .72rem; font-weight: 700; letter-spacing: .03em;
    }
    .u-thumbbar a i { font-size: 1.16rem; }
    .u-thumbbar a.wa { background: var(--whatsapp); color: var(--ink); }
    .u-thumbbar a.go { color: #fff; background: var(--brand); }
    .u-thumbbar a:active { background: var(--surface-2); }
    .u-thumbbar a.go:active { background: var(--brand-dark); }

    /* Clear the bar so the footer and the back-to-top button are not sat on. */
    body { padding-bottom: 62px; }

    /* An open soft keyboard shrinks the visual viewport but leaves a fixed
       bottom bar floating over the field being typed into. While any field
       has focus the bar steps out of the way. */
    html.kb .u-thumbbar { display: none; }
    html.kb body { padding-bottom: 0; }
    #backToTop { bottom: calc(62px + clamp(12px, 3vw, 20px)); }
}

/* ---- Filter chips -------------------------------------------------------
   Used on the course listing. Filtering is the most useful thing a visitor
   can do there, and doing it without a page reload is what stops the
   listing feeling like a printed prospectus. */
.u-chips { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.u-chip {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 9px 18px; border-radius: var(--r-pill);
    border: 1px solid var(--line); background: var(--surface);
    color: var(--body); font-size: .9rem; font-weight: 600;
    cursor: pointer; transition: background .2s, color .2s, border-color .2s, transform .15s;
}
.u-chip:hover { border-color: var(--brand); transform: translateY(-2px); }
.u-chip .n {
    font-size: .74rem; font-weight: 800; padding: 1px 7px; border-radius: var(--r-pill);
    background: var(--surface-2); color: var(--muted);
}
.u-chip[aria-pressed="true"] { background: var(--brand); border-color: var(--brand); color: #fff; }
.u-chip[aria-pressed="true"] .n { background: rgba(255, 255, 255, .22); color: #fff; }
.u-chip:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.u-filterable.is-out { display: none; }

/* ---- Wide-gutter rows --------------------------------------------------
   A Bootstrap row offsets itself by half its own gutter, but .container pads
   by half of ITS gutter, which stays 1.5rem. A .g-5 row (3rem) therefore
   hangs 12px past the container on each side — a real 4px page overflow at
   992px that body{overflow-x:hidden} was quietly swallowing. DESIGN.md asks
   for the layout fixed rather than hidden, so the container is told to use
   the same gutter its row does. */
.container:has(> .row.g-5),
.container:has(> .row.gx-5) { --bs-gutter-x: 3rem; }
/* The responsive variants only raise the gutter from their own breakpoint up,
   so the container has to match them there and not before. */
@media (min-width: 768px) {
    .container:has(> .row.g-md-5),
    .container:has(> .row.gx-md-5) { --bs-gutter-x: 3rem; }
}
@media (min-width: 992px) {
    .container:has(> .row.g-lg-5),
    .container:has(> .row.gx-lg-5) { --bs-gutter-x: 3rem; }
}
@media (min-width: 1200px) {
    .container:has(> .row.g-xl-5),
    .container:has(> .row.gx-xl-5) { --bs-gutter-x: 3rem; }
}

/* ---- Sliding tab indicator --------------------------------------------
   The pressed chip keeps its own colour for the no-JS and reduced-motion
   cases; when the glider is running it takes over the fill and the chip
   goes transparent, so the highlight travels instead of blinking. */
.u-chips { position: relative; }
.u-chips .glider {
    position: absolute; top: 0; left: 0; height: 0; width: 0;
    border-radius: var(--r-pill); background: var(--brand);
    transition: transform .3s cubic-bezier(.3, .9, .4, 1),
                width .3s cubic-bezier(.3, .9, .4, 1), opacity .2s ease;
    pointer-events: none; z-index: 0;
    /* Hidden until its measurement has been confirmed against the final
       fonts. Until then the pressed chip's own fill carries the look, so a
       stale measurement can never be seen sitting over a neighbour. */
    opacity: 0;
}
.u-chips.glider-ready .glider { opacity: 1; }
.u-chips.has-glider .u-chip { position: relative; z-index: 1; }
/* While the glider is still travelling the pressed chip has no fill of its
   own, so white-on-light would be unreadable for those 300ms. It keeps the
   normal dark label until .is-lit arrives, which JS adds when the glider
   finishes moving. */
.u-chips.has-glider .u-chip[aria-pressed="true"] {
    background: transparent; border-color: transparent; color: var(--body);
}
.u-chips.has-glider .u-chip[aria-pressed="true"] .n { background: var(--surface-2); color: var(--muted); }
/* Once it has arrived the chip takes the same fill the glider is already
   showing underneath. Nothing changes visually, but the element now owns a
   real background instead of borrowing a sibling's — which is what makes it
   honestly checkable rather than only looking right. */
.u-chips.has-glider .u-chip.is-lit {
    color: #fff; background: var(--brand); border-color: var(--brand);
}
.u-chips.has-glider .u-chip.is-lit .n { background: rgba(255, 255, 255, .22); color: #fff; }

/* ---- Filtered content change ----
   Hidden instantly, but arriving over 250ms so a track swap reads as a
   change rather than a jump cut.

   An animation, not a transition: these same cards carry the reveal engine's
   850ms transition, which is more specific and would swallow a 250ms one.
   Animations and transitions are separate, so the two no longer fight. */
@keyframes u-enter { from { opacity: 0; transform: translateY(10px); } }
.u-filterable.is-entering { animation: u-enter .25s cubic-bezier(.3, .9, .4, 1) both; }

/* ---- Pathway process flow ----------------------------------------------
   A numbered node per stage, sitting on a connector that fills in as the
   track arrives: left to right on a desktop, top to bottom on a phone. The
   shape is borrowed; none of the colour is. The rail, the nodes and the fill
   all come from this site's own tokens, and each track keeps the tone it
   already had — blue, teal, indigo — so the three stay told apart.

   Two pseudo-elements do the whole thing: ::before is the unlit rail and
   ::after is the lit part laid over it, scaled from 0 to 1. A transform
   rather than a width, so the fill is composited rather than relaid out on
   every frame.

   Mobile first: the vertical pipeline is the base, and the horizontal map
   takes over at 768px, which is where .u-steps becomes four columns. */
.u-steps {
    position: relative;
    /* The gutter the rail runs down, and where its centre sits inside it.
       Both live here so the rail and whatever rides it cannot drift apart. */
    --node-gutter: 34px;
    --rail-cx: 13px;
    padding-left: var(--node-gutter);
}
.u-steps::before,
.u-steps::after {
    content: "";
    position: absolute;
    left: calc(var(--rail-cx) - 2px); width: 4px;
    top: 10px; bottom: 10px;
    border-radius: 2px;
    z-index: 0;
}
.u-steps::before { background: var(--rx-line); }
.u-steps::after {
    transform-origin: top center;
    transition: transform .9s cubic-bezier(.3, .9, .4, 1);
}
.u-track.tone-blue   .u-steps::after { background: linear-gradient(180deg, var(--brand), var(--rx-teal)); }
.u-track.tone-teal   .u-steps::after { background: linear-gradient(180deg, var(--rx-teal), var(--rx-navy)); }
.u-track.tone-indigo .u-steps::after { background: linear-gradient(180deg, #3B3F8F, var(--brand)); }

html.rv .u-track .u-steps::after       { transform: scaleY(0); }
html.rv .u-track.rv-in .u-steps::after { transform: scaleY(1); }

.u-step { z-index: 1; }


/* Lit is the default state, so a visitor whose reveal engine never runs sees
   a finished flow rather than a grey one. */
.u-track.tone-blue   .u-step .stage { background: var(--brand);   border-color: var(--brand);   color: #fff; box-shadow: 0 0 0 5px var(--brand-pale); }
.u-track.tone-teal   .u-step .stage { background: var(--rx-teal); border-color: var(--rx-teal); color: #fff; box-shadow: 0 0 0 5px var(--rx-mint); }
.u-track.tone-indigo .u-step .stage { background: #3B3F8F;        border-color: #3B3F8F;        color: #fff; box-shadow: 0 0 0 5px #E6E8F7; }
/* The last stage is the destination, and takes the dark fill its card has. */
.u-track .u-step.is-last .stage {
    background: var(--rx-navy); border-color: var(--rx-navy);
    color: var(--rx-mint); box-shadow: 0 0 0 5px var(--rx-mint);
}

/* Waiting, and only while the reveal engine has still to reach this track. */
html.rv .u-track:not(.rv-in) .u-step .stage {
    background: var(--surface); border-color: var(--rx-line);
    color: var(--muted); box-shadow: none;
}

/* The nodes light in turn as the fill passes them, and each card follows its
   own node. */
html.rv .u-track.rv-in .u-step:nth-child(1) .stage { transition-delay: .12s; }
html.rv .u-track.rv-in .u-step:nth-child(2) .stage { transition-delay: .30s; }
html.rv .u-track.rv-in .u-step:nth-child(3) .stage { transition-delay: .48s; }
html.rv .u-track.rv-in .u-step:nth-child(4) .stage { transition-delay: .66s; }

@media (min-width: 768px) {
    .u-steps { padding-left: 0; padding-top: 52px; }

    /* The rail stops at the first and last node rather than running off the
       ends. With four equal columns a column centre is half a column in, and
       a column is (100% - three gaps) / 4 — so half of that is the inset. */
    .u-steps::before,
    .u-steps::after {
        top: 18px; bottom: auto; height: 4px; width: auto;
        left:  calc((100% - 3 * var(--step-gap)) / 8);
        right: calc((100% - 3 * var(--step-gap)) / 8);
    }
    .u-track.tone-blue   .u-steps::after { background: linear-gradient(90deg, var(--brand), var(--rx-teal)); }
    .u-track.tone-teal   .u-steps::after { background: linear-gradient(90deg, var(--rx-teal), var(--rx-navy)); }
    .u-track.tone-indigo .u-steps::after { background: linear-gradient(90deg, #3B3F8F, var(--brand)); }

    .u-steps::after { transform-origin: left center; }
    html.rv .u-track .u-steps::after       { transform: scaleX(0); }
    html.rv .u-track.rv-in .u-steps::after { transform: scaleX(1); }

    /* From 768px up the pill leaves the card and becomes the stop on the
       rail. Anchored by its centre, so its width — Grow is short, Senior is
       not — never shifts it off: -33px = the rail's centre at 20, less the
       52px of padding above the cards and the step's own 1px border. */
    .u-step .stage {
        position: absolute; z-index: 2;
        top: -33px; left: 50%;
        transform: translate(-50%, -50%);
        margin: 0;
    }

    /* Each card arrives just behind its own node. */
    html.rv .u-track.rv-in .u-step:nth-child(1) { transition-delay: .20s; }
    html.rv .u-track.rv-in .u-step:nth-child(2) { transition-delay: .38s; }
    html.rv .u-track.rv-in .u-step:nth-child(3) { transition-delay: .56s; }
    html.rv .u-track.rv-in .u-step:nth-child(4) { transition-delay: .74s; }
}

@media (prefers-reduced-motion: reduce) {
    html.rv .u-track .u-steps::after,
    html.rv .u-track.rv-in .u-steps::after { transform: none; transition: none; }
    .u-step .stage { transition: none; }
}

/* ---- Domain card feel ----
   Movement only on hover, never idle: the icon leans, the border takes the
   teal and the arrow steps forward. */
.u-rpt-card { position: relative; }
.u-rpt-card .ic { transition: transform .18s ease, background-color .18s ease; }
.u-rpt-card .go {
    position: absolute; right: 16px; bottom: 16px;
    color: var(--rx-teal); font-size: .9rem; opacity: 0;
    transform: translateX(-5px); transition: transform .18s ease, opacity .18s ease;
}
.u-rpt-card:hover .ic { transform: translateY(-3px) rotate(-7deg); }
.u-rpt-card:hover .go { opacity: 1; transform: none; }
.u-rpt-card.is-key:hover .go { color: var(--rx-mint); }

@media (prefers-reduced-motion: reduce) {
    .u-chips .glider { transition: none; }
    .u-filterable.is-entering { animation: none; }
    .u-rpt-card:hover .ic { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .u-post::after, .u-numcard::after, .u-quote::after,
    .u-person::after, .u-mq-logo::after, .card::after { display: none; }
    .u-btn-solid::before, .u-btn-sun::before, .u-btn-green::before,
    .u-btn-clay::before, .u-btn-ink::before { display: none; }
    .u-eyebrow::before { animation: none; opacity: .7; }
    .u-chip, .u-raildots i { transition: none; }
    .u-chip:hover { transform: none; }
}

/* =========================================================================
   ERROR PAGES — resources/views/errors/404 and 500
   ========================================================================= */
.u-errpage {
    background: radial-gradient(820px 520px at 80% -16%, rgba(var(--rgb-accent), .13), transparent 62%),
                var(--grad-banner);
    padding: clamp(64px, 10vw, 128px) 0;
    min-height: 68vh; display: grid; place-items: center;
}
.u-errbox { text-align: center; max-width: 720px; margin: 0 auto; position: relative; }

/* The status code sits behind the heading as a watermark rather than as the
   headline — the visitor needs the way out, not the number. */
.u-errbox .code {
    position: absolute; left: 50%; top: -14px; transform: translateX(-50%);
    font-family: 'Montserrat', sans-serif; font-weight: 500;
    font-size: clamp(7rem, 20vw, 13rem); line-height: 1;
    color: var(--brand); opacity: .07; pointer-events: none; user-select: none;
    z-index: 0;
}
.u-errbox > *:not(.code) { position: relative; z-index: 1; }
.u-errbox .u-measure { margin-left: auto; margin-right: auto; }

.u-errlinks {
    display: grid; gap: 12px; margin: 32px auto 0; max-width: 520px; text-align: left;
}
.u-errlink {
    display: flex; align-items: center; gap: 14px;
    padding: 15px 18px; border-radius: var(--r-md);
    background: var(--surface); border: 1px solid var(--line);
    text-decoration: none; color: var(--body);
    transition: transform .22s, box-shadow .22s, border-color .22s;
}
.u-errlink:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--accent); color: var(--body); }
.u-errlink .ic { font-size: 1.2rem; color: var(--brand); flex: 0 0 auto; }
.u-errlink > span {
    display: flex; flex-direction: column; flex: 1; line-height: 1.45;
    font-size: .88rem; color: var(--muted);
}
.u-errlink strong { color: var(--ink); font-size: 1rem; }
.u-errlink .go { color: var(--muted-2); transition: transform .22s, color .22s; }
.u-errlink:hover .go { transform: translateX(4px); color: var(--accent-text); }

/* =========================================================================
   IMAGE SETTLE
   Content images arrive at whatever speed the connection allows. Fading them
   in on decode stops the page snapping about as each one lands.
   ========================================================================= */
img[data-settle] { opacity: 0; transition: opacity .45s ease; }
img[data-settle].is-in { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
    .u-errlink, .u-errlink .go { transition: none; }
    .u-errlink:hover { transform: none; }
    img[data-settle] { opacity: 1; transition: none; }
}

/* =========================================================================
   COURSE CARD — the database-backed listing on /courses
   The whole tile is one link rather than a card with a button inside it, so
   the hit area matches what it looks like, and the image is what responds.
   ========================================================================= */
.u-ccard {
    display: flex; flex-direction: column; height: 100%;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); overflow: hidden;
    text-decoration: none; color: inherit;
    transition: transform .25s, box-shadow .25s, border-color .25s;
}
.u-ccard:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); border-color: var(--accent); color: inherit; }

.u-ccard .shot {
    position: relative; height: 172px; overflow: hidden;
    background: var(--grad-ink); display: grid; place-items: center;
}
.u-ccard.bio .shot { background: linear-gradient(135deg, var(--accent), var(--accent-dark)); }
.u-ccard .shot img {
    width: 100%; height: 100%; object-fit: cover;
    transition: transform .5s cubic-bezier(.22, .61, .36, 1);
}
.u-ccard:hover .shot img { transform: scale(1.07); }
.u-ccard .shot .watermark { font-size: 2.6rem; color: rgba(255, 255, 255, .4); }

/* A wash over the image so the pill stays legible whatever the photo is. */
.u-ccard .shot::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(var(--rgb-ink), .36) 0%, transparent 42%, rgba(var(--rgb-ink), .34) 100%);
    pointer-events: none;
}
.u-ccard .shot .kind {
    position: absolute; left: 14px; top: 14px; z-index: 1;
    background: rgba(255, 255, 255, .94); color: var(--brand);
    font-size: .72rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
    padding: 5px 11px; border-radius: var(--r-pill);
}

.u-ccard .inner { padding: 22px 22px 20px; display: flex; flex-direction: column; flex: 1; }
.u-ccard .inner h3 { font-size: 1.06rem; margin-bottom: 8px; }
.u-ccard .inner p { color: var(--muted); font-size: .94rem; line-height: 1.7; }
.u-ccard .facts { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 16px; }
.u-ccard .facts span {
    font-size: .8rem; padding: 4px 12px; border-radius: var(--r-pill);
    background: var(--surface-2); color: var(--body);
}
.u-ccard .facts span.on-accent { background: var(--accent-wash); color: var(--accent-text); }
.u-ccard .more {
    margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line-soft);
    display: flex; align-items: center; justify-content: space-between;
    font-weight: 700; color: var(--brand); font-size: .92rem;
}
.u-ccard .more i { transition: transform .25s; }
.u-ccard:hover .more i { transform: translateX(5px); }
.u-ccard:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
    .u-ccard, .u-ccard .shot img, .u-ccard .more i { transition: none; }
    .u-ccard:hover { transform: none; }
    .u-ccard:hover .shot img, .u-ccard:hover .more i { transform: none; }
}

/* =========================================================================
   REVEAL ENGINE
   Replaces AOS. AOS gave one motion (fade-up) and only where someone had
   remembered to put the attribute, which left whole pages static. This drives
   every repeating component on every page from one place, and keeps the
   existing data-aos attributes working as a direction hint.

   The hidden state hangs off html.rv, which the inline script in the <head>
   of layouts/app.blade.php sets. Nothing is hidden without JavaScript, and
   because the class lands before first paint there is no flash of content
   appearing and then being taken away again.

   KEEP IN STEP: the selector list below is mirrored by RV_SEL in
   layouts/app.blade.php. A component added to one must be added to the other.
   ========================================================================= */
html.rv [data-aos],
html.rv [data-rv],
html.rv .u-head,
html.rv .u-modbox,
html.rv .u-post,
html.rv .u-numcard,
html.rv .u-quote,
html.rv .u-person,
html.rv .u-ccard,
html.rv .u-track,
html.rv .u-errlink,
html.rv .u-chip,
html.rv .u-accred li,
html.rv .u-rpt,
html.rv .card,
html.rv .page-hero h1,
html.rv .faq-hero h1,
html.rv .page-hero .breadcrumb,
html.rv .section-title,
html.rv .section-subtitle {
    opacity: 0;
    transform: translate3d(0, 26px, 0);
    will-change: transform, opacity;
    /* One curve for the whole site: a quick start that settles rather than
       easing symmetrically, which is what makes it read as physical. */
    transition: opacity .85s cubic-bezier(.22, .68, .26, 1),
                transform .85s cubic-bezier(.22, .68, .26, 1),
                filter   .85s cubic-bezier(.22, .68, .26, 1);
}

/* Direction hints, written by the engine while the element is still at
   opacity 0, so swapping the start position is never visible. */
html.rv [data-rv="left"]  { transform: translate3d(-38px, 0, 0); }
html.rv [data-rv="right"] { transform: translate3d(38px, 0, 0); }
html.rv [data-rv="zoom"]  { transform: scale(.94); }
/* Cards lift and come forward slightly — the animated card-grid move. */
html.rv [data-rv="card"]  { transform: translate3d(0, 34px, 0) scale(.97); }
/* A wrapper whose heading carries the motion only needs to fade. */
html.rv [data-rv="soft"]  { transform: none; }

html.rv .rv-in {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    will-change: auto;
}

/* ---- Headline word reveal ----------------------------------------------
   The signature move across the animated-template galleries: the headline
   rises a word at a time instead of the block fading in. The engine splits
   text nodes only, so inline spans inside a heading keep their styling. */
.rv-w {
    display: inline-block;
    opacity: 0;
    transform: translate3d(0, .54em, 0);
    filter: blur(6px);
    /* Reference section headings slide up over 1s on a slightly springy
       curve, one word every 60ms. The overshoot is what gives it the
       bounce; keeping it on transform only leaves the text crisp. */
    transition: opacity 1s cubic-bezier(.3, 1.7, .4, 1),
                transform 1s cubic-bezier(.3, 1.7, .4, 1),
                filter 1s cubic-bezier(.3, 1.7, .4, 1);
    will-change: transform, opacity, filter;
}
/* The hero's words come in from the left instead, slower and tighter
   together — the reference staggers these 20ms apart over 1.2s. */
.mc-hero .rv-w {
    transform: translate3d(-.6em, 0, 0);
    transition: opacity 1.2s cubic-bezier(.25, 1, .5, 1),
                transform 1.2s cubic-bezier(.25, 1, .5, 1),
                filter 1.2s cubic-bezier(.25, 1, .5, 1);
}
.rv-w.rv-in { opacity: 1; transform: none; filter: none; will-change: auto; }

/* ---- Magnetic CTA -------------------------------------------------------
   The primary buttons lean a few pixels toward the pointer. Enough to feel
   responsive, not enough to make the target harder to hit. */
.u-btn.is-mag, .btn-apply.is-mag {
    transition: transform .18s cubic-bezier(.22, .68, .26, 1),
                background .2s, color .2s, box-shadow .2s, border-color .2s;
}

/* ---- Hero drift ---------------------------------------------------------
   The hero copy and the orbit part company slightly as the page scrolls off,
   which gives the fold some depth without a scroll library. */
.mc-drift { will-change: transform, opacity; }

@media (prefers-reduced-motion: reduce) {
    html.rv [data-aos],
    html.rv [data-rv],
    html.rv .u-head,
    html.rv .u-modbox,
    html.rv .u-post,
    html.rv .u-numcard,
    html.rv .u-quote,
    html.rv .u-person,
    html.rv .u-ccard,
    html.rv .u-track,
    html.rv .u-errlink,
    html.rv .u-chip,
    html.rv .u-accred li,
    html.rv .u-rpt,
    html.rv .card,
    html.rv .page-hero h1,
html.rv .faq-hero h1,
    html.rv .page-hero .breadcrumb,
    html.rv .section-title,
    html.rv .section-subtitle {
        opacity: 1; transform: none; transition: none; will-change: auto;
    }
    /* .mc-hero .rv-w is more specific than .rv-w, so it has to be named
       here too or the hero words stay shifted left under reduced motion. */
    .rv-w, .mc-hero .rv-w { opacity: 1; transform: none; filter: none; transition: none; }
    .mc-drift { transform: none !important; opacity: 1 !important; }
}

/* =========================================================================
   FLAT SURFACES — the mitconskills.com card treatment
   The sister site has no bordered, elevated cards at all: a panel is a flat
   #F6F6F6 fill with no border and no shadow, and it separates from the page
   by tone alone. Everything below overrides the bordered-and-lifted cards
   this site had, which is what made it look like a different product.
   Loaded last so it wins without editing the component definitions above.
   ========================================================================= */
.card,
.u-post,
.u-quote,
.u-person,
.u-numcard,
.u-mq-logo,
.u-mq-student,
.u-ccard,
.u-modbox,
.u-errlink {
    background: var(--surface-2);
    border: 0 !important;
    box-shadow: none !important;
}

/* Panels that sit ON the grey ground invert to white, so the two tones keep
   doing the separating rather than a border. */
.u-sec.paper .card,
.u-sec.paper .u-post,
.u-sec.paper .u-quote,
.u-sec.paper .u-person,
.u-sec.paper .u-numcard,
.u-sec.paper .u-ccard,
.u-sec.paper .u-modbox,
.u-sec.paper .u-mq-logo,
.u-sec.paper .u-mq-student {
    background: var(--surface);
}

/* Hover is a tone change and a small lift, not a drawn border. */
.card:hover,
.u-post:hover,
.u-quote:hover,
.u-person:hover,
.u-numcard:hover,
.u-ccard:hover,
.u-mq-logo:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md) !important;
    border-color: transparent !important;
}

/* Square like the sister site, except where a pill is the point. */
.card, .u-post, .u-quote, .u-person, .u-numcard, .u-ccard, .u-modbox,
.u-errlink, .u-mq-logo, .u-mq-student {
    border-radius: var(--r-lg);
}
/* Their accreditation logos sit on plain white with no frame. With no frame
   there is nothing for a shadow to sit under either, so hover is the lift
   alone — a shadow under a bare transparent PNG traces the logo's silhouette
   and looks like a printing fault. */
.u-accred img, .u-accred .mark {
    background: transparent; border: 0; box-shadow: none;
}

/* The key-numbers strip loses its rules and becomes four quiet columns. */
.u-keynums { border: 0; }

/* A heading set at weight 400 needs the measure kept short, or it reads thin
   across a wide column. The sister site holds its display lines to ~16 words. */
.u-display.u-measure, .u-h2.u-measure { max-width: 19ch; }
@media (min-width: 768px) { .u-display.u-measure, .u-h2.u-measure { max-width: 26ch; } }

/* Section labels on the sister site carry a small square bullet rather than
   the round pulsing dot this site used inside its chip. */
.u-eyebrow::before { width: auto; height: auto; flex: 0 0 auto; border-radius: 0; }

/* Meta lines — durations, dates, captions — are their lighter grey. */
.u-micro, .u-ccard .facts span { color: var(--muted); }

/* =========================================================================
   GALLERY — editorial mosaic, five photographs to a set

   Five is the composition, not just the page size: a lead tile two cells
   wide and two tall, with four supporting tiles beside it. Earlier passes
   tried a balanced column wall, which left every set looking like the same
   anonymous grid.

   The grid carries the proportions, so the tiles need no intrinsic height
   and nothing has to be measured in JavaScript. Photographs crop to fill
   their cell; the lightbox is where the uncropped frame lives.
   ========================================================================= */

/* The navbar link lands here by fragment when it comes from another page,
   and the sticky bar would otherwise sit on top of the heading. The in-page
   click takes its offset from the live navbar height in app.blade.php; this
   covers the browser's own jump on load. */
.u-gal { scroll-margin-top: 100px; }

.u-gal-stage { position: relative; }

.u-gal-grid {
    display: grid; gap: 14px;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(2, 1fr);
    aspect-ratio: 2.25 / 1;
    animation: u-enter .34s cubic-bezier(.3, .9, .4, 1) both;
}
.u-gal-grid[hidden] { display: none; }
/* The lead photograph. :first-child rather than a class, so the mosaic needs
   nothing from the markup beyond the order the admin already controls. */
.u-gal-grid > :first-child { grid-column: span 2; grid-row: span 2; }

/* Two across on a tablet: the lead runs the full width as a banner and the
   four others fall into a square below it. */
@media (max-width: 991.98px) {
    .u-gal-grid {
        grid-template-columns: repeat(2, 1fr);
        grid-template-rows: 1fr 1fr 1fr;
        aspect-ratio: 1 / 1.08;
    }
    .u-gal-grid > :first-child { grid-column: span 2; grid-row: span 1; }
}
/* One column on a phone. A fixed aspect-ratio would squash five photographs
   into a strip, so there the grid lets each tile keep a 4:3 cell instead. */
@media (max-width: 575.98px) {
    .u-gal-grid {
        grid-template-columns: 1fr; grid-template-rows: none;
        grid-auto-rows: auto; aspect-ratio: auto; gap: 12px;
    }
    .u-gal-grid > :first-child { grid-column: auto; grid-row: auto; }
    .u-gal-tile { aspect-ratio: 4 / 3; }
}

.u-gal-tile {
    position: relative; isolation: isolate;
    display: block; width: 100%; height: 100%;
    margin: 0; padding: 0; border: 0; overflow: hidden;
    border-radius: var(--r-md); background: var(--surface-2);
    cursor: pointer;
}
.u-gal-tile img {
    display: block; width: 100%; height: 100%;
    object-fit: cover;
    transition: transform .5s cubic-bezier(.3, .9, .4, 1);
}
.u-gal-tile:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* The caption rides a scrim only across the strip it occupies, so the
   photograph above it stays untouched. White on rgba(0,0,0,.72) over the
   brightest possible frame still measures 9.3:1. */
.u-gal-tile .tag {
    position: absolute; left: 12px; bottom: 12px; z-index: 2;
    max-width: calc(100% - 24px);
    padding: 6px 12px; border-radius: var(--r-pill);
    background: rgba(0, 0, 0, .72);
    color: #fff; font-size: .76rem; font-weight: 500; line-height: 1.3;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The expand badge is the tile's affordance: it says the tile opens rather
   than navigates. It is decorative, so the button also carries a text label
   for assistive technology. */
.u-gal-tile .zoom {
    position: absolute; top: 12px; right: 12px; z-index: 2;
    display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .92); color: var(--brand);
    font-size: .78rem;
    opacity: 0; transform: scale(.85);
    transition: opacity .25s ease, transform .25s cubic-bezier(.3, .9, .4, 1);
}
/* Touch has no hover, so there the badge is simply always on. */
@media (hover: hover) {
    .u-gal-tile:hover img { transform: scale(1.05); }
    .u-gal-tile:hover .zoom,
    .u-gal-tile:focus-visible .zoom { opacity: 1; transform: none; }
}
@media (hover: none) {
    .u-gal-tile .zoom { opacity: 1; transform: none; }
}

/* ---- Pager ---- */
/* ---- Gallery page -------------------------------------------------------
   The homepage shows the same photographs as a mosaic that pages five at a
   time; this is the whole set, four to a row, two rows at a time. Tiles are
   the mosaic's own .u-gal-tile — same crop, same hover, same lightbox — but
   the mosaic sizes them from its grid rows, so here they need a shape of
   their own. */
.u-galp-grid {
    display: grid;
    gap: 14px;
    grid-template-columns: 1fr;
}
@media (min-width: 576px) { .u-galp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 768px) { .u-galp-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 992px) { .u-galp-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.u-galp-grid .u-gal-tile { height: auto; aspect-ratio: 4 / 3; }
/* .u-gal-tile is display:block, which beats the browser's own rule for
   [hidden]; without this the rows waiting for Load more would all show. */
.u-galp-grid .u-gal-tile[hidden] { display: none; }

.u-galp-more { display: flex; justify-content: center; margin-top: clamp(26px, 3vw, 40px); }

.u-gal .ctl { margin-top: 18px; }
.u-gal .ctl .dots { display: flex; align-items: center; gap: 8px; }
.u-gal .ctl .dot {
    width: 10px; height: 10px; padding: 0;
    border-radius: var(--r-pill); border: 1px solid var(--line);
    background: var(--surface); cursor: pointer;
    transition: background .25s, border-color .25s, transform .25s;
}
.u-gal .ctl .dot[aria-selected="true"] {
    background: var(--brand); border-color: var(--brand); transform: scale(1.25);
}
.u-gal .ctl .dot:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* ---- Lightbox ----------------------------------------------------------
   Fixed to the viewport and above the sticky navbar, which sits at 1030. */
.u-lightbox {
    position: fixed; inset: 0; z-index: 1080;
    display: flex; align-items: center; justify-content: center;
    gap: clamp(8px, 2vw, 28px); padding: clamp(14px, 4vw, 48px);
    background: rgba(0, 0, 0, .92);
    animation: u-lb-in .22s ease both;
}
.u-lightbox[hidden] { display: none; }
@keyframes u-lb-in { from { opacity: 0; } }

.u-lightbox figure {
    margin: 0; min-width: 0; max-width: 100%;
    display: flex; flex-direction: column; align-items: center; gap: 16px;
    animation: u-lb-pop .28s cubic-bezier(.3, .9, .4, 1) both;
}
@keyframes u-lb-pop { from { opacity: 0; transform: scale(.97); } }
.u-lightbox img {
    display: block; max-width: 100%; max-height: 74vh;
    width: auto; height: auto; object-fit: contain;
    border-radius: var(--r-md); background: #000;
}
.u-lightbox figcaption { text-align: center; max-width: 62ch; }
.u-lightbox figcaption .t {
    display: block; color: #fff; font-size: .98rem; font-weight: 500; line-height: 1.5;
}
.u-lightbox figcaption .c {
    display: block; margin-top: 5px; color: var(--brand-light);
    font-size: .84rem; letter-spacing: .04em;
}
.u-lightbox figcaption .c:empty { display: none; }

.u-lightbox .close, .u-lightbox .step {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    width: 48px; height: 48px; padding: 0;
    border-radius: var(--r-pill);
    border: 1px solid rgba(255, 255, 255, .28);
    background: rgba(255, 255, 255, .10); color: #fff;
    font-size: 1.05rem; cursor: pointer;
    transition: background .25s, border-color .25s;
}
.u-lightbox .close:hover, .u-lightbox .step:hover {
    background: rgba(255, 255, 255, .22); border-color: rgba(255, 255, 255, .5);
}
.u-lightbox .close:focus-visible, .u-lightbox .step:focus-visible {
    outline: 3px solid var(--accent); outline-offset: 3px;
}
.u-lightbox .close {
    position: absolute;
    top: clamp(12px, 2.5vw, 28px); right: clamp(12px, 2.5vw, 28px);
}

/* On a phone the arrows sit under the picture rather than squeezing it. */
@media (max-width: 575.98px) {
    .u-lightbox { flex-wrap: wrap; align-content: center; }
    .u-lightbox figure { flex: 0 0 100%; order: 1; }
    .u-lightbox .step.prev { order: 2; }
    .u-lightbox .step.next { order: 3; }
    .u-lightbox img { max-height: 58vh; }
}

/* With motion off the sets stop advancing, so every photograph has to be
   reachable without the timer: the sets simply stack and the pager steps out.
   The lightbox stays — it is an action, not decoration. */
@media (prefers-reduced-motion: reduce) {
    .u-gal-grid { animation: none; }
    .u-gal-grid[hidden] { display: grid; }
    .u-gal-grid + .u-gal-grid { margin-top: 14px; }
    .u-gal-tile img { transition: none; }
    .u-gal .ctl { display: none; }
    .u-lightbox, .u-lightbox figure { animation: none; }
}

/* =========================================================================
   REELS & SHORTS — vertical clips embedded from Instagram and YouTube

   The two platforms do not agree on a shape. YouTube hands back a bare
   player, so its frame is exactly 9:16, the shape of the video. Instagram
   hands back a whole card — account header, like and comment row — and sets
   its own height over postMessage, which is taller than the video alone.
   Fighting that would mean cropping Instagram's attribution off, so the
   cards are top-aligned instead and each keeps its platform's proportions.
   ========================================================================= */
.u-clips-grid {
    display: grid;
    gap: clamp(18px, 2.4vw, 28px);
    grid-template-columns: 1fr;
    align-items: start;
}
/* Four to a row on a desktop, stepping down rather than letting a 9:16 card
   get too narrow to read. minmax(0, 1fr) and not 1fr: an iframe's own width
   must not be allowed to set the track. */
@media (min-width: 576px) { .u-clips-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 992px) { .u-clips-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1200px){ .u-clips-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.u-clip { display: flex; flex-direction: column; gap: 10px; min-width: 0; }

.u-clip .plat {
    display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
    background: var(--surface); color: var(--body);
    border: 1px solid var(--line); border-radius: var(--r-pill);
    padding: 6px 14px; font-size: .8rem; font-weight: 600;
}
.u-clip.is-instagram .plat i { color: #c13584; }
.u-clip.is-youtube   .plat i { color: #ff0000; }

.u-clip .media {
    position: relative;
    border-radius: var(--r-md); overflow: hidden;
    background: var(--surface-2); box-shadow: var(--shadow-sm);
}

/* YouTube takes the shape Instagram dictates, so the two cards are the same
   size. It cannot be the other way round: Instagram renders a reel in a 4:5
   window and the only thing under it is the like/comment furniture that was
   deliberately cut, so stretching that card to 9:16 would put the furniture
   straight back. Matching the other way costs the Short nothing it cannot
   spare — the player letterboxes the video inside the box and keeps every
   frame of it, just drawn smaller. Black, because the player's own bars are
   black and the box should read as one frame. */
.u-clip.is-youtube .media {
    padding-top: 54px;                 /* mirrors Instagram's account bar */
    background: #000;
}
.u-clip.is-youtube .media::before {
    content: "";
    display: block;
    aspect-ratio: 4 / 5;               /* the same window Instagram uses */
}
/* The frame fills the whole box, the 54px included: that padding is only
   here to add the height, not to reserve a strip. */
.u-clip.is-youtube iframe {
    position: absolute; inset: 0;
    display: block; width: 100%; height: 100%; border: 0;
}

/* Instagram: show the account bar and the reel, and stop there.

   Under the reel Instagram's embed stacks a like/comment/share bar, a like
   count and an "Add a comment" row. That is a copy of the Instagram app
   inside a page about courses, and none of it does anything useful here —
   every control in it just sends you to Instagram, which the link under the
   card already does. It lives inside a cross-origin iframe, so it cannot be
   styled away; the frame is cut to the height of the part worth keeping.

   The numbers are measured from the embed itself, not guessed:
     . the account bar (.Header) is 54px, at every width
     . the media sits directly under it, at a ratio of exactly 1.25 — the
       embed renders a reel in a 4:5 window, not at 9:16, through a
       padding-bottom trick that holds that ratio at any width
     . what follows is 154px of app furniture, which is what gets cut
   So the frame is 54px plus a 4:5 box, and the iframe is held to that height
   with !important so Instagram's own postMessage height cannot push it back.

   The !importants on width also beat the inline min-width:326px embed.js
   writes, which would otherwise overflow a narrow column. */
.u-clip.is-instagram .media {
    position: relative;
    overflow: hidden;
    padding-top: 54px;                 /* the account bar */
    background: var(--surface);
    box-shadow: var(--shadow-sm);
}
.u-clip.is-instagram .media::before {
    content: "";
    display: block;
    aspect-ratio: 4 / 5;               /* the reel, as the embed frames it */
}
.u-clip.is-instagram blockquote.u-ig-pending {
    border: 0; padding: 0; background: transparent;
}
/* embed.js does not take the blockquote away when it builds the iframe — it
   retags it and leaves it in the flow, where it was quietly adding 45px to
   the box and making this card taller than the YouTube one beside it.
   Matched by "there is an iframe now" rather than by the class Instagram
   happens to retag it with, which is theirs to change. While embed.js has
   yet to run, or if a blocker eats it, there is no iframe and the blockquote
   stays put with its link. */
.u-clip.is-instagram .media:has(iframe) blockquote { display: none; }
.u-clip.is-instagram .instagram-media,
.u-clip.is-instagram blockquote.u-ig-pending {
    position: absolute !important;
    top: 0 !important; left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    min-width: 0 !important;
    max-width: none !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}
/* The link that stands in for the embed: before its batch is handed over,
   and for good if a blocker eats embed.js. */
.u-clip.is-instagram blockquote.instagram-media > a,
.u-clip.is-instagram blockquote.u-ig-pending > a {
    display: block; padding: 22px 18px; text-align: center;
    color: var(--brand); font-weight: 600; font-size: .92rem;
}

.u-clip .src {
    display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
    color: var(--brand); font-size: .88rem; font-weight: 600; text-decoration: none;
}
.u-clip .src:hover { text-decoration: underline; }
.u-clip .src i { font-size: .78rem; }

/* Two rows are shown; the rest arrive from here, eight at a time. */
.u-clips-more { display: flex; justify-content: center; margin-top: clamp(26px, 3vw, 40px); }
.u-clip[hidden] { display: none; }
.u-clip:focus { outline: none; }
.u-clip:focus-visible { outline: 3px solid var(--accent); outline-offset: 6px; border-radius: var(--r-md); }

/* =========================================================================
   POLICY PAGE — long-form text, read rather than scanned
   ========================================================================= */
.u-policy { max-width: 760px; margin-inline: auto; }
.u-policy h2 {
    font-family: 'Montserrat', sans-serif; font-weight: 600;
    font-size: 1.22rem; color: var(--ink);
    margin: 38px 0 12px; padding-top: 24px;
    border-top: 1px solid var(--line);
}
.u-policy h2:first-of-type { border-top: 0; padding-top: 0; margin-top: 26px; }
.u-policy p { color: var(--body); line-height: 1.75; margin-bottom: 14px; }
.u-policy ul { color: var(--body); line-height: 1.75; padding-left: 22px; margin-bottom: 16px; }
.u-policy li { margin-bottom: 6px; }
.u-policy a { color: var(--brand); }
.u-policy code {
    background: var(--surface-alt); border: 1px solid var(--line);
    border-radius: 5px; padding: 1px 6px; font-size: .88em; color: var(--ink);
}
/* The one thing on this page that still needs the institute's own answer. */
.u-policy mark {
    background: var(--accent-wash); color: var(--ink);
    border-radius: 5px; padding: 2px 6px;
}
