/* AUSTCPD landing - design system */
.au{
  --ground:#FBF9F6; --ink:#0B0B0C; --ink-2:#2A2724; --muted:#6B6259;
  --line:#E3DCD3; --surface:#FFFFFF; --surface-2:#F4EFE8;
  --brand:#CC5500; --hot:#FF6900; --wash:#FDF0E6;
  --display:"Sora",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --body:"Inter",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:ui-monospace,"SF Mono","Cascadia Mono","Roboto Mono",Menlo,Consolas,monospace;
  --s1:8px;--s2:16px;--s3:24px;--s4:32px;--s5:48px;--s6:72px;--s7:104px;
  background:var(--ground); color:var(--ink); font-family:var(--body); font-size:16px; line-height:1.6;
}
.au *{box-sizing:border-box}
.au .wrap{max-width:1240px;margin:0 auto;padding:0 var(--s3)}
.au h1,.au h2,.au h3,.au h4{margin:0;font-family:var(--display);text-wrap:balance;letter-spacing:-.03em;line-height:1.05;font-weight:800;color:var(--ink)}
.au p{margin:0}
.au a{color:inherit;text-decoration:none}
.au :focus-visible{outline:2px solid var(--hot);outline-offset:3px}
.au img{max-width:100%;display:block}
.au .eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--brand);font-weight:600}
.au section{padding:var(--s7) 0}
.au .head{display:flex;align-items:flex-end;gap:var(--s4);flex-wrap:wrap;margin-bottom:var(--s5)}
.au .head h2{font-size:clamp(30px,4vw,46px);max-width:19ch;margin-top:12px}
.au .head .sub{color:var(--muted);max-width:44ch;margin-left:auto;font-size:15px}
.au .btn{display:inline-flex;align-items:center;gap:8px;font-family:var(--body);font-weight:700;font-size:14px;
  padding:12px 22px;border:1.5px solid var(--brand);background:var(--brand);color:#fff;
  transition:background .15s,transform .15s,color .15s;cursor:pointer}
.au .btn:hover{background:var(--hot);border-color:var(--hot);transform:translateY(-1px);color:#fff}
.au .btn.ghost{background:transparent;color:var(--brand)}
.au .btn.ghost:hover{background:var(--brand);color:#fff}
.au .btn.onDark{border-color:rgba(255,255,255,.25);background:rgba(255,255,255,.10);color:#fff}
.au .btn.onDark:hover{background:#fff;color:#0B0B0C;border-color:#fff}
.au .btn.sm{padding:9px 16px;font-size:13px}

/* hero */
.au-hero{position:relative;background:#0B0B0C;color:#fff;overflow:hidden}
.au-hero__bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.au-hero__veil{position:absolute;inset:0;background:linear-gradient(90deg,rgba(11,11,12,.90) 0%,rgba(11,11,12,.62) 46%,rgba(11,11,12,.24) 100%)}
.au-hero__in{position:relative} /* vertical padding set further down, scoped as .au .au-hero__in */
.au-hero h1{font-size:clamp(40px,7vw,88px);letter-spacing:-.045em;max-width:16ch;margin:var(--s3) 0 0;color:#fff}
.au-hero h1 em{font-style:normal;color:var(--hot)}
.au-hero .lede{margin-top:var(--s3);max-width:56ch;font-size:clamp(16px,1.5vw,19px);color:#D6D0C8}
.au-hero .cta{display:flex;gap:12px;margin-top:var(--s5);flex-wrap:wrap}
.au-hero .meta{display:flex;gap:var(--s5);flex-wrap:wrap;margin-top:var(--s6);padding-top:var(--s3);border-top:1px solid rgba(255,255,255,.12)}
.au-hero .meta .n{font-family:var(--mono);font-size:15px;font-weight:700;color:#fff;margin-top:3px}
.au-hero .meta .l{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:#9C948C}

/* value props */
.au-props{display:grid;grid-template-columns:repeat(4,1fr);border-left:1px solid var(--line)}
.au-props>div{padding:var(--s4) var(--s3);border-right:1px solid var(--line);border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--surface)}
.au-props h3{font-size:18px;margin-bottom:8px}
.au-props p{color:var(--muted);font-size:14px}
.au-props .k{font-family:var(--mono);font-size:10px;letter-spacing:.18em;color:var(--brand);display:block;margin-bottom:var(--s2)}
@media(max-width:900px){.au-props{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.au-props{grid-template-columns:1fr;border-left:0}.au-props>div{border-right:0}}

/* about */
.au-about{display:grid;grid-template-columns:1.05fr .95fr;gap:var(--s6);align-items:center}
.au-about img{width:100%;aspect-ratio:4/3;object-fit:cover;border:1px solid var(--line)}
.au-modes{display:grid;gap:var(--s3);margin-top:var(--s4)}
.au-mode{display:grid;grid-template-columns:auto 1fr;gap:var(--s3);padding:var(--s3);border:1px solid var(--line);background:var(--surface)}
.au-mode .num{font-family:var(--mono);font-size:11px;color:var(--brand);letter-spacing:.12em;white-space:nowrap}
.au-mode h4{font-size:17px;margin-bottom:6px}
.au-mode p{color:var(--muted);font-size:14px}
@media(max-width:900px){.au-about{grid-template-columns:1fr;gap:var(--s4)}}

/* contact */
.au-contact{display:grid;grid-template-columns:repeat(3,1fr)}
.au-contact>div{padding:var(--s4);border:1px solid var(--line);margin-left:-1px;background:var(--surface);display:flex;flex-direction:column;gap:var(--s2)}
.au-contact h3{font-size:19px}
.au-contact p{color:var(--muted);font-size:14px;flex:1}
.au-contact .big{font-family:var(--mono);font-size:21px;font-weight:700;color:var(--ink);letter-spacing:-.02em}
@media(max-width:900px){.au-contact{grid-template-columns:1fr}.au-contact>div{margin-left:0;margin-top:-1px}}

/* course cards */
.au-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s3)}
@media(max-width:1000px){.au-cards{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){.au-cards{grid-template-columns:1fr}}
.au-card{display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--line);
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease;height:100%}
.au-card:hover{transform:translateY(-5px);box-shadow:0 14px 30px rgba(17,17,17,.11);border-color:var(--brand)}
.au-card__media{overflow:hidden;line-height:0}
.au-card__media img{width:100%;aspect-ratio:16/9;object-fit:cover;filter:saturate(.9) contrast(1.03);transition:transform .5s ease,filter .3s ease}
.au-card:hover .au-card__media img{transform:scale(1.05);filter:saturate(1) contrast(1.05)}
.au-card__body{padding:var(--s3);display:flex;flex-direction:column;flex:1;gap:10px}
.au-card h3{font-size:19px;line-height:1.25}
.au-card p{color:var(--muted);font-size:14px;flex:1}
.au-card__facts{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:6px 12px;margin-top:2px;padding-top:12px;border-top:1px solid var(--line);font-family:var(--mono);font-size:12.5px;letter-spacing:.01em}
.au-card__facts .dur{color:var(--muted);white-space:nowrap}
.au-card__facts .fee{color:var(--ink);font-weight:700;white-space:nowrap}
.au-card .go{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--brand);letter-spacing:.06em;margin-top:4px}
.au-card:hover .go{color:var(--hot)}
.au-more{display:flex;justify-content:center;margin-top:var(--s5)}
/* keep the #fees anchor from being hidden under the sticky header when jumped to */
.au-anchor{display:block;position:relative;top:-90px;visibility:hidden;height:0}

/* fees */
.au-tableWrap{overflow-x:auto;border:1px solid var(--line);background:var(--surface)}
.au table{width:100%;border-collapse:collapse;min-width:560px}
.au th,.au td{text-align:left;padding:14px var(--s3);border-bottom:1px solid var(--line);font-size:15px}
.au th{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);font-weight:600;background:var(--surface-2)}
.au tbody tr:last-child td{border-bottom:0}
.au tbody tr:hover{background:var(--wash)}
.au td.fee{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:700;white-space:nowrap}
.au td.t{font-weight:600}

/* partners */
.au-partners{background:var(--surface);border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:var(--s6) 0}
.au-logos{display:grid;grid-template-columns:repeat(8,1fr);gap:var(--s4);align-items:center;margin-top:var(--s4)}
.au-logos img{width:100%;height:auto;object-fit:contain;filter:grayscale(1);opacity:.7;transition:opacity .2s,filter .2s}
.au-logos img:hover{opacity:1;filter:grayscale(0)}
@media(max-width:900px){.au-logos{grid-template-columns:repeat(4,1fr)}}

/* testimonials */
/* sticky stacked cards (scroll-stack).
   Each card is sticky at the SAME top offset inside one shared parent, so card 1
   pins at centre and STAYS pinned while 2, 3, 4 come to rest on top of it. The
   pile releases when the parent's bottom edge passes. Pure CSS: works with JS off.
   JS (au_stack_script in austcpd-landing.php) only adds the depth fade/scale. */
.au-quotes.au-stack{
  display:block;
  max-width:720px;
  margin-inline:auto;
  --au-card-h:280px;          /* JS overwrites with the measured tallest card */
  --au-runway:24vh;           /* JS overwrites - see THE RUNWAY IS SIZED BY THE PEEK */
  --au-peek:8px;              /* how far a covered card lifts, per depth level */
}
/* THE RUNWAY IS SIZED BY THE PEEK, NOT PICKED BY EYE.
   The gap between two cards decides how far the next one sits below the fold while
   the current one is parked at centre. At the old 70vh the next card's top landed
   323px past the bottom edge (measured, 1440x900), so a third of every card's 917px
   advance was scroll in which literally nothing on screen moved - which is exactly
   what read as "stuck", and it left no cue that anything came next.
   au_stack_script now solves the gap for a target peek instead:
       rest top  = vh/2 - cardH/2
       next top  = rest top + cardH + runway    <- we want this at (vh - peek)
       runway    = vh/2 - peek - cardH/2
   so a sliver of the next card is ALWAYS showing at the bottom of the viewport.
   Keep the CSS value as a no-JS fallback only; do not tune the effect here. */
.au-quotes.au-stack > .au-quote{
  position:sticky;
  top:calc(50vh - (var(--au-card-h) / 2));
  /* the runway sits ABOVE each card, never below it - see THE LAST CARD'S RUNWAY. */
  margin:var(--au-runway) 0 0;
  transform-origin:50% 0%;
  /* NO transition. --d and --a are recomputed from the scroll position every animation
     frame, so a transition here only makes the cards lag behind the wheel. The old
     .25s ease-out was animating a THRESHOLD snap; there is no threshold any more. */
  will-change:transform,opacity;
}
/* THE RUNWAY GOES ABOVE THE CARDS, NOT BELOW - read this before rearranging it.
   A sticky box is constrained so that its MARGIN box stays inside the containing
   block, so a card's own margin-BOTTOM shortens that card's travel by exactly the
   space it adds: it is self-cancelling. With margin-bottom runways the last card
   started flush against the constraint edge and could never be displaced at all -
   it never pinned, and the pile released the instant it reached centre (measured on
   staging: 80px at centre, about one wheel flick - that is what read as "skipped").
   Cards 0..n-1 were merely short-changed by one runway each, so they let go before
   the last card had finished and the stack visibly fell apart above it.
   (display:flow-root on the parent does NOT fix this. It stops the last margin
   collapsing out, which does lengthen the earlier cards, but the last card's own
   margin still eats every pixel it adds.)
   Runway as margin-TOP fixes both: every card now has margin-bottom 0, so all four
   share one constraint edge and stay pinned until the pile releases together. The
   final runway - the beat the last card holds at centre - cannot be a margin at all;
   it is an in-flow ::after spacer, space no card owns. Total scroll length is
   unchanged: n runways either way. */
.au-quotes.au-stack > .au-quote:first-child{margin-top:0}
/* The last card's beat at centre. This one is NOT like the others: every card before
   it has a next card rising behind it, so its dwell always has motion in it. The last
   card has nothing behind it - the thing that has to rise is the NEXT SECTION - so a
   beat sized as one full advance just freezes the screen. Measured on staging
   2026-08-24: 312px desktop / 354px mobile of completely motionless scroll, which is
   the original "feels stuck" complaint relocated to the end of the stack.
   JS now derives the beat from where the next section actually sits and writes
   --au-lastbeat; see THE LAST CARD'S BEAT in the stack script. Do not tune it here.
   The fallback is the no-JS value and stays deliberately generous. */
.au-quotes.au-stack::after{content:"";display:block;height:var(--au-lastbeat, calc(var(--au-card-h) + var(--au-runway)))}
/* Depth and arrival - both CONTINUOUS 0..n, rewritten by JS every frame.
     --d  how deep this card sits under the pile. Fractional while the next card is
          still on its way up, so the pile recedes smoothly with the scroll instead
          of snapping one whole level at a threshold.
     --a  how far THIS card has arrived at centre: 0 while it is only a sliver at the
          bottom edge, 1 at rest. The sliver is scaled back a little so it reads as
          "behind, coming forward" rather than as a stray box.
   Defaults (--d:0, --a:1) are the identity transform, so with JS off this is a plain
   pinned stack with no depth effect and nothing looks broken. */
.au-quotes.au-stack > .au-quote{
  transform:
    translateY(calc(var(--au-peek) * -1 * var(--d,0)))
    scale(calc(1 - (.035 * var(--d,0)) - (.03 * (1 - var(--a,1)))));
  opacity:calc(1 - (.2 * var(--d,0)));
}
@media(max-width:840px){
  .au-quotes.au-stack{--au-runway:18vh;--au-peek:6px;max-width:none}
  .au-quotes.au-stack > .au-quote{padding:var(--s3)}
}
/* reduced motion / no-stack fallback: plain list, no pinning at all */
@media (prefers-reduced-motion:reduce){
  .au-quotes.au-stack > .au-quote{
    position:static;margin:0 0 var(--s3);transform:none;opacity:1;transition:none;
  }
  .au-quotes.au-stack > .au-quote:last-child{margin-bottom:0}
  .au-quotes.au-stack::after{display:none}   /* no pinning, so no runway to reserve */
}
/* "What our participants say." stays on screen for the whole stack.
   It used to scroll away ~200px in and be gone for the remaining ~2,500px, so the
   reader was left with cards pinning at centre and no label for what they were.
   z-index 5 beats the cards' inline z-index 1..4 - .au-quotes is unpositioned, so the
   cards sit in .wrap's stacking context, not in one of their own. The --ground fill
   keeps the heading legible if a tall card on a short viewport rides up under it. */
#voices .head{
  position:sticky;
  top:78px;                 /* clears the 62px fixed .au-hd */
  z-index:5;
  background:var(--ground);
  padding-block:12px;
}
@media(max-width:840px){
  #voices .head{ top:70px; padding-block:8px }
}
@media (prefers-reduced-motion:reduce){
  #voices .head{ position:static; background:none; padding-block:0 }
}
.au-quote{border:1px solid var(--line);background:var(--surface);padding:var(--s4);display:flex;flex-direction:column;gap:var(--s3)}
.au-quote .mk{font-family:var(--mono);color:var(--brand);font-size:26px;line-height:1}
.au-quote p{font-size:16.5px;color:var(--ink-2);line-height:1.6;flex:1}
.au-who{display:flex;align-items:center;gap:14px;border-top:1px solid var(--line);padding-top:var(--s3)}
.au-who img{width:44px;height:44px;border-radius:50%;object-fit:cover;flex:0 0 auto}
.au-who .n{font-weight:700;font-size:15px}
.au-who .r{font-family:var(--mono);font-size:11px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase}

/* stats */
.au-stats{display:grid;grid-template-columns:repeat(3,1fr);border-left:1px solid var(--line)}
.au-stats>div{padding:var(--s5) var(--s3);border-right:1px solid var(--line);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.au-stats .n{font-family:var(--mono);font-size:clamp(34px,4.6vw,54px);font-weight:700;color:var(--brand);letter-spacing:-.03em;line-height:1}
.au-stats .l{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);margin-top:10px}
@media(max-width:840px){.au-stats>div{padding:var(--s4) var(--s1)}.au-stats .n{font-size:clamp(24px,6.4vw,34px)}.au-stats .l{font-size:9px;letter-spacing:.12em}}

/* app band */

@media(max-width:767px){
  .au section{padding:var(--s5) 0}
}
@media (prefers-reduced-motion:reduce){.au *{transition:none!important}}

/* ---- full-bleed: neutralise the theme content container for this template only ---- */
.page-template-austcpd-landing #content.site-content > .ast-container,
.page-template-austcpd-landing .site-content > .ast-container{
  max-width:100%; width:100%; padding-left:0; padding-right:0; display:block;
}
.page-template-austcpd-landing #primary,
.page-template-austcpd-landing .entry-content,
.page-template-austcpd-landing .ast-article-single,
.page-template-austcpd-landing .site-main{
  margin:0; padding:0; width:100%; max-width:100%;
}
.page-template-austcpd-landing .entry-content > .au{ margin:0 }
.page-template-austcpd-landing .ast-single-post .entry-header,
.page-template-austcpd-landing .entry-title,
.page-template-austcpd-landing .ast-single-entry-banner{ display:none }
.page-template-austcpd-landing #content{ padding:0 }
/* Horizontal clipping lives on html ONLY, and body is forced back to visible.
   Why: the root element's overflow propagates to the viewport, so html alone still clips
   horizontal overflow. But when html is not visible, body's own overflow is NOT propagated
   - it applies to body itself and makes it a scroll container, which silently disables
   position:sticky in every descendant. That is what broke the testimonials scroll-stack.
   The theme and ElementsKit both ship a plain `body{overflow-x:hidden}` and an
   `html,body{overflow-x:hidden}`, so removing our own body rule is not enough - this
   override has to out-specify them. Do NOT set overflow-x on body for this template. */
html.page-template-austcpd-landing{ overflow-x:hidden }
body.page-template-austcpd-landing{ overflow-x:visible }

/* ---- hero breathing room ----
   NOTE: .au-hero__in also carries .wrap, and `.au .wrap{padding:0 var(--s3)}`
   (specificity 0,2,0) beat the old single-class `.au-hero__in` rules, so the
   hero's vertical padding was computing to 0 — the eyebrow sat flush under the
   navbar and the meta row sat flush against the next section. These rules are
   scoped with `.au ` so they match that specificity and win on source order. */
.au .au-hero__in{
  padding-top:clamp(80px,8vw,120px);
  padding-bottom:clamp(64px,6.5vw,96px);
}
.au-hero .eyebrow{ display:block; margin-bottom:4px }
@media (max-width:767px){
  .au .au-hero__in{ padding-top:72px; padding-bottom:56px }
}
/* anchor jumps shouldn't land under the sticky header either */
.au [id]{ scroll-margin-top:96px }

/* ---- partners: bolder logos, endless marquee ---- */
.au-partners{ padding:var(--s6) 0; overflow:hidden }
.au-marquee{
  position:relative;
  margin-top:var(--s4);
  overflow:hidden;
  /* fade the ends so logos enter and leave rather than getting cut */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
}
.au-marquee__track{
  display:flex;
  align-items:center;
  gap:clamp(40px,6vw,88px);
  width:max-content;
  will-change:transform;
  animation:au-marquee 38s linear infinite;
}
.au-marquee:hover .au-marquee__track{ animation-play-state:paused }
.au-marquee__item{
  flex:0 0 auto;
  display:flex;
  align-items:center;
  justify-content:center;
}
.au-marquee__item img{
  height:clamp(52px,6vw,76px);
  width:auto;
  max-width:none;
  object-fit:contain;
  /* bolder: full colour, full opacity, slight punch */
  filter:contrast(1.08) saturate(1.06);
  opacity:1;
  transition:transform .2s ease;
}
.au-marquee__item img:hover{ transform:scale(1.06) }

@keyframes au-marquee{
  from{ transform:translateX(0) }
  to  { transform:translateX(-50%) }
}
@media (max-width:767px){
  .au-marquee__track{ gap:36px; animation-duration:26s }
  .au-marquee__item img{ height:46px }
}
@media (prefers-reduced-motion:reduce){
  .au-marquee__track{ animation:none; flex-wrap:wrap; justify-content:center; width:auto }
}

/* ================= FIXES ================= */

/* --- 1. Section headings: align heading and subtitle consistently (left, stacked).
       The previous split (h2 left / sub pushed right by margin-left:auto) read as
       accidental misalignment. Applies to all six section heads. --- */
.au .head{
  display:block;
  margin-bottom:var(--s5);
}
.au .head > div{ max-width:none }
.au .head h2{ max-width:22ch; margin-top:12px }
.au .head .sub{
  margin-left:0;
  margin-top:16px;
  max-width:62ch;
}

/* --- 2. Partner logos: double size --- */
.au-marquee__item img{
  height:clamp(96px,10vw,140px) !important;
  width:auto;
  max-width:none;
}
@media (max-width:767px){
  .au-marquee__item img{ height:80px !important }
}

/* --- 3. Marquee: seamless loop.
   `gap` on the track is applied BETWEEN items only, so the two halves are not
   identical in width - the trailing gap is missing from the second half and the
   -50% reset lands a gap short, which reads as a stutter. Spacing each item with
   its own margin-right makes both halves byte-identical in width. --- */
.au-marquee__track{
  gap:0 !important;
  animation:au-marquee-smooth 44s linear infinite;
  backface-visibility:hidden;
  transform:translate3d(0,0,0);
}
.au-marquee__item{
  margin-right:clamp(40px,6vw,88px);
}
.au-marquee:hover .au-marquee__track{ animation-play-state:paused }

@keyframes au-marquee-smooth{
  from{ transform:translate3d(0,0,0) }
  to  { transform:translate3d(-50%,0,0) }
}
@media (max-width:767px){
  .au-marquee__item{ margin-right:36px }
  .au-marquee__track{ animation-duration:30s }
}
@media (prefers-reduced-motion:reduce){
  .au-marquee__track{ animation:none; flex-wrap:wrap; justify-content:center; width:auto }
}

/* --- partner logos: larger again --- */
.au-marquee__item img{
  height:clamp(132px,13vw,190px) !important;
}
.au-partners{ padding:clamp(64px,7vw,96px) 0 }
.au-marquee__track{ animation-duration:52s }
@media (max-width:767px){
  .au-marquee__item img{ height:104px !important }
  .au-marquee__track{ animation-duration:34s }
}

/* --- partners: match the live site's logo scale, tighten the band --- */
.au-partners{
  padding:clamp(28px,3vw,44px) 0 !important;   /* was ~96px top+bottom - band was far too tall */
}
.au-marquee{ margin-top:var(--s2) }
.au-marquee__item img{
  height:clamp(150px,15vw,205px) !important;   /* live renders these squares at ~200px */
}
.au-marquee__track{ animation-duration:56s }
@media (max-width:767px){
  .au-partners{ padding:24px 0 !important }
  .au-marquee__item img{ height:112px !important }
  .au-marquee__track{ animation-duration:36s }
}

/* ---- hero legibility ----
   The veil is a HORIZONTAL gradient (90% left -> 24% right). That suits the desktop
   layout, where copy occupies the left 56ch and the clear right side shows the video.
   On narrow screens the copy runs full-width, so line ends sit over the 24% zone -
   essentially unveiled video - and the warm-grey text disappears against bright frames.
   Fix: a vertical, uniformly strong veil below 1024px, brighter text, and a shadow
   as insurance against whatever frame the video happens to be on. */

/* brighter copy at every size - #D6D0C8 was too low-contrast over moving video */
.au-hero .lede{
  color:#F2EEE8;
  font-weight:450;
  text-shadow:0 1px 14px rgba(0,0,0,.55);
}
.au-hero h1{ text-shadow:0 2px 20px rgba(0,0,0,.5) }
.au-hero .eyebrow{ text-shadow:0 1px 10px rgba(0,0,0,.6) }
.au-hero .meta .n{ text-shadow:0 1px 10px rgba(0,0,0,.6) }

@media (max-width:1024px){
  /* vertical veil: consistent darkness across the full line length */
  .au-hero__veil{
    background:linear-gradient(180deg,
      rgba(11,11,12,.80) 0%,
      rgba(11,11,12,.74) 42%,
      rgba(11,11,12,.90) 100%) !important;
  }
  .au-hero .lede{
    color:#F7F4EF;
    font-size:17px;
    line-height:1.62;
    max-width:42ch;
  }
  .au-hero .meta .l{ color:#C6BEB5 }
  .au-hero .meta .n{ color:#fff }
}

@media (max-width:767px){
  .au-hero__veil{
    background:linear-gradient(180deg,
      rgba(11,11,12,.84) 0%,
      rgba(11,11,12,.78) 40%,
      rgba(11,11,12,.93) 100%) !important;
  }
  .au-hero .lede{ font-size:16.5px; max-width:38ch }
}

/* ================= TIER 1 AUDIT FIXES ================= */

/* 1. Eyebrow contrast. #CC5500 on #FBF9F6 measured 4.11:1 - below the 4.5:1 AA floor,
      and it is the primary orientation device for a scanning reader. */
.au .eyebrow{ color:#A83F00; font-size:12px; font-weight:700; letter-spacing:.18em }

/* 2. Never fetch 45MB on a metered mobile connection - the poster carries the hero. */
@media (max-width:900px){
  .au-hero__bg{ display:none }
  .au-hero{
    background-image:var(--au-hero-poster);
    background-size:cover; background-position:center;
  }
}

/* 3. Card images on phones: shown, but on a shallower crop.
      Originally hidden - the covers were unrelated stock photos costing ~184px
      of scroll each for no information. Every card now carries a subject-matched
      real photograph (2026-08-23), so the picture earns its place; the full 16/9
      height does not. A 3/1 banner keeps the subject readable at roughly 60% of
      the height. Decision was show-shorter, not hide. */
@media (max-width:640px){
  .au-card__media img{ aspect-ratio:3/1 }
  .au-card__body{ padding:20px }
}

/* 4. Sticky mobile action bar. The page's CTAs cluster at top and bottom, leaving the
      entire middle - where the courses are - with no visible way to act. */
.au-sticky{
  position:fixed; left:0; right:0; bottom:0; z-index:900;
  display:none; gap:10px; padding:10px 12px;
  background:color-mix(in srgb, var(--ground) 94%, transparent);
  backdrop-filter:blur(12px); border-top:1px solid var(--line);
  transform:translateY(110%); transition:transform .35s cubic-bezier(.16,1,.3,1);
}
.au-sticky.show{ transform:translateY(0) }
.au-sticky a{
  flex:1; display:flex; align-items:center; justify-content:center; gap:8px;
  min-height:50px; font-weight:700; font-size:15px; border:1.5px solid var(--brand);
}
.au-sticky .primary{ background:var(--brand); color:#fff }
.au-sticky .wa{ background:transparent; color:var(--brand) }
@media (max-width:900px){ .au-sticky{ display:flex } body{ padding-bottom:72px } }

/* 5. Price-moment CTA - the strongest conversion point on the page had no action attached. */
.au-feeCta{
  display:flex; flex-wrap:wrap; align-items:center; gap:16px;
  margin-top:var(--s3); padding:var(--s3);
  border:1px solid var(--brand); background:var(--wash);
}
.au-feeCta p{ margin:0; flex:1; min-width:240px; font-size:15px; color:var(--ink-2) }
.au-feeCta strong{ color:var(--ink) }

/* 6. Tap targets. .btn.sm computed to ~39px, under the 44px minimum - and those were the
      lead-capture CTAs. */
.au .btn.sm{ min-height:44px; padding:11px 18px }
.au .btn{ min-height:46px }

.au-feeCta__fine{flex-basis:100%;margin-top:4px;font-size:13px;color:var(--muted)}
.au-feeCta__fine a{color:var(--brand);text-decoration:underline}

/* 7. Hero meta row spacing on phones.
      The row uses a single `gap:var(--s5)` (48px), which sets the ROW gap as well as the
      column gap. Below ~767px the tiles wrap onto separate lines, so that 48px became
      vertical dead space between three stacked lines (~225px of hero for four short
      stats). Split the shorthand on mobile: keep a comfortable column gap, and give the
      wrapped rows 20px - roughly half a tile's height, so lines stay clearly separated
      (each tile is a 15px number over a 10px uppercase label) without reading as one
      run-on block. */
@media (max-width:767px){
  .au-hero .meta{ gap:20px 28px; margin-top:var(--s5); }
}
@media (max-width:400px){
  .au-hero .meta{ column-gap:22px }
}

.au-stats__note{font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--muted);margin-bottom:12px}

/* ================= STATS BLOCK + SECTION TOP SPACING (2026-08-24) =================
   Appended rather than edited in place so this block stays easy to lift out and cannot
   collide with concurrent work higher up the file.

   1. The stats strip had no heading at all - it opened on 11px grey fine print, the
      smallest type on the page, directly under the hero. It now leads with a title and
      keeps the cumulative-totals sentence as the qualifier underneath. The title sits
      deliberately BELOW the section h2 scale (clamp 30-46px) so a three-tile strip does
      not out-shout "Every course ends in an AUST Abuja certificate."
   2. Tile labels went 10px/400 -> 12px/600, matching .eyebrow (12px/700/.18em), which is
      this design system's canonical small mono label. Kept --muted rather than brand
      orange so they stay subordinate to the numbers they caption.
   3/4. Two places where text sat flush against a hard edge with a MEASURED 0px gap: the
      stats note against the hero video, and the courses eyebrow against the partners
      band's bottom border. Both came from padding-top:0 set inline on the markup.
      --s6/--s5 restores the page's own rhythm without the full --s7 that a free-standing
      section gets, since both of these follow a block that already has bottom padding. */

.au .wrap.au-statsSec{ padding-top:var(--s6); padding-bottom:var(--s7) }
.au .au-secTight{ padding-top:var(--s6) }

.au .au-stats__title{ font-size:clamp(22px,2.4vw,30px); margin:0 0 6px }
.au .au-stats__note{ font-size:12px; margin-bottom:var(--s3) }
.au .au-stats .l{ font-size:12px; font-weight:600; letter-spacing:.16em; margin-top:12px }

/* 840px is where .au-stats already re-tunes itself - stay on the same breakpoint.
   Letter-spacing must come down with the size or "INSTRUCTORS" (11 mono chars) overruns
   its third of a 375px row. */
@media(max-width:840px){
  .au .au-stats .l{ font-size:11px; letter-spacing:.08em }
}
@media(max-width:767px){
  .au .wrap.au-statsSec{ padding-top:var(--s5) }
  .au .au-secTight{ padding-top:var(--s5) }
  .au .au-stats__note{ margin-bottom:var(--s2) }
}

/* ================= TESTIMONIAL SECTION TAIL (2026-08-24) =================
   Appended, following the convention of the block above, so it cannot collide with
   concurrent work higher up the file.

   `.au section{padding:var(--s7) 0}` puts 104px under #voices. Every one of those
   pixels sits BETWEEN the pinned last card and the next section, so during the stack
   it is not breathing room at all - it is frozen scroll, and it pushes the next
   section that much further below the fold. Trimming it buys the closing quote ~80px
   of extra hold at no visual cost, because the ::after spacer already leaves a large
   gap once the pile releases.

   Reduced motion has no pinning and therefore no tail problem, so it keeps the page's
   normal section rhythm. */
#voices{ padding-bottom:24px }
@media (prefers-reduced-motion:reduce){ #voices{ padding-bottom:var(--s7) } }
@media (prefers-reduced-motion:reduce) and (max-width:767px){ #voices{ padding-bottom:var(--s5) } }

/* ================= HERO COPY CLEARS THE HEADER SCRIM (2026-08-24) =================
   Chimdalu: "Get certified." looked dimmed. It is not a colour problem - the h1 computes to
   a clean rgb(255,255,255) with no gradient, mask, filter or opacity on it, and it already
   paints ABOVE .au-hero__veil. The culprit is the dark scrim behind the fixed header.

   Measured by laying pure-white probe strips down the hero and reading back what they
   actually rendered as. The scrim is a FIXED 200px top band, identical at every viewport
   width, and it is steep:

       y=0 -> 32/255      y=80 -> 103      y=140 -> 191
       y=40 -> 68         y=120 -> 162     y=180 -> 251      y>=200 -> 255 (clear)

   The headline used to start at y=103 (375px) to y=154 (1440px) - i.e. inside that band at
   EVERY width, which is why each glyph was dark at the top and lighter toward the baseline.
   Worst on phones, not desktop: at 375px the cap tops rendered at ~135/255.

   The scrim stays as it is (it is what keeps the white nav legible over the video). The copy
   moves below it instead. 176px puts the cap tops at ~207-215, clear of the band with ~8px
   of margin for font-metric variation across browsers.

   Specificity 0,3,0 deliberately: it has to beat both `.au .au-hero__in` (0,2,0) and the
   `@media (max-width:767px)` rule of the same specificity further up, without depending on
   source order if this block is ever moved.

   VERIFIED after the change: headline peak AND cap-top peak = pure 255,255,255 at 1440,
   1100, 768 and 375; both hero CTAs still above the fold at 1440x900, 1100x820, 768x800,
   375x760 and 375x667 (the short iPhone SE). Do not reduce this below ~168px - that is the
   point where the cap tops re-enter the scrim. */
.au .au-hero .au-hero__in{ padding-top:176px }

/* ================= STATS NOTE: PROMOTE FROM FINE PRINT (2026-08-24) =================
   Chimdalu: "this text is too tiny". It was 11px mono, raised to 12px earlier today, still the
   smallest thing on the page and set in the monospace face, which reads as a code comment
   rather than a sentence.

   The page already has a pattern for exactly this job: every section head is an h2 with a
   `.sub` under it at 15px, body face, --muted. The stats block now has a title, so its note
   should be that same `.sub`, not fine print. Matching it rather than inventing a third size.
   Mono and the .06em tracking are dropped with it - both are this system's LABEL treatment
   (eyebrows, stat labels, meta keys), and this is prose, not a label. */
.au .au-stats__note{
  font-family:var(--body);
  font-size:15px;
  letter-spacing:normal;
  line-height:1.55;
  max-width:52ch;
}

/* ================= STATS AS SEPARATE TILES + VOICES HEAD SCROLLS (2026-08-24) =========

   (a) STATS: three separate boxes, not one ruled rectangle.
   The block was a single bordered rectangle with internal dividers: a shared border-left on
   the grid plus right/top/bottom borders on each cell, so adjacent edges met and read as one
   table. Chimdalu asked for each metric to be its own box. Dropping the grid's border-left and
   giving each cell a full border + gap turns the dividers into real separation. Surface white
   on the ground colour matches how every other boxed group on this page is built
   (.au-props > div, .au-contact > div, .au-mode).
   Gap is tighter below 840px: at 375px each tile is only ~98px wide, and "INSTRUCTORS" is the
   longest label on the page, so the gap has to come out of the row rather than the label.

   (b) VOICES: the heading scrolls with the content again.
   Chimdalu: at the end of the stack the last card slides BEHIND "What our participants say."
   Measured at 1440x900: the head pins at scrollY 4114 and does not release until ~6060,
   because position:sticky only releases at the bottom of its containing block (.wrap), which
   runs to 6230 - it includes the stack's trailing ::after runway. The last card starts riding
   up at ~5750, so there is a ~300px window where it passes under the pinned label.

   NOTE FOR WHOEVER ADDED THE STICKY HEAD (another session, 2026-08-24 08:39): this is not a
   merge accident. Chimdalu asked for it directly after seeing the end-of-stack behaviour. The
   rationale in that block - that the label otherwise disappears for the rest of the stack - is
   still sound; the middle ground (sticky during the stack, released before the last card rides
   up) needs the head and .au-quotes wrapped in their own container so sticky has a shorter
   containing block, which is a markup change and was not made unilaterally on a file two
   sessions were editing. Raise it with him rather than reverting this.
   The background/padding-block/z-index are reset too - they exist only to make a pinned bar
   read as solid, and padding-block:12px would otherwise add 24px to the head's own rhythm. */

.au .au-stats{ gap:var(--s3); border-left:0 }
.au .au-stats>div{ border:1px solid var(--line); background:var(--surface) }
@media(max-width:840px){
  .au .au-stats{ gap:var(--s1) }
}

.au #voices .head{
  position:static;
  z-index:auto;
  background:none;
  padding-block:0;
}

/* Phone label headroom after the tiles were separated. Adding an 8px gap and a border to each
   tile took "INSTRUCTORS" (the longest label on the page) down to 5.4px of slack at 375px, from
   11.4px. That still fits in Chromium, but it is inside the margin where a slightly different
   font metric wraps it, so buy the room back from the tracking rather than the type size. */
@media(max-width:840px){
  .au .au-stats .l{ letter-spacing:.04em }
}

/* ========= VOICES: HEAD STICKY THROUGH THE STACK, RELEASED AT THE LAST CARD (2026-08-24) =====

   This resolves the disagreement flagged in the block above ("NOTE FOR WHOEVER ADDED THE
   STICKY HEAD"). Both sessions were right and both fixes were half of one:

     - sticky head  -> the label stays with the pile it is labelling  (wanted)
     - static head  -> the closing quote never slides under it        (wanted)

   Chimdalu, 2026-08-24, verbatim: "i want it to be there and then once it gets to the last
   card then it stops being sticky and scrolls along so that the card does not go behind the
   text". So: pinned for the whole stack, then let go at the last card and travel with it.

   THE TRAP. position:sticky releases at the bottom of its CONTAINING BLOCK. The head's was
   .wrap, which runs to the bottom of .au-quotes - and .au-quotes ends with the ::after beat
   that holds the closing quote at centre. Measured 1440x900: the last card starts riding up
   at scrollY ~5635, the head did not let go until ~6068. That ~430px is the whole bug.
   Wrapping .head and .au-quotes in a new div does NOT fix it: the wrapper still contains the
   beat, so it ends in the same place.

   THE FIX. Keep the beat where it is - the cards' pin depends on it - and take it out of the
   HEAD's containing block only:

     .wrap > .au-voicesStick   <- the head's containing block; flow-root so the negative
             > .head              margin below actually shortens it instead of collapsing out
             > .au-quotes.au-stack { margin-bottom: -release }
           > .au-voicesTail    <- height: +release, puts the flow back

   Net page height is unchanged to the pixel, every card's sticky range is unchanged (their
   containing block is .au-quotes, whose own box is untouched), and the head now lets go on
   the same pixel as the closing quote, so the two travel up together.

   release = lastCardH + restTop - headH - headTop, computed per viewport in au_stack_script
   (THE HEADING LETS GO). The literal below is only the no-JS fallback - it is used by BOTH
   rules, so the flow stays balanced whatever value applies.

   Reduced motion has no pinning at all, so it opts out of the whole arrangement. */
.au-voicesStick{ display:flow-root }
.au-voicesStick > .au-quotes.au-stack{ margin-bottom:calc(-1 * var(--au-headrelease, 430px)) }
.au-voicesTail{ height:var(--au-headrelease, 430px) }

/* Restores the sticky head that the STATS AS SEPARATE TILES block above turned off. Same
   values as the original #voices .head rule; repeated here rather than reverted there so the
   two sessions' blocks both stay readable as a record. */
.au #voices .head{
  position:sticky;
  top:78px;
  z-index:5;
  background:var(--ground);
  padding-block:12px;
}
@media(max-width:840px){
  .au #voices .head{ top:70px; padding-block:8px }
}
@media (prefers-reduced-motion:reduce){
  .au #voices .head{ position:static; z-index:auto; background:none; padding-block:0 }
  .au-voicesStick{ display:block }
  .au-voicesStick > .au-quotes.au-stack{ margin-bottom:0 }
  .au-voicesTail{ display:none }
}
