/* /agentic-ai, the Agentic AI page, and the only place Autobricks is branded.
   It was four pages (a partnership hub, a training page, a products page and this one);
   they are one now, because they were all selling the same three things.

   Lengths are rem on the same 1920 grid as the rest of the site (design px / 16). Unlike
   the marketing pages this is not a clone of anything on Wix any more, so the numbers here
   are chosen rather than measured, but they still scale the same way.

   The type is the site's throughout, Questrial on the measured scale, and eyebrows set
   uppercase at 0.1em exactly like .hero__eyebrow on the home page. An earlier draft used a
   monospace label voice taken from the Autobricks deck; it was the one thing on the page
   that did not look like the rest of the site, so what is Autobricks' here is the indigo
   accent and nothing else. Every --ab-* colour sits inside .ab so it cannot reach a page
   held against the capture. */

/* --------------------------------------------------------------- shared bits */

/* The two pages this sheet serves were near enough identical to be mistaken for each
   other: same hero photo, same co-brand, same four-card grid, same closing form. They
   differ deliberately now. /ai-transformation is dark, indigo, and abstract, because it
   sells a system that runs without you. /agentic-ai-training is light, red, and
   photographic, because it sells four days in a room with your team. The accent is one
   variable and the deck's two accents are what fills it. */
.ab { --ab-accent: var(--ab-indigo); }
.ab--train { --ab-accent: var(--ab-red); }

.ab .section { padding: 7rem var(--gutter); }    /* 112 */
.ab .section__inner { text-align: left; }

/* The site's own eyebrow, same uppercase and 0.1em tracking as .hero__eyebrow, with a
   leading dot. That dot is the one place indigo appears on every section, which is enough
   to mark the page as Autobricks' without competing with lime. */
.ab-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;                                  /* 10 */
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ab-grey);
}
.ab-eyebrow::before {
  content: '';
  flex: none;
  width: 0.5rem;                                  /* 8 */
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ab-accent);
}
.ab-eyebrow--light { color: rgb(255 252 248 / 72%); }

.ab-h2 {
  max-width: 84rem;                               /* 1344 */
  margin-top: 1.75rem;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.ab-lead {
  max-width: 76rem;                               /* 1216 */
  margin-top: 1.5rem;
  font-size: var(--fs-sm);
}

/* An indigo rule rather than the site's lime tick: the tick lives in home.css, which this
   page does not load, and a second brand's list should not wear the first brand's bullet. */
.ab-list { margin-top: 1.5rem; }
.ab-list li {
  position: relative;
  padding-left: 1.375rem;                         /* 22 */
  margin-top: 0.875rem;
  font-size: var(--fs-sm);
}
.ab-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 0.625rem;                                /* 10 */
  height: 1px;
  background: var(--ab-accent);
}

.ab-grid { display: grid; gap: 1.5rem; margin-top: 3rem; }
.ab-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ab-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.ab-card {
  display: flex;
  flex-direction: column;
  padding: 2rem 1.75rem;
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;                        /* 6, the site's card radius */
}
.ab-card h3 { margin-top: 0.75rem; font-size: var(--fs-item); line-height: 1.25; }
.ab-card p { margin-top: 0.75rem; font-size: var(--fs-sm); color: var(--ab-grey); }
.ab-card .ab-eyebrow { margin-top: 0.75rem; }

.ab-num {
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ab-accent);
}

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

.ab-hero {
  justify-content: center;
  min-height: 50rem;                              /* 800 */
  padding: 7rem var(--gutter);
  background: var(--ink);
  color: var(--paper);
  text-align: center;
}
/* The image is a photograph, so the type needs a floor under it rather than luck. Darkest
   in the middle, where the words are, and the section's own --ink shows through at the
   edges so it still reads as part of the black band. */
.ab-hero .section__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 50%, rgb(0 0 0 / 62%) 0%, rgb(0 0 0 / 88%) 100%);
}
.ab-hero__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* The co-brand, which used to sit in the site header. It belongs here now: this is the one
   page where Autobricks is what is being sold. */
.ab-cobrand { display: flex; align-items: center; gap: 0.875rem; }
.ab-cobrand img { width: 2.75rem; height: 2.75rem; }   /* 44, art draws its own corners */
.ab-cobrand span {
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.ab-hero__title {
  max-width: 72rem;                               /* 1152 */
  margin-top: 2.25rem;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.ab-hero__lead {
  max-width: 56rem;                               /* 896 */
  margin-top: 2rem;
  font-size: var(--fs-body);
  color: rgb(255 252 248 / 82%);
}
.ab-hero__cta { display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; margin-top: 3rem; }
.ab-hero__note {
  margin-top: 1.5rem;
  font-size: var(--fs-sm);
  color: rgb(255 252 248 / 62%);
}

/* ----------------------------------------------------- three ways to work with us */

.ab-ways { background: var(--paper); }
.ab-ways__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2rem;
  margin-top: 3.5rem;
}
.ab-way {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--ab-paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;
}
.ab-way > img { width: 100%; height: 14rem; object-fit: cover; }   /* 224 */
.ab-way__body { display: flex; flex-direction: column; flex: 1; padding: 2rem; }
.ab-way h3 { margin-top: 0.75rem; font-size: var(--fs-h2-sm); line-height: 1.2; }
.ab-way p { margin-top: 0.875rem; font-size: var(--fs-sm); color: var(--ab-grey); }

/* The only affordance on a card, so it has to read as one without being a button that
   competes with the lime CTAs. */
.ab-more {
  align-self: flex-start;
  margin-top: auto;
  padding-top: 1.75rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ab-accent);
}
.ab-more::after { content: ' →'; }
.ab-more:hover { opacity: 0.7; }

/* Cards that are only a label, a title and the link, the detail is in the dialog. */
.ab-card .ab-more { padding-top: 1.5rem; }
.ab-plat .ab-card { overflow: hidden; padding: 0; }
.ab-plat .ab-card > img { width: 100%; height: 11rem; object-fit: cover; }   /* 176 */
.ab-plat .ab-card > :not(img) { margin-inline: 1.75rem; }
.ab-plat .ab-card > span { margin-top: 1.5rem; }
.ab-plat .ab-card > .ab-more { margin-bottom: 1.75rem; }

/* --------------------------------------------------------------------- modals */

.ab-modal {
  /* base.css resets margin on everything, which beats the UA's `dialog { margin: auto }`
     and leaves an open dialog pinned to the top-left instead of centred. */
  margin: auto;
  width: min(34rem, calc(100vw - 2.5rem));
  max-height: calc(100vh - 4rem);
  padding: 2.5rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.5rem;
}
.ab-modal::backdrop { background: rgb(0 0 0 / 62%); }
.ab-modal h3 { margin-top: 0.75rem; font-size: var(--fs-h2-sm); line-height: 1.25; }
.ab-modal p { margin-top: 1rem; font-size: var(--fs-sm); }
.ab-modal .ab-outcome { margin-top: 1.5rem; }
.ab-modal .btn { margin-top: 2rem; }
.ab-modal form { float: right; margin: -1rem -1rem 0 0; }
.ab-modal form button {
  width: 2.25rem;
  height: 2.25rem;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ab-grey);
}
.ab-modal form button:hover { color: var(--ink); }

/* -------------------------------------------------------------- case studies */

.ab-cases { background: var(--ab-paper); }
.ab-outcome {
  margin-top: auto;
  padding-top: 1.5rem;
  border-top: 1px solid var(--ab-line);
}
.ab-outcome span {
  display: block;
  margin-bottom: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ab-accent);
}

/* ----------------------------------------------------------------- the numbers */

.ab-outcomes { background: var(--ab-paper); }
.ab-stat {
  display: flex;
  flex-direction: column;
  padding-top: 1.5rem;
  border-top: 1px solid rgb(255 252 248 / 22%);
}
.ab-stat__n { font-size: var(--fs-h3); line-height: 1.1; }
.ab-stat__n small { font-size: 0.5em; }
.ab-stat__of { margin-top: 0.875rem; font-size: var(--fs-sm); }

/* ------------------------------------------------------------------ platforms */

.ab-platforms { background: var(--paper); }
.ab-platforms .ab-grid { margin-top: 1.5rem; }
.ab-plat .ab-card h3 { font-size: var(--fs-h2-sm); }

/* ------------------------------------------------------------------- training */

.ab-training { background: var(--ab-paper); }

.ab-proof {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
  margin-top: 2.5rem;
}
.ab-proof li {
  padding-top: 1.25rem;
  border-top: 1px solid var(--ab-line);
  font-size: var(--fs-sm);
  color: var(--ab-grey);
}
.ab-proof b { display: block; margin-bottom: 0.375rem; font-size: var(--fs-h3); font-weight: 400; color: var(--ab-ink); }

/* ----------------------------------------------------------------- start here */

.ab-start { background: var(--paper); }
.ab-start__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 4rem;
  margin-top: 3rem;
}
.ab-start__cols { display: grid; gap: 2.5rem; align-content: start; }

.ab-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
  padding: 2.5rem;
  background: var(--ab-paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;
}
.ab-form .field--wide,
.ab-form .form-error,
.ab-form .contact-form__submit { grid-column: 1 / -1; }
.ab-form label { display: block; margin-bottom: 0.5rem; font-size: var(--fs-sm); }
.ab-form input,
.ab-form select,
.ab-form textarea {
  width: 100%;
  padding: 0.75rem 0.875rem;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid #b9b6b2;
  border-radius: 0.25rem;
}
.ab-form select { padding-right: 2rem; }
.ab-form textarea { resize: vertical; }
.ab-form input:focus-visible,
.ab-form select:focus-visible,
.ab-form textarea:focus-visible { outline: 2px solid var(--ab-accent); outline-offset: 1px; }
.ab-form [aria-invalid='true'] { border-color: #df3131; }

/* ------------------------------------------------------- tablet + mobile */

@media (max-width: 999px) {
  .ab .section { padding: 4rem var(--gutter); }
  .ab-hero { padding-top: 5rem; padding-bottom: 5rem; }
  .ab-grid { margin-top: 2.5rem; }
  .ab-grid--3,
  .ab-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ab-ways__grid { grid-template-columns: 1fr; gap: 1.5rem; margin-top: 2.5rem; }
  .ab-way { padding: 2rem 1.5rem; }
  .ab-way__go { padding-top: 1.5rem; }
  .ab-days { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; margin-top: 2.5rem; }
  .ab-start__grid { grid-template-columns: 1fr; gap: 2rem; margin-top: 2.5rem; }
}

@media (max-width: 749px) {
  .ab-grid--3,
  .ab-grid--4,
  .ab-days,
  .ab-proof,
  .ab-form { grid-template-columns: 1fr; }
  .ab-form { padding: 1.5rem; }
  .ab-hero__cta .btn { width: 100%; }
  /* The copy block covers far more of the image at this width, so more of it sits over the
     lighter middle of the scrim. Darken it rather than hope. */
  .ab-hero .section__bg::after {
    background: radial-gradient(140% 80% at 50% 45%, rgb(0 0 0 / 74%) 0%, rgb(0 0 0 / 92%) 100%);
  }

  /* The mobile scale is tuned for body copy, and at this width --fs-h2-sm and --fs-item
     both land within a pixel of it, so a heading set in either stops looking like one.
     Same reason components.css overrides .pathway__name here. */
  .ab-hero__title { font-size: var(--fs-h1); }   /* 28, --fs-display is 22 here */
  .ab-h2 { font-size: 1.5rem; }          /* 24 */
  .ab-way h3 { font-size: 1.25rem; }     /* 20 */
  .ab-card h3 { font-size: 1.125rem; }   /* 18 */
}

/* ==================================================================== split heroes

   Both pages used to open on the same centred stack over the same photograph, which is
   most of why they read as one page. Each opens on a two-column hero now, and what sits
   in the second column is the difference: an abstract diagram of a system on the build
   page, a photograph of a room full of people on the training page. */

.ab-hero--split { text-align: left; }
.ab-hero--split .ab-hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: center;
  gap: 5rem;
  max-width: var(--content);
  margin-inline: auto;
}
.ab-hero--split .ab-hero__title,
.ab-hero--split .ab-hero__lead { max-width: none; }
.ab-hero--split .ab-hero__cta { justify-content: flex-start; }

/* The training page is the light one. Its hero is paper rather than ink, which is the
   single biggest thing telling the two apart at a glance. */
.ab-hero--light { background: var(--ab-paper); color: var(--ab-ink); }
.ab-hero--light .ab-hero__lead { color: var(--ab-grey); }
.ab-hero--light .ab-hero__note { color: var(--ab-grey-2); }
.ab-hero--light .ab-cobrand { color: var(--ab-ink); }

/* ------------------------------------------------------- the orchestration diagram

   /ai-transformation sells work that happens without anybody watching, so the hero shows
   it happening: a hub with four functions hanging off it and a pulse running out to each.
   Inline SVG, animated by dashoffset alone, so there is no library and no script. With
   JavaScript off it is a static diagram, which still says the same thing. */

/* The hero photograph is a close-up of a circuit board, which is exactly the wrong thing
   to draw a diagram of a system on top of. The panel gives the diagram its own ground. */
.ab-orbit {
  width: 100%;
  height: auto;
  padding: 1.5rem;
  background: rgb(6 6 6 / 72%);
  border: 1px solid rgb(255 252 248 / 12%);
  border-radius: 0.5rem;
}
.ab-orbit__wire { stroke: rgb(255 252 248 / 20%); stroke-width: 1.5; fill: none; }
.ab-orbit__pulse {
  stroke: var(--ab-accent);
  stroke-width: 2.5;
  fill: none;
  stroke-linecap: round;
  stroke-dasharray: 10 190;
  animation: ab-pulse 3.2s linear infinite;
}
.ab-orbit__pulse:nth-of-type(2) { animation-delay: 0.8s; }
.ab-orbit__pulse:nth-of-type(3) { animation-delay: 1.6s; }
.ab-orbit__pulse:nth-of-type(4) { animation-delay: 2.4s; }
@keyframes ab-pulse {
  from { stroke-dashoffset: 200; }
  to   { stroke-dashoffset: 0; }
}
.ab-orbit__hub { fill: var(--ab-accent); }
.ab-orbit__node { fill: rgb(255 252 248 / 8%); stroke: rgb(255 252 248 / 26%); }
.ab-orbit text {
  font-family: var(--font);
  fill: var(--paper);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.ab-orbit .ab-orbit__hub-label { fill: var(--paper); font-size: 15px; }

/* The hub breathes so the diagram is not dead on arrival, which a static one looks. */
.ab-orbit__ring {
  fill: none;
  stroke: var(--ab-accent);
  transform-origin: 260px 200px;
  animation: ab-ring 3.2s ease-out infinite;
}
@keyframes ab-ring {
  0%   { transform: scale(0.7); opacity: 0.55; }
  70%  { transform: scale(1.6); opacity: 0; }
  100% { transform: scale(1.6); opacity: 0; }
}

/* ------------------------------------------------------------- the training photo */

.ab-shot { position: relative; }
.ab-shot img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 0.375rem;
}
/* Sits on the photograph rather than beside it, so the claim and the evidence are one
   object. The count is the page's whole argument in three words. */
.ab-shot__tag {
  position: absolute;
  left: 1.5rem;
  bottom: 1.5rem;
  right: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  padding: 1.25rem 1.5rem;
  background: rgb(22 21 15 / 88%);
  border-radius: 0.375rem;
  color: var(--paper);
}
.ab-shot__tag b { font-size: var(--fs-h2-sm); font-weight: 400; }
.ab-shot__tag span { font-size: var(--fs-sm); color: rgb(255 252 248 / 70%); }

/* ==================================================================== the four days

   A four-up card grid is what the build page uses for its case studies, and days are a
   sequence rather than four alternatives, so this is a rail instead. It also stops the
   two pages having the same shape in the middle. */

.ab-rail { margin-top: 3.5rem; border-top: 1px solid var(--ab-line); }
.ab-step {
  display: grid;
  grid-template-columns: 11rem minmax(0, 1fr) minmax(0, 1fr);
  gap: 2.5rem;
  align-items: start;
  padding: 2.5rem 0;
  border-bottom: 1px solid var(--ab-line);
}
.ab-step__day {
  position: relative;
  padding-left: 1.75rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ab-accent);
}
/* The dot and the line through it are the rail: each step draws its own segment, so the
   sequence reads without a wrapper element holding a background. */
.ab-step__day::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background: var(--ab-accent);
}
.ab-step__day::after {
  content: '';
  position: absolute;
  left: 0.28rem;
  top: 1.6em;
  bottom: -3.5rem;
  width: 1px;
  background: var(--ab-line);
}
.ab-step:last-child .ab-step__day::after { display: none; }
.ab-step h3 { font-size: var(--fs-h2-sm); line-height: 1.2; }
.ab-step p { margin-top: 0.875rem; font-size: var(--fs-sm); color: var(--ab-grey); }
.ab-step__ships {
  padding: 1.25rem 1.5rem;
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;
}
.ab-step__ships b {
  display: block;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--ab-grey-2);
}
.ab-step__ships span { display: block; margin-top: 0.625rem; font-size: var(--fs-item); }
.ab-step .ab-more { margin-top: 1.25rem; }

/* ------------------------------------------------------------------ on scroll

   Progressive: nothing is hidden until nav.js says it can also unhide it, so with the
   script off every section is simply there. */
html[data-reveal] [data-reveal] {
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
html[data-reveal] [data-reveal].is-in { opacity: 1; transform: none; }

@media (max-width: 999px) {
  .ab-hero--split .ab-hero__inner { grid-template-columns: 1fr; gap: 3rem; }
  .ab-step { grid-template-columns: 1fr; gap: 1.25rem; padding: 2rem 0; }
  .ab-step__day::after { display: none; }
}

/* ================================================== the training page's evidence

   Four sections from the deck, in the site's own voice rather than as slide screenshots:
   how it is taught, what learners shipped, the internal tools, and the class-group
   messages. They sit between the four days and the form, so the page argues its case
   before it asks for anything. */

/* ------------------------------------------------------------------- pedagogy */

.ab-peda { background: var(--paper); }
.ab-peda__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 4rem;
  align-items: start;
  margin-top: 3.5rem;
}
.ab-peda__shot img {
  width: 100%;
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;
}
.ab-peda__shot figcaption {
  margin-top: 1rem;
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ab-grey-2);
}
.ab-peda__list { display: grid; gap: 2.5rem; }
.ab-peda__list h3 { margin-top: 0.75rem; font-size: var(--fs-h2-sm); line-height: 1.2; }
.ab-peda__list p { margin-top: 0.75rem; font-size: var(--fs-sm); color: var(--ab-grey); }
.ab-peda__list p b { font-weight: 400; color: var(--ab-ink); border-bottom: 2px solid var(--ab-accent); }

/* -------------------------------------------------------------- what they shipped */

.ab-shipped { background: var(--ab-paper); }
.ab-built {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem;
  margin-top: 3.5rem;
}
/* An accent edge each, the way the deck sets them, so the two read as a pair. */
.ab-built__item {
  display: flex;
  flex-direction: column;
  padding: 2.25rem;
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-left: 3px solid var(--ab-accent);
  border-radius: 0.375rem;
}
.ab-built__item:last-child { border-left-color: var(--ab-indigo); }
.ab-built__item h3 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1rem;
  margin-top: 0.75rem;
  font-size: var(--fs-h2-sm);
}
/* The address, not a link: these are shown as evidence, not as somewhere to go. */
.ab-built__item h3 span {
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
  color: var(--ab-grey-2);
}
.ab-built__desc { margin-top: 1rem; font-size: var(--fs-sm); color: var(--ab-grey); }
.ab-built__item .ab-list { margin-bottom: 2rem; }
.ab-built__item > img {
  width: 100%;
  margin-top: auto;
  border-radius: 0.25rem;
}

/* ---------------------------------------------------------------- internal tools */

.ab-tools { background: var(--paper); }
.ab-tools__grid .ab-card { padding: 0 0 1.75rem; overflow: hidden; }
.ab-tools__grid .ab-card > img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: top left;
  border-bottom: 1px solid var(--ab-line);
}
.ab-tools__grid .ab-card > :not(img) { margin-inline: 1.75rem; }
.ab-tools__grid .ab-card > span { margin-top: 1.5rem; }
.ab-tools__was {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--ab-line);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ab-grey-2);
}

/* -------------------------------------------------------------------- the wall

   A masonry column layout, because the screenshots are wildly different shapes and a
   grid would either crop them or leave holes. columns is old, well supported and needs
   no script. break-inside stops a message being split across two columns. */

.ab-voices { background: var(--ab-ink); color: var(--paper); }
.ab-voices .ab-eyebrow { color: rgb(255 252 248 / 72%); }
.ab-voices .ab-lead { color: rgb(255 252 248 / 72%); }
/* Two, not three. The screenshots are wide and their type is baked in, so a third
   column shrinks the widest messages past legible. */
.ab-voices__wall {
  margin-top: 3.5rem;
  columns: 2;
  column-gap: 1.5rem;
}
.ab-voices__wall li {
  break-inside: avoid;
  margin-bottom: 1.5rem;
}
.ab-voices__wall img {
  display: block;
  width: 100%;
  border-radius: 0.375rem;
}

@media (max-width: 999px) {
  .ab-peda__grid, .ab-built { grid-template-columns: 1fr; gap: 2.5rem; }
}
@media (max-width: 749px) {
  .ab-voices__wall { columns: 1; }
  .ab-built__item { padding: 1.75rem; }
}

/* ------------------------------------------------------------ zoomable screenshots

   The app shots render about a sixth of their source width inside a card, and the
   testimonials are only readable at size. A button rather than a bare image, so it is
   reachable by keyboard; with JavaScript off the picture is simply still there. */

.ab-shot-zoom {
  display: block;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  cursor: zoom-in;
}
.ab-shot-zoom img { display: block; width: 100%; border-radius: 0.25rem; }
.ab-shot-zoom:hover img { opacity: 0.88; }
.ab-shot-zoom:focus-visible { outline: 2px solid var(--ab-accent); outline-offset: 3px; }

.ab-zoom {
  /* Same trap as .ab-modal above: base.css resets margin everywhere, which beats the
     UA's `dialog { margin: auto }` and leaves the dialog pinned to the top-left. */
  margin: auto;
  width: min(94vw, 82rem);
  max-height: 92vh;
  padding: 1rem;
  background: var(--ab-ink);
  border: 0;
  border-radius: 0.5rem;
}
.ab-zoom::backdrop { background: rgb(0 0 0 / 82%); }
.ab-zoom img { display: block; width: 100%; height: auto; border-radius: 0.25rem; }
.ab-zoom form { display: flex; justify-content: flex-end; }
.ab-zoom form button {
  padding: 0 0.5rem;
  font-size: var(--fs-item);
  line-height: 1;
  color: rgb(255 252 248 / 70%);
  background: none;
  border: 0;
  cursor: pointer;
}
.ab-zoom form button:hover { color: var(--paper); }

/* ------------------------------------------------------------- the testimonial wall

   Two rows travelling in opposite directions. Each row carries its own copy in the markup
   rather than having one cloned by script, so translating by -50% loops seamlessly with
   JavaScript off too. Click a message to open it full size.

   Rows share a height and the images keep their own width, which is what makes six
   screenshots of wildly different shapes read as one set. */

.ab-wall {
  display: grid;
  gap: 1.5rem;
  margin-top: 3.5rem;
  overflow: hidden;
  /* Softens both ends so a message never appears to be sliced off at the edge. */
  mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.ab-wall__col {
  display: flex;
  gap: 1.5rem;
  width: max-content;
  animation: ab-crawl 34s linear infinite;
}
.ab-wall__col--down { animation-duration: 40s; animation-direction: reverse; }
/* The images are pre-scaled to one type size and padded to one height, so the row only
   has to set a height and let each keep its own width. */
.ab-wall__col > li { flex: none; height: 24rem; }          /* 384, near the normalised size */
.ab-wall__col .ab-shot-zoom { width: auto; height: 100%; }
.ab-wall__col img {
  width: auto;
  height: 100%;
  border: 1px solid rgb(255 252 248 / 10%);
  border-radius: 0.375rem;
}
@keyframes ab-crawl {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Not a crawl at all then: rows the reader drags. */
@media (prefers-reduced-motion: reduce) {
  /* The scroller has to be the container: the rows are width:max-content, so putting
     overflow on them leaves the wall itself clipped and nothing reachable. */
  .ab-wall { overflow-x: auto; mask-image: none; -webkit-mask-image: none; }
  .ab-wall__col { animation: none; }
}

/* Horizontal travel does not fight the page scroll, so a phone keeps the marquee and all
   six messages with it. Only the height comes down. */
@media (max-width: 749px) {
  .ab-wall__col > li { height: 15rem; }
}

/* ------------------------------------------------------------- the numbers, louder

   The four ranges were bare figures on black. They keep a category above them, the line
   that explains what the number is, and the mechanism underneath, so the section can be
   read rather than glanced at. */

.ab-stats { margin-top: 4rem; }
.ab-stat {
  display: flex;
  flex-direction: column;
  padding: 2rem 1.75rem;
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-top: 3px solid var(--ab-accent);
  border-radius: 0.375rem;
}
.ab-stat__cat {
  font-size: var(--fs-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ab-grey-2);
}
.ab-stat__n {
  margin-top: 1.25rem;
  font-size: var(--fs-h3);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ab-accent);
}
.ab-stat__n small { font-size: 0.42em; letter-spacing: 0; }
.ab-stat__of {
  margin-top: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--ab-line);
  font-size: var(--fs-item);
  line-height: 1.25;
}
.ab-stat__how { margin-top: 1rem; font-size: var(--fs-sm); color: var(--ab-grey); }
.ab-outcomes__sum {
  max-width: 76rem;
  margin-top: 3rem;
  font-size: var(--fs-sm);
  color: var(--ab-grey);
}
.ab-outcomes__sum b { color: var(--ab-ink); font-weight: 400; }

/* --------------------------------------------------------------- the build belt

   Two rows travelling opposite ways. Each carries its own copy in the markup, so -50%
   loops seamlessly with no script cloning anything, the same as the training page's wall. */

.ab-belt {
  display: grid;
  gap: 1.5rem;
  margin-top: 3.5rem;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.ab-belt__row {
  display: flex;
  gap: 1.5rem;
  width: max-content;
  animation: ab-belt 46s linear infinite;
}
.ab-belt__row--back { animation-duration: 58s; animation-direction: reverse; }
@keyframes ab-belt {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.ab-belt__row > li {
  flex: none;
  width: 26rem;                                   /* 416 */
  padding: 1.75rem;
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;
}
.ab-belt__cat {
  font-size: var(--fs-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ab-accent);
}
.ab-belt__row h3 { margin-top: 0.75rem; font-size: var(--fs-h2-sm); line-height: 1.2; }
.ab-belt__row > li > p:last-child {
  margin-top: 0.75rem;
  font-size: var(--fs-sm);
  color: var(--ab-grey);
}

/* --------------------------------------------------------------- the six platforms

   Icons rather than photographs. Three of the six had stock images and three had none,
   and six cards where half carry a picture reads as an oversight rather than a set. */

.ab-plat {
  display: flex;
  flex-direction: column;
  padding: 2rem 1.75rem;
  background: var(--paper);
  border: 1px solid var(--ab-line);
  border-top: 3px solid var(--ab-accent);
  border-radius: 0.375rem;
}
.ab-plat__icon { width: 2.25rem; height: 2.25rem; color: var(--ab-accent); }
.ab-plat .ab-num { margin-top: 1.5rem; }
.ab-plat h3 { margin-top: 0.5rem; font-size: var(--fs-h2-sm); line-height: 1.2; }
.ab-plat__line { margin-top: 0.875rem; font-size: var(--fs-sm); color: var(--ab-grey); }

/* -------------------------------------------------------------------- grants */

.ab-grant { background: var(--ab-paper); }
.ab-grant__cta { margin-top: 2.5rem; }

@media (max-width: 999px) {
  .ab-belt__row > li { width: 21rem; }
}
@media (max-width: 749px) {
  .ab-belt__row > li { width: 18rem; padding: 1.5rem; }
}

/* The belt is full-bleed, and .section centres its children, so without this it shrinks to
   its content and a row can end in the middle of the screen with white space beside it. */
.ab-belt { width: 100%; }

/* -------------------------------------------- the platforms, as alternating rows

   The shape /cybersecurity uses for the Arena: a media panel on one side over an offset
   block of colour, the copy and its feature list on the other, sides swapping down the
   page. Its own rules rather than .arena-row, which lives in home.css and is absolutely
   positioned against hard-coded 1920 coordinates.

   The panels are placeholders. Swapping one for a real screenshot means replacing the
   inner div with an <img> or a <video>; the frame and the colour block do not move. */

.ab-rows { display: grid; gap: 6rem; margin-top: 4.5rem; }
.ab-row {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 5rem;
  align-items: center;
}
.ab-row--reverse .ab-row__media { order: 2; }

/* The block of colour sits behind and down-left, so the frame reads as lifted off it. */
.ab-row__media { position: relative; padding: 0 2.5rem 2.5rem 0; }
.ab-row__media::before {
  content: '';
  position: absolute;
  inset: 2.5rem 0 0 2.5rem;
  border-radius: 0.375rem;
}
.ab-row__media--indigo::before { background: rgb(42 45 217 / 12%); }
.ab-row__media--red::before { background: rgb(229 37 29 / 10%); }

.ab-row__shot,
.ab-row__media img,
.ab-row__media video {
  position: relative;
  display: block;
  width: 100%;
  border-radius: 0.375rem;
}
/* Only the placeholder is 4:3. A real screenshot keeps its own shape, from the width and
   height on the tag: these are 17:10, and cropping them to 4:3 would take a quarter of the
   interface off the sides, which is the one thing a screenshot of an interface may not do.
   The colour block behind sizes itself off the frame either way. */
.ab-row__shot { aspect-ratio: 4 / 3; }
.ab-row__media img,
.ab-row__media video { height: auto; }

/* What a placeholder should look like: obviously a slot, not a broken image. */
.ab-row__shot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  background: var(--paper);
  border: 1px dashed var(--ab-line);
}
.ab-row__shot svg { width: 3.5rem; height: 3.5rem; color: var(--ab-accent); }
.ab-row__shot p { font-size: var(--fs-item); color: var(--ab-ink); }
.ab-row__soon {
  font-size: var(--fs-sm) !important;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ab-grey-2) !important;
}

.ab-row__copy h3 { margin-top: 0.5rem; font-size: var(--fs-h3); line-height: 1.15; }
.ab-row__sub { margin-top: 1.25rem; font-size: var(--fs-body); color: var(--ab-grey); }
.ab-row__copy .ab-list { margin-top: 2rem; }

/* ------------------------------------------------------------------------ grants */

.ab-grant { background: var(--paper); }
.grant-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
  margin-top: 3.5rem;
}
.grant {
  padding: 2.25rem;
  background: var(--ab-paper);
  border: 1px solid var(--ab-line);
  border-radius: 0.375rem;
}
.grant__tag {
  font-size: var(--fs-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ab-accent);
}
.grant h3 { margin-top: 0.75rem; font-size: var(--fs-h2-sm); line-height: 1.2; }
.grant__for { margin-top: 0.625rem; font-size: var(--fs-sm); color: var(--ab-grey); }

/* A definition list, because that is what these are: three labelled facts, not prose. */
.grant__facts { margin-top: 1.75rem; }
.grant__facts > div {
  display: grid;
  grid-template-columns: 10rem minmax(0, 1fr);
  gap: 1rem;
  padding: 0.875rem 0;
  border-top: 1px solid var(--ab-line);
  font-size: var(--fs-sm);
}
.grant__facts dt { color: var(--ab-grey-2); }
.grant__facts dd { color: var(--ab-ink); }
.grant__facts b { font-weight: 400; border-bottom: 2px solid var(--ab-accent); }

.grant__note {
  max-width: 76rem;
  margin-top: 2rem;
  font-size: var(--fs-sm);
  color: var(--ab-grey-2);
}
.ab-grant__cta { margin-top: 2rem; }

@media (max-width: 999px) {
  .grant-grid { grid-template-columns: 1fr; }
}
@media (max-width: 749px) {
  .grant { padding: 1.75rem; }
  .grant__facts > div { grid-template-columns: 1fr; gap: 0.25rem; }
}

/* A scheme we are not listed for yet reads as one we are, unless it is visibly held back.
   Dashed rather than solid, and the status says so in words as well. */
.grant--pending {
  background: transparent;
  border-style: dashed;
}
.grant--pending .grant__tag,
.grant--pending h3 { color: var(--ab-grey-2); }
.grant--pending .grant__facts b { border-bottom-color: var(--ab-grey-2); }
.grant__status {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1875rem 0.625rem;
  font-size: 0.8em;
  letter-spacing: 0.06em;
  color: var(--ab-ink);
  background: var(--ab-line);
  border-radius: 999px;
}

@media (max-width: 999px) {
  /* Stacked, media first in every row: alternating sides means nothing in one column. */
  .ab-rows { gap: 4rem; }
  .ab-row { grid-template-columns: 1fr; gap: 2.5rem; }
  .ab-row--reverse .ab-row__media { order: 0; }
  .ab-row__media { padding: 0 1.5rem 1.5rem 0; }
  .ab-row__media::before { inset: 1.5rem 0 0 1.5rem; }
}
