/* Home page. Comments give the live site's design pixels at the 1920 anchor. */

/* --------------------------------------------------------------------- hero */

.hero {
  justify-content: center;
  min-height: 79.0625rem;          /* 1265 */
  padding: 0 var(--gutter);
  background: var(--ink);
  text-align: center;
  color: var(--paper);
}
.hero__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}
.hero__eyebrow {
  max-width: 72rem;                /* 1152 */
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.hero__title {
  max-width: 96rem;                /* 1536 */
  margin-top: 1.5rem;              /* 24 */
}
.hero__lead {
  max-width: 63rem;                /* 1008 */
  margin-top: 2.3125rem;           /* 37 */
}
.hero__cta { margin-top: 5.125rem; }  /* 82 */

/* -------------------------------------------------------------------- arena */

.arena {
  min-height: 172.9375rem;         /* 2767 */
  padding: 9.375rem 0 0;           /* 150 */
  background: var(--paper);
}
.arena__eyebrow { font-size: var(--fs-h2); text-align: center; }
.arena__title {
  max-width: 65.3125rem;           /* 1045 */
  margin: 1.125rem auto 0;         /* 18 */
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  text-align: center;
}

/* Each row is exactly 750px tall on the original and the colour panels tile
   with no gap between them, so the rows are positioned rather than flowed. */
.arena__rows {
  position: relative;
  width: 120rem;                   /* 1920 */
  max-width: 100%;
  margin: 5.9375rem auto 0;        /* 95 */
  height: 140.625rem;              /* 3 x 750 */
}
.arena-row { position: absolute; left: 0; width: 100%; height: 46.875rem; }
.arena-row:nth-child(1) { top: 0; }
.arena-row:nth-child(2) { top: 46.875rem; }
.arena-row:nth-child(3) { top: 93.75rem; }

.arena-row__media { position: static; }
.arena-row__media::before {
  content: '';
  position: absolute;
  top: 0;
  width: 50.4375rem;               /* 807 */
  height: 46.875rem;               /* 750 */
}
.arena-row:nth-child(1) .arena-row__media::before,
.arena-row:nth-child(3) .arena-row__media::before { left: 0; }
.arena-row:nth-child(2) .arena-row__media::before { right: 0; }
.arena-row__media--cyan::before { background: var(--cyan); }
.arena-row__media--lilac::before { background: var(--lilac); }
.arena-row__media--lime::before { background: var(--lime); }

.arena-row__media video {
  position: absolute;
  z-index: 1;
  border-radius: 0.75rem;
  background: #000;
}
.arena-row:nth-child(1) video { top: 7.4375rem; left: 6.25rem;  width: 55.9375rem; }
.arena-row:nth-child(2) video { top: 6.875rem;  left: 60.0625rem; width: 55.4375rem; }
.arena-row:nth-child(3) video { top: 7.375rem;  left: 3.625rem; width: 55.4375rem; }

.arena-row__copy { position: absolute; z-index: 1; }
.arena-row:nth-child(1) .arena-row__copy { top: 6.5rem;   left: 70.75rem;   width: 39.1875rem; }
.arena-row:nth-child(2) .arena-row__copy { top: 7.5rem;   left: 6.75rem;    width: 39.1875rem; }
.arena-row:nth-child(3) .arena-row__copy { top: 5.1875rem; left: 67.0625rem; width: 45.0625rem; }

.arena-row__copy h3 { font-size: var(--fs-h3); }
.arena-row__sub { margin-top: 0.9375rem; font-size: var(--fs-item); }
.arena-row__body { margin-top: 1.125rem; font-size: var(--fs-sm); }

.tick-list { margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.5rem; }
.tick-list li {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 3.25rem;
  padding-left: 4.5rem;            /* 72 = icon 52 + gap */
  font-size: var(--fs-sm);
}
.tick-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 3.25rem;                  /* 52 */
  height: 3.25rem;
  background: url('../../img/brand/icon-check-320w.webp') center / contain no-repeat;
}

/* ----------------------------------------------------------------- audience */

.audience {
  padding: 5rem var(--gutter) 6rem;
  background: var(--paper);
  text-align: center;
}
.audience__eyebrow { font-size: var(--fs-h2-sm); }
.audience__title {
  margin-top: 1.5rem;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.audience__lead {
  max-width: 56.875rem;            /* 910 */
  margin: 1.5rem auto 0;
  font-size: var(--fs-sm);
}
.audience__cta { margin-top: 2.75rem; min-width: 34.5625rem; }   /* 553 */

.audience-grid {
  display: grid;
  grid-template-columns: repeat(3, 29.8125rem);   /* 477 */
  justify-content: center;
  gap: 3.375rem;                   /* 54 */
  margin-top: 5.5rem;
}
.audience-card {
  padding: 3.25rem 0 0;
  background: var(--paper);
  border-radius: 0.375rem;
  box-shadow: 0 2px 14px rgb(0 0 0 / 8%);
}
.audience-card__title { font-size: var(--fs-card); font-weight: 700; }

/* Logo ticker. The live site runs this inside a third-party widget; here it is
   a duplicated track and one keyframe. */
.marquee {
  overflow: hidden;
  margin: 3.5rem 1.25rem 1.25rem;
  padding: 0.5rem 0;
  background: #fff;
  border-radius: 6px;
}
.marquee__track {
  display: flex;
  align-items: center;
  gap: 3.5rem;
  width: max-content;
  animation: marquee 28s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__track img {
  width: 4.8125rem;                /* 77 */
  height: 4.8125rem;
  object-fit: contain;
}
@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* -------------------------------------------------------------------- media */

.media-centre {
  padding: 5rem var(--gutter) 6rem;
  background: var(--paper);
  text-align: center;
}
.media-centre__title { font-size: var(--fs-display); line-height: var(--lh-display); }
.media-centre__lead { margin-top: 1.5rem; font-size: var(--fs-sm); }

.post-grid {
  display: grid;
  grid-template-columns: repeat(3, 29.25rem);   /* 468 */
  justify-content: center;
  gap: 2rem;
  margin-top: 6.5rem;
  text-align: left;
}
.post-card {
  background: var(--paper);
  border: 1px solid #e6e3df;
  overflow: hidden;
}
.post-card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.post-card__body { padding: 2rem 2rem 2.5rem; }
.post-card__date { font-size: 1.125rem; opacity: 0.7; }   /* 18 */
.post-card__title { margin-top: 1rem; font-size: var(--fs-sm); font-weight: 700; }
.post-card a:hover .post-card__title { text-decoration: underline; }

.media-centre__cta { margin-top: 3rem; }

/* ------------------------------------------------------------------ contact */

.contact {
  padding: 5rem var(--gutter) 7rem;
  background: var(--paper);
  text-align: center;
}
.contact__icon { width: 11.375rem; margin-inline: auto; }   /* 182 */
.contact__title {
  margin-top: 3rem;                /* 48 */
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.contact__lead { margin-top: 1rem; font-size: var(--fs-sm); }   /* 16 */

/* Field metrics below are the live form's: 17px label, 9px gap, 33px control,
   25px between fields, an 84px pitch. */
.contact-form {
  width: 100%;
  max-width: 69.3125rem;           /* 1109 */
  margin: 3rem auto 0;             /* 48 */
  text-align: left;
  font-size: 0.875rem;             /* 14 */
}
.field { margin-bottom: 1.5625rem; }   /* 25 */
.field > label,
.field legend {
  display: block;
  margin-bottom: 0.5625rem;        /* 9 */
  font-size: 0.875rem;
  line-height: 1.0625rem;          /* 17 */
}
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.4375rem 0.9rem;
  font: inherit;
  font-size: 0.875rem;
  line-height: 1.0625rem;
  color: var(--ink);
  background: transparent;
  border: 1px solid #6b4a3a;
  border-radius: 1.5rem;
}
.field textarea { height: 4.625rem; border-radius: 1rem; resize: vertical; }  /* 74 */
.field input:focus,
.field select:focus,
.field textarea:focus { border-color: var(--ink); outline: none; }
.field input[aria-invalid='true'],
.field select[aria-invalid='true'],
.field textarea[aria-invalid='true'] { border-color: #df3131; }

.field--checks { border: 0; }
.check-grid {
  display: grid;
  grid-template-columns: repeat(2, 34.125rem);   /* 546 */
  gap: 0 1rem;                                   /* 16 */
  margin-top: 0.5rem;
}
.check-grid label {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.25rem;             /* 36 row pitch */
}
.check-grid input { width: 0.8rem; height: 0.8rem; accent-color: var(--ink); }

/* .form-error and .form-sent are in components.css, every form reaches them. */
.contact-form__submit {
  width: 100%;
  height: 2.4375rem;               /* 39 */
  padding: 0;
  font-size: 0.875rem;
  border-radius: 0.375rem;
}

/* ------------------------------------------------------ tablet and mobile */

@media (max-width: 999px) {
  .hero { min-height: 44rem; }
  .pathways,
  .arena,
  .audience,
  .media-centre,
  .contact { min-height: 0; padding-top: 4.5rem; padding-bottom: 4.5rem; }

  .pathway-grid { grid-template-columns: 1fr; gap: 3rem; max-width: 26rem; margin-inline: auto; }
  .pathway__head { min-height: 0; }

  .arena { padding-inline: var(--gutter); }
  .arena__rows {
    position: static;
    height: auto;
    width: 100%;
    margin-top: 4rem;
    display: flex;
    flex-direction: column;
    gap: 4rem;
  }
  .arena-row {
    position: static;
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }
  .arena-row__media::before { display: none; }
  .arena-row__media video,
  .arena-row__copy {
    position: static;
    width: 100%;
    border-radius: 1rem;
  }

  .audience-grid,
  .post-grid { grid-template-columns: 1fr; gap: 2rem; max-width: 30rem; margin-inline: auto; }
  .audience__cta { min-width: 0; width: 100%; max-width: 26rem; }
}

@media (max-width: 749px) {
  .hero { min-height: 34rem; }
  .hero__title { margin-top: 0.75rem; }
  .hero__lead { margin-top: 1rem; }
  .hero__cta { margin-top: 1.75rem; }

  .pathways__art { top: 30%; }
  .tick-list li { padding-left: 2.5rem; min-height: 2rem; }
  .tick-list li::before { width: 1.75rem; height: 1.75rem; }

  .check-grid { grid-template-columns: 1fr; }
  .contact-form { font-size: 1rem; }
}

/* ------------------------------------------------------ /cybersecurity tail

   The closing CTA on /cybersecurity. That page is this stylesheet's second
   consumer: it took the hero, the pathway block and the Arena rows when the
   home page became a four-focus hub, and shares home.css because those rows are
   absolutely positioned against hard-coded 1920 coordinates and the media
   queries below group selectors from every section together. */

.cyber-tail { padding: 7rem var(--gutter); background: var(--paper); text-align: center; }
.cyber-tail__title { font-size: var(--fs-display); line-height: var(--lh-display); }
.cyber-tail__lead {
  max-width: 52rem;
  margin: 1.5rem auto 0;
  font-size: var(--fs-sm);
}
.cyber-tail__cta { margin-top: 2.5rem; }

@media (max-width: 999px) { .cyber-tail { padding: 4rem var(--gutter); } }

/* ------------------------------------------------------------- the hub

   The front door. The four panels ARE the page's opening, full bleed, filling the
   screen, so the choice is the first thing rather than something to scroll past. */

/* The heading and the grid together are one screen: the section owns the height and the
   grid takes whatever the heading leaves, so adding the heading did not push the tiles
   off the fold. */
.hub-picks {
  display: flex;
  flex-direction: column;
  /* .section centres its children; these two are full-bleed. */
  align-items: stretch;
  min-height: calc(100vh - var(--header-h));
  padding: 0;
  background: var(--ink);
}
/* The bar above this is black too, so without the rule the two read as one slab. */
.hub-picks__head {
  padding: 5rem var(--gutter) 4.5rem;
  border-bottom: 1px solid rgb(255 252 248 / 12%);
  color: var(--paper);
  text-align: center;
}
.hub-picks__eyebrow {
  font-size: var(--fs-nav);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--lime);
}
.hub-picks__title {
  margin-top: 1.25rem;
  font-size: var(--fs-h2);
  line-height: var(--lh-display);
  font-weight: 400;
}
.hub-picks__lead {
  max-width: 48rem;                     /* 768 */
  margin: 1.25rem auto 0;
  font-size: var(--fs-sm);
  color: rgb(255 252 248 / 66%);
}

/* The home banner. Same block /cybersecurity uses, sized so the bar and the banner
   together are exactly one screen rather than the Wix 1265px. */
.hero--hub { min-height: calc(100vh - var(--header-h)); overflow: hidden; }

/* ------------------------------------------------------------- the banner's motion

   `/cybersecurity` and `/` open on the same shape, so they cannot open on the same
   movement. That page is a surveillance console: a hard grid, a scan line, code falling.
   This one is the company above both halves of the practice, so everything here rises
   instead of falls, and nothing has a hard edge: a slow aurora, and motes drifting up
   through it. Same lime, opposite temperament.

   All CSS. No library, no script, nothing added to the DOM, and base.css stops every one
   of these under prefers-reduced-motion, where what is left is still a photograph with a
   readable headline on it. */

/* The photograph is bright teal at full strength and the lead sat on it at about 3:1.
   A wash fixes the contrast and ties the ground to this site's accent at the same time. */
.hero--hub .section__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(90% 70% at 50% 38%, rgb(170 255 0 / 8%), transparent 72%),
    linear-gradient(180deg, rgb(10 10 10 / 30%) 0%, rgb(10 10 10 / 62%) 100%);
}
.hero--hub .hero__inner { z-index: 2; }

.hub-fx {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* One vignette for every layer inside rather than a mask apiece, so nothing arrives as
     a hard edge at the top of the section. */
  mask-image: radial-gradient(130% 105% at 50% 50%, #000 30%, transparent 90%);
  -webkit-mask-image: radial-gradient(130% 105% at 50% 50%, #000 30%, transparent 90%);
}

/* An aurora: two soft fields breathing against each other on different periods, so the
   pattern never repeats where anybody is looking. Deliberately slow. This is the layer
   that makes the banner feel alive when nothing else is moving much. */
.hub-fx::before {
  content: '';
  position: absolute;
  inset: -25%;
  background:
    radial-gradient(38% 44% at 28% 34%, rgb(170 255 0 / 16%), transparent 68%),
    radial-gradient(42% 38% at 74% 62%, rgb(64 220 200 / 14%), transparent 70%);
  animation: hub-aurora 26s ease-in-out infinite alternate;
}
@keyframes hub-aurora {
  from { transform: translate3d(-3%, 2%, 0) scale(1); }
  to   { transform: translate3d(4%, -3%, 0) scale(1.12); }
}

/* A horizon that swells and fades, once every eleven seconds. It reads as the ground
   under everything else rather than as an object, which is why it is so faint. */
.hub-fx::after {
  content: '';
  position: absolute;
  left: -10%;
  right: -10%;
  bottom: 0;
  height: 28rem;
  background: linear-gradient(0deg, rgb(170 255 0 / 18%), transparent 78%);
  animation: hub-swell 11s ease-in-out infinite;
}
@keyframes hub-swell {
  0%, 100% { opacity: 0.35; transform: translateY(2rem); }
  50%      { opacity: 1;    transform: translateY(0); }
}

/* The traces, falling.

   The photograph is drawn circuit traces coming down from the top, each with a lit dot at
   its tip and one or two with an elbow. The banner's motion is that continued rather than
   something set against it: same shape, same direction, same two greens, just moving.

   This is still not `/cybersecurity`'s rain, and the difference is the point. That is a
   code column, cut into segments by a mask, tiled edge to edge and marching. These are
   fifteen separate traces at fifteen speeds, each a single line with a head on it, and the
   gaps between them are as deliberate as the traces. One reads as a machine scanning; this
   reads as the picture it is sitting on. */
.hub-traces {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 1.5;
}
/* Constant hairlines however wide the viewport gets. `preserveAspectRatio: none` stretches
   the box to fill the banner, which would otherwise thicken every vertical line with it. */
.hub-traces path { vector-effect: non-scaling-stroke; }

.hub-trace {
  /* Both set per trace in the markup: --d is its duration, --t a negative delay so every
     one is already mid-fall when the page arrives and the banner is never caught empty. */
  animation: hub-fall var(--d) linear var(--t) infinite;
}
@keyframes hub-fall {
  /* Fades in over the first tenth and out over the last fifth, so a trace never appears or
     vanishes at a hard edge, and the tip is brightest through the middle of the fall. */
  0%        { transform: translateY(0);      opacity: 0; }
  10%, 78%  { opacity: 1; }
  100%      { transform: translateY(1220px); opacity: 0; }
}

/* One pass of light across the whole banner, every nine seconds.

   This is the layer that answers the cyber page's scan line, and it is deliberately not
   one: that page gets a hard horizontal edge sweeping down, a machine reading a screen.
   This is a soft diagonal passing over, which is what light does. Wide and low-contrast,
   so it lifts the headline as it goes rather than striping it. */
.hub-sheen {
  position: absolute;
  inset: -50%;
  display: block;
  background: linear-gradient(74deg,
    transparent 38%,
    rgb(255 252 248 / 5%) 47%,
    rgb(170 255 0 / 14%) 50%,
    rgb(255 252 248 / 5%) 53%,
    transparent 62%);
  animation: hub-sheen 9s ease-in-out infinite;
}
@keyframes hub-sheen {
  0%       { transform: translate3d(-55%, 22%, 0); opacity: 0; }
  12%, 62% { opacity: 1; }
  100%     { transform: translate3d(55%, -22%, 0); opacity: 0; }
}

@media (max-width: 46.875rem) {
  /* Fewer traces on a phone: at that width fifteen of them across 390px is a thicket, and
     each one is its own animated element to composite. The aurora, the horizon and the
     sheen carry the rest. */
  .hub-trace:nth-child(even) { display: none; }
  .hub-fx::after { height: 18rem; }
}


/* Two by two, one screen of its own, immediately after the banner. */
.hub-grid {
  display: grid;
  flex: 1;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 1fr;
  gap: 2px;
  background: rgb(255 252 248 / 14%);   /* shows through the gap as a hairline */
}
.hub-tile { display: flex; }
.hub-tile a {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 100%;
  min-height: 20rem;                    /* 320, a floor for short viewports */
  padding: 3rem;
  overflow: hidden;
  color: var(--paper);
  background: var(--ink);
}
.hub-tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.82;
  transition: transform 0.6s ease, opacity 0.3s ease;
}
/* Darkest at the bottom, where the words are. */
.hub-tile a::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, rgb(6 6 6 / 88%) 0%, rgb(6 6 6 / 55%) 45%, rgb(6 6 6 / 10%) 100%),
    linear-gradient(to top, rgb(6 6 6 / 88%) 0%, rgb(6 6 6 / 62%) 38%, rgb(6 6 6 / 30%) 100%);
}
.hub-tile a:hover img { transform: scale(1.04); opacity: 0.95; }

.hub-tile__body { position: relative; z-index: 1; max-width: 34rem; }
/* A number and a rule, so the four read as a numbered set rather than four posters. */
.hub-tile__num {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  font-size: var(--fs-nav);
  letter-spacing: 0.22em;
  color: var(--lime);
}
.hub-tile__num::after {
  content: '';
  flex: 1;
  max-width: 4rem;
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}
.hub-tile h2 {
  margin-top: 1.25rem;
  font-size: var(--fs-card);
  line-height: 1.15;
}
.hub-tile p {
  margin-top: 1rem;
  font-size: var(--fs-sm);
  color: rgb(255 252 248 / 78%);
}
/* An actual button, because a card that only looks like a card does not say "press me". */
.hub-tile__go {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.75rem;
  padding: 0.75rem 1.5rem;
  font-size: var(--fs-nav);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--lime);
  background: transparent;
  border: 1px solid var(--lime);
  border-radius: var(--radius);
  transition: gap 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.hub-tile__go::after { content: '→'; }
.hub-tile a:hover .hub-tile__go {
  gap: 0.875rem;
  color: var(--ink);
  background: var(--lime);
}

.hub-cred { padding: 0 var(--gutter) 5rem; background: var(--paper); }
.hub-cred__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2rem;
  max-width: var(--content);
  margin: 2.5rem auto 0;
}
.hub-cred__grid li { padding-top: 1.25rem; border-top: 1px solid #e6e3df; }
.hub-cred__grid b { display: block; font-size: var(--fs-h2-sm); font-weight: 400; }
.hub-cred__grid p { margin-top: 0.625rem; font-size: var(--fs-sm); color: #5c5c5c; }

.hub-about { padding: 6rem var(--gutter); background: var(--paper); text-align: center; }

/* The Hexcore / Autobricks lockup. The mark is the only Autobricks asset on this page and
   it brings none of the --ab-* palette with it: only .ab pages get repainted. */
.hub-lockup {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  margin-bottom: 3rem;
}
.hub-lockup__hex { width: auto; height: 2.75rem; }              /* 44 */
.hub-lockup__x { font-size: var(--fs-item); color: #b3aea7; line-height: 1; }
.hub-lockup__ab { display: flex; align-items: center; gap: 0.75rem; }
/* The supplied art already has its own rounded corners and hairline, so nothing is
   added here: a CSS radius would clip the corners it draws itself. */
.hub-lockup__ab > img:first-child { width: 2.75rem; height: 2.75rem; }
.hub-lockup__word { width: auto; height: 1.625rem; }   /* 26, one line beside the mark */
.hub-about__lead b { font-weight: 400; border-bottom: 2px solid var(--lime); }
.hub-about__title { font-size: var(--fs-display); line-height: var(--lh-display); }
.hub-about__lead {
  max-width: 80rem;                /* 1280 */
  margin: 1.75rem auto 0;
  font-size: var(--fs-sm);
}
.hub-about__cta { margin-top: 2.5rem; }

@media (max-width: 999px) {
  .hub-grid { min-height: 0; }
  .hub-tile a { padding: 2rem; min-height: 17rem; }
  .hub-about { padding: 4rem var(--gutter); }
  .hub-lockup { gap: 1rem; margin-bottom: 2.25rem; }
  .hub-picks__head { padding: 3.25rem var(--gutter) 3rem; }
  .hub-cred { padding: 3rem var(--gutter); }
  .hub-cred__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 749px) {
  /* One column, but still tall enough that each is a panel rather than a row. */
  .hub-grid, .hub-cred__grid { grid-template-columns: 1fr; }
  .hub-tile a { min-height: 15rem; padding: 1.75rem; }
  .hub-tile h2 { font-size: 1.375rem; }   /* 22 */
  .hub-picks__head { padding: 2.5rem var(--gutter) 2.25rem; }
  /* Wrapping strands the "x" at the end of a line, so stack the two marks instead. */
  .hub-lockup { flex-direction: column; gap: 0.875rem; }
}

/* --------------------------------------------------- icons on the hub

   Inline SVG rather than image files: no extra requests, they inherit
   currentColor, and they stay sharp at any size. The site's existing icons are
   1920px PNGs made for the pathway cards and are the wrong tool here. */

.hub-cred__icon { width: 2rem; height: 2rem; color: var(--ink); }   /* 32 */
.hub-cred__grid li { padding-top: 1.5rem; }
.hub-cred__grid b { margin-top: 1rem; }

.hub-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2.5rem;
  max-width: var(--content);
  margin: 3rem auto 0;
}
.hub-stats svg { width: 2.25rem; height: 2.25rem; margin-inline: auto; }
.hub-stats b { display: block; margin-top: 1rem; font-size: var(--fs-item); font-weight: 400; }
.hub-stats span { display: block; margin-top: 0.5rem; font-size: var(--fs-sm); color: #5c5c5c; }

@media (max-width: 999px) { .hub-stats { grid-template-columns: 1fr; gap: 2rem; } }

/* ============================================================= /cybersecurity hero

   This page opened on the same photograph and nearly the same headline as the home page,
   so the two were indistinguishable above the fold. It has its own now. The background is
   Arena footage, which is the thing the page sells, and everything over it is CSS: a grid,
   a scan sweep and a terminal line. No library, no new image, and under
   prefers-reduced-motion base.css stops all three.

   Only this page uses these rules. `/` uses .hero--hub, and .hero itself still carries the
   Wix numbers for anything else that might want them. */

.hero--cyber {
  min-height: calc(100vh - var(--header-h));
  overflow: hidden;
}
.hero--cyber .section__bg img { opacity: 0.55; }
/* A wash of lime over a blue-black photograph, so the ground reads as this site's rather
   than as stock. */
.hero--cyber .section__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 60% at 50% 42%, rgb(170 255 0 / 7%), transparent 70%),
    linear-gradient(180deg, rgb(10 10 10 / 45%), rgb(10 10 10 / 82%));
}
.hero--cyber .hero__inner { z-index: 2; }

/* The effects sit between the footage and the words, in their own element: as pseudo
   elements of the section they would have painted under .section__bg, which is a real
   child and therefore later in DOM order at the same z-index. */
.cyber-fx { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

/* One vignette for every layer inside, rather than a mask per layer. It also keeps the
   scan sweep from arriving as a hard edge at the top of the section. */
.cyber-fx {
  mask-image: radial-gradient(140% 100% at 50% 45%, #000 32%, transparent 88%);
  -webkit-mask-image: radial-gradient(140% 100% at 50% 45%, #000 32%, transparent 88%);
}

/* A range grid, drifting a cell every four seconds and bright enough to be seen rather
   than merely sensed. */
.cyber-fx::before {
  content: '';
  position: absolute;
  inset: -4rem;
  background-image:
    linear-gradient(rgb(170 255 0 / 13%) 1px, transparent 1px),
    linear-gradient(90deg, rgb(170 255 0 / 13%) 1px, transparent 1px);
  background-size: 3.75rem 3.75rem;                 /* 60 */
  animation: cyber-grid 4s linear infinite;
}
@keyframes cyber-grid {
  to { background-position: 0 3.75rem, 3.75rem 0; }
}

/* A sweep with a hard bright line at its leading edge, so it reads as a scan passing
   rather than as the background brightening. */
.cyber-fx::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 14rem;
  background: linear-gradient(180deg, transparent, rgb(170 255 0 / 13%));
  border-bottom: 2px solid rgb(170 255 0 / 70%);
  animation: cyber-scan 4.5s linear infinite;
}
@keyframes cyber-scan {
  from { top: -14rem; }
  to   { top: 100%; }
}

/* Falling code. The background paints thin vertical columns, the mask cuts them into
   segments, and translating the whole layer moves both together so the segments fall.
   Two passes at different pitches and speeds, so the columns do not march in step.
   Gradients rather than characters: no font work, no script, nothing in the DOM. */
.cyber-fx span {
  position: absolute;
  inset: -70% 0;
  display: block;
  animation: cyber-rain 3s linear infinite;
}
.cyber-fx span:first-child {
  background-image: repeating-linear-gradient(90deg,
    rgb(170 255 0 / 42%) 0 1px, transparent 1px 7.5rem);
  mask-image: repeating-linear-gradient(180deg,
    transparent 0 7rem, #000 8rem 11rem, transparent 12rem 20rem);
  -webkit-mask-image: repeating-linear-gradient(180deg,
    transparent 0 7rem, #000 8rem 11rem, transparent 12rem 20rem);
}
.cyber-fx span:last-child {
  background-image: repeating-linear-gradient(90deg,
    transparent 0 3.75rem, rgb(170 255 0 / 26%) 3.75rem 3.8125rem, transparent 3.8125rem 7.5rem);
  mask-image: repeating-linear-gradient(180deg,
    transparent 0 4rem, #000 5rem 7rem, transparent 8rem 13rem);
  -webkit-mask-image: repeating-linear-gradient(180deg,
    transparent 0 4rem, #000 5rem 7rem, transparent 8rem 13rem);
  animation-duration: 4.6s;
  animation-direction: reverse;
}
@keyframes cyber-rain {
  to { transform: translateY(20rem); }
}

/* An actual terminal line, so monospace is the right voice here rather than a stylistic
   one. It is aria-hidden: it is decoration, and a screen reader reading out a shell
   prompt would be nonsense. */
.hero__term {
  margin-top: 2.5rem;
  font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace;
  font-size: var(--fs-sm);
  color: rgb(255 252 248 / 55%);
}
.hero__term span { color: var(--lime); }
.hero__term b {
  display: inline-block;
  width: 0.5em;
  height: 1.1em;
  margin-left: 0.35em;
  vertical-align: text-bottom;
  background: var(--lime);
  animation: cyber-caret 1.1s steps(1) infinite;
}
@keyframes cyber-caret {
  50% { opacity: 0; }
}

@media (max-width: 749px) {
  .hero--cyber .section__bg img { opacity: 0.42; }
  /* One line or it stops looking like a prompt. */
  .hero__term { font-size: 0.6875rem; white-space: nowrap; }
}

/* ==================================================== the domains we teach

   Sits under the three pathways: the pathways are the route, these are the subjects along
   it. auto-fit means the grid takes any number of them, so the full list drops in as extra
   <li>s and nothing here changes. */

.domains { padding: 6rem var(--gutter); background: var(--paper); }
.domains__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #5c5c5c;
}
.domains__eyebrow::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--lime);
}
.domains__title {
  max-width: 84rem;
  margin-top: 1.75rem;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.domains__lead { max-width: 76rem; margin-top: 1.5rem; font-size: var(--fs-sm); color: #5c5c5c; }

.domain-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr));   /* 336 */
  gap: 1.5rem;
  margin-top: 3.5rem;
}
.domain {
  padding: 2rem 1.75rem;
  background: #fff;
  border: 1px solid #e6e3df;
  border-radius: 0.375rem;
  transition: border-color 0.2s ease;
}
.domain:hover { border-color: var(--ink); }
.domain__icon { width: 2.25rem; height: 2.25rem; }
.domain h3 { margin-top: 1.25rem; font-size: var(--fs-item); line-height: 1.25; }
.domain p { margin-top: 0.75rem; font-size: var(--fs-sm); color: #5c5c5c; }

/* ===================================================== government-backed credentials

   After the Arena, because the Arena is the thing these two programmes picked. Dark, so
   it reads as a full stop between the Arena and the closing ask. */

.creds { padding: 6rem var(--gutter); background: var(--ink); color: var(--paper); }
.creds__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgb(255 252 248 / 72%);
}
.creds__eyebrow::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--lime);
}
.creds__title {
  max-width: 84rem;
  margin-top: 1.75rem;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.creds__lead {
  max-width: 76rem;
  margin-top: 1.5rem;
  font-size: var(--fs-sm);
  color: rgb(255 252 248 / 72%);
}

.cred-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
  margin-top: 3.5rem;
}
.cred {
  display: flex;
  flex-direction: column;
  padding: 2.5rem;
  background: rgb(255 252 248 / 5%);
  border: 1px solid rgb(255 252 248 / 14%);
  border-top: 3px solid var(--lime);
  border-radius: 0.375rem;
}
/* Both marks share a box, so a supplied logo replaces the lettered plate without the two
   cards falling out of alignment. */
.cred__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5.5rem;                                  /* 88 */
  height: 5.5rem;
  padding: 0.625rem;
  background: #fff;
  border-radius: 0.5rem;
}
.cred__mark img { width: 100%; height: 100%; object-fit: contain; }
.cred__mark--text span {
  font-size: var(--fs-h2-sm);
  letter-spacing: 0.06em;
  color: var(--ink);
}
.cred__prog {
  margin-top: 1.75rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--lime);
}
.cred__claim { margin-top: 0.875rem; font-size: var(--fs-h2-sm); line-height: 1.25; }
.cred__body { margin-top: 1rem; font-size: var(--fs-sm); color: rgb(255 252 248 / 76%); }

@media (max-width: 999px) {
  .domains, .creds { padding: 4rem var(--gutter); }
  .cred-grid { grid-template-columns: 1fr; }
}
@media (max-width: 749px) {
  .domain-grid { grid-template-columns: 1fr; }
  .cred { padding: 1.75rem; }
}

/* ================================================= the cybersecurity progression

   Replaces the three parallel subjects (entrepreneurship, cybersecurity, AI) with one
   route through cybersecurity in stages. New classes on purpose: the old block used
   .pathway* from components.css, which /cert-pathways also renders and which is the last
   page held against the Wix capture, so those rules cannot move. */

.cyber-path { padding: 6rem var(--gutter); background: var(--paper); }
.cyber-path__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #5c5c5c;
}
.cyber-path__eyebrow::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--lime);
}
.cyber-path__title {
  max-width: 84rem;
  margin-top: 1.75rem;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.cyber-path__lead { max-width: 76rem; margin-top: 1.5rem; font-size: var(--fs-sm); color: #5c5c5c; }

.cyber-path__cta { margin-top: 1.5rem; }

@media (max-width: 999px) {
  .cyber-path { padding: 4rem var(--gutter); }
}

/* ---------------------------------------------------------------- the flow

   The stages as a journey rather than three cards side by side: a dashed rail, a pulse of
   lime travelling it, and a ring firing at each node as the pulse arrives. The modules are
   chips instead of bullet lists, which is most of what took the wall of text away.

   All of it is CSS. base.css stops every animation under prefers-reduced-motion, and what
   is left then is still a legible diagram. */

.flow {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2.5rem;
  margin-top: 5rem;
}
/* The track and the pulse both span between the first and last node centres, which sit a
   sixth of the width in from each end. */
.flow::before,
.flow::after {
  content: '';
  position: absolute;
  top: 3.5rem;                                    /* the node's vertical centre */
  left: 16.6%;
  right: 16.6%;
  height: 2px;
}
.flow::before {
  background: repeating-linear-gradient(90deg, #d4cfc6 0 8px, transparent 8px 18px);
}
.flow::after {
  background: linear-gradient(90deg, transparent, var(--lime) 45%, transparent);
  background-size: 26% 100%;
  background-repeat: no-repeat;
  animation: flow-pulse 3.6s linear infinite;
}
@keyframes flow-pulse {
  from { background-position: -30% 0; }
  to   { background-position: 130% 0; }
}

/* A column so the outcome pill can be pushed to the bottom: the three stages carry
   different numbers of chips, and without this their outcomes sit at three heights. */
.flow__stage {
  position: relative;
  /* Above both rails. ::after paints after the children, so without this the lime pulse
     ran over the chips and the type rather than behind the nodes. */
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.flow__node {
  position: relative;
  display: grid;
  place-items: center;
  width: 7rem;                                    /* 112 */
  height: 7rem;
  margin: 0 auto;
  background: #fff;
  border: 2px solid #e6e3df;
  border-radius: 50%;
}
.flow__node svg { width: 2.75rem; height: 2.75rem; }
/* Fires as the pulse reaches this node, so the three go off in sequence down the rail. */
.flow__node::after {
  content: '';
  position: absolute;
  inset: -2px;
  border: 2px solid var(--lime);
  border-radius: 50%;
  animation: flow-ring 3.6s ease-out infinite;
}
.flow__stage:nth-child(2) .flow__node::after { animation-delay: 1.2s; }
.flow__stage:nth-child(3) .flow__node::after { animation-delay: 2.4s; }
@keyframes flow-ring {
  0%        { transform: scale(1); opacity: 0; }
  6%        { opacity: 1; }
  34%, 100% { transform: scale(1.42); opacity: 0; }
}

.flow__num {
  position: absolute;
  right: -0.25rem;
  bottom: -0.25rem;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--lime);
  border-radius: 50%;
}

.flow__who { margin-top: 1.75rem; font-size: var(--fs-item); line-height: 1.2; }
.flow__sub { margin-top: 0.5rem; font-size: var(--fs-sm); color: #8b857c; }

/* Rising difficulty, said with three bars rather than a sentence. */
.flow__level { display: flex; justify-content: center; gap: 0.3125rem; margin-top: 1rem; }
.flow__level span {
  width: 1.75rem;
  height: 0.25rem;
  border-radius: 999px;
  background: #e0dbd3;
}
.flow__level span.on { background: var(--lime); }

.flow__name {
  margin-top: 1.5rem;
  font-size: var(--fs-h2-sm);
  line-height: 1.2;
  font-weight: 400;
}

.flow__chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1.25rem;
  margin-bottom: 1.75rem;
}
.flow__chips li {
  padding: 0.4375rem 0.875rem;
  font-size: var(--fs-sm);
  color: #4a4a4a;
  background: #fff;
  border: 1px solid #e0dbd3;
  border-radius: 999px;
}

/* The outcome, said as an outcome. As a bare lime pill it read as one more module chip in
   a different colour, so it carries its own label now and sits in a block rather than in
   the same pill shape the chips use. */
.flow__out {
  display: block;
  width: 100%;
  margin-top: auto;
  padding: 1rem 1.25rem;
  background: rgb(170 255 0 / 16%);
  border: 1px solid rgb(170 255 0 / 55%);
  border-radius: 0.5rem;
}
.flow__out-k {
  display: block;
  font-size: var(--fs-sm);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #6f7a3f;
}
.flow__out-v {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  font-size: var(--fs-item);
  line-height: 1.2;
  color: var(--ink);
}
/* A tick, so the block reads as something achieved rather than something offered. */
.flow__out-v::before {
  content: '';
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  background: var(--ink);
  mask: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 12.5 5 5L20 6.5'/%3E%3C/svg%3E");
  -webkit-mask: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 12.5 5 5L20 6.5'/%3E%3C/svg%3E");
}

/* Under the middle of the flow, not hanging off the left of it. */
.cyber-path__cta { display: block; width: fit-content; margin: 4rem auto 0; }

@media (max-width: 999px) {
  /* Stacked, so the rail runs down the middle of the nodes instead of across them. */
  .flow { grid-template-columns: 1fr; gap: 3.5rem; }
  .flow::before,
  .flow::after {
    top: 3.5rem;
    bottom: 3.5rem;
    left: calc(50% - 1px);
    right: auto;
    width: 2px;
    height: auto;
  }
  .flow::before { background: repeating-linear-gradient(180deg, #d4cfc6 0 8px, transparent 8px 18px); }
  .flow::after {
    background: linear-gradient(180deg, transparent, var(--lime) 45%, transparent);
    background-size: 100% 26%;
    animation-name: flow-pulse-y;
  }
  @keyframes flow-pulse-y {
    from { background-position: 0 -30%; }
    to   { background-position: 0 130%; }
  }
  .flow__stage { padding-top: 0.5rem; background: var(--paper); }
  .flow__node { width: 6rem; height: 6rem; }
  .flow__node svg { width: 2.25rem; height: 2.25rem; }
}
