/* ============================================================
   TTCC — AI LAB
   ai-lab.html only. Five stacked sections: intro, the visual strip,
   the statement, the "AI, in practice" grid and the contact block.
   The shell (top bar, menu panel, search overlay, footer) comes from
   base.css + nav.css + footer.css, shared with every page.

   Proportions are carried over from the original AI Lab source, but
   the site's own conventions win: the 96px gutter, the 1300/900/700
   breakpoints, TTCC Sans throughout. Media stays square, with the
   orbit cards the one exception carried over from the source.
   ============================================================ */

/* Shared measure — the same gutter the top bar sits on. */
.ai-lab__inner {
  max-width: 2000px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* The small caps label above each section's heading. */
.ai-eyebrow {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #1a1a1a;
}

/* ----- Hero -----
   One viewport-high block below the fixed top bar: the copy sits
   vertically centred, the scroll note is pushed to the floor by the
   space between them. Nothing from the orbit shows on first load. */
.ai-hero {
  min-height: 100vh;
  background: #f8f8f6;                   /* edge to edge, behind the gutter */
}

.ai-hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* The inner box carries the section's own height so the note has a
     floor to sit on, and the top bar's clearance so the hero itself
     measures a clean viewport. */
  min-height: 100vh;
  padding-top: var(--topbar-h);          /* clears the fixed top bar */
  padding-bottom: 56px;
}

/* Centred both ways: vertically in whatever is left above the note,
   and horizontally with its lines centred too. */
.ai-hero__copy {
  flex: 1 1 auto;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.ai-hero__title {
  margin-top: 28px;
  font-size: clamp(40px, 6vw, 104px);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.05em;
  color: #000000;
}

.ai-hero__text {
  margin-top: 28px;
  margin-left: auto;
  margin-right: auto;
  max-width: 380px;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.55;
  color: #6b6b6b;
}

.ai-hero__note {
  flex: 0 0 auto;
  text-align: center;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #6b6b6b;
  /* js/ai-lab.js drops .is-hidden on once the page has moved. */
  transition: opacity 0.4s ease, transform 0.4s ease;
  will-change: opacity, transform;
}

.ai-hero__note.is-hidden {
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
}

/* The dot itself — an empty span, drawn entirely in CSS. */
.ai-hero__note span {
  position: relative;
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 10px;
  border-radius: 50%;
  background: currentColor;
  vertical-align: middle;
}

/* The ring that pulses out of it. */
.ai-hero__note span::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: 0;
  animation: ai-ring 2.4s ease-out infinite;
}

@keyframes ai-ring {
  0% { transform: scale(0.4); opacity: 0.7; }
  70% { transform: scale(1.6); opacity: 0; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .ai-hero__note span::after {
    animation: none;
  }
}

/* ----- Orbit -----
   A tall section whose stage sticks to the viewport; the wheel inside
   is rotated by js/ai-lab.js from scroll progress. The height is what
   gives the rotation its travel — 13 visuals x 48vh, floored at 620vh,
   the same rule the original page used. Change the count, change this.
   Everything here is geometry the script depends on: the wheel is a
   square positioned by its centre, and each card is placed on the
   circle by transform alone. */
.ai-orbit {
  position: relative;
  height: 624vh;
  background: #f8f8f6;                  /* continuous with the hero above */
}

.ai-orbit__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
}

/* The wheel's own width is the radius the script measures, so it is
   sized here and never in JS. */
.ai-orbit__wheel {
  position: absolute;
  left: 50%;
  top: 96%;
  width: min(1560px, 78vw, 148vh);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  transform-origin: 50% 50%;
  will-change: transform;
  pointer-events: none;                 /* only the front card takes clicks */
}

.ai-orbit__card {
  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(123px, 11vw, 185px);
  aspect-ratio: 0.755;
  transform-origin: 50% 50%;
  will-change: transform;
  pointer-events: none;
  border: 0;
  padding: 0;
  background: #eeeeee;
  /* The orbit is the one place that keeps the source's rounded cards —
     15px, straight from the original .visual-card. Every other image
     on the site stays square. overflow: hidden clips the img to it. */
  border-radius: 15px;
  overflow: hidden;
  appearance: none;
  -webkit-appearance: none;
}

/* Only the card at the front is reachable, and it is the one that
   opens the lightbox. */
.ai-orbit__card.is-active {
  pointer-events: auto;
  cursor: zoom-in;
}

.ai-orbit__card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 15px;                  /* matches the card it clips to */
}

/* Caption for whichever visual is at the front, sitting above it. */
.ai-orbit__focus {
  position: absolute;
  left: 50%;
  top: 88%;
  transform: translate(-50%, -50%);
  width: min(460px, 70vw);
  text-align: center;
  z-index: 25;
  pointer-events: none;
}

.ai-orbit__kicker {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: #000000;
}

.ai-orbit__title {
  margin-top: 12px;
  font-size: clamp(26px, 3vw, 48px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
  color: #000000;
}

.ai-orbit__meta {
  margin-top: 13px;
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #898989;
}

.ai-orbit__count {
  position: absolute;
  right: 30px;
  bottom: 27px;
  z-index: 5;
  font-size: 12px;
  letter-spacing: 0.12em;
  color: #000000;
}

.ai-orbit__count-now {
  font-size: 16px;
  font-weight: 500;
}

/* ----- Lightbox -----
   One dialog reused for all thirteen. It sits above the top bar and
   the menu panel, and locks the page with body.search-open — the same
   class the search overlay uses, so the two can never fight over it. */
.ai-lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  background: rgba(8, 8, 8, 0.96);
  color: #ffffff;
  opacity: 0;
  visibility: hidden;
  transition: opacity 320ms ease, visibility 320ms;
}

.ai-lightbox.is-open {
  opacity: 1;
  visibility: visible;
}

.ai-lightbox__inner {
  height: min(84svh, 900px);
  max-width: min(90vw, 900px);
  display: flex;
  flex-direction: column;
  align-items: center;
  transform: scale(0.78);
  transition: transform 500ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.ai-lightbox.is-open .ai-lightbox__inner {
  transform: scale(1);
}

.ai-lightbox__img {
  display: block;
  min-height: 0;
  height: calc(100% - 46px);
  max-width: 100%;
  object-fit: contain;
  border-radius: 0;
}

.ai-lightbox__caption {
  width: 100%;
  padding-top: 14px;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.ai-lightbox__close {
  position: absolute;
  top: 28px;
  right: 30px;
  padding: 10px;
  border: 0;
  background: none;
  color: #ffffff;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

.ai-lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  padding: 14px 18px;
  border: 0;
  background: none;
  color: #ffffff;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 200ms ease;
}

.ai-lightbox__nav:hover {
  opacity: 1;
}

.ai-lightbox__nav--prev { left: 18px; }
.ai-lightbox__nav--next { right: 18px; }

/* ----- Statement ----- */
.ai-statement {
  /* Fills the viewport with the copy centred in it. */
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 160px 0;
  background: #0a0a0a;
  color: #ffffff;
  text-align: center;
}

.ai-statement .ai-eyebrow {
  font-weight: 600;
  color: #ffffff;
}

.ai-statement__title {
  margin-top: 28px;
  font-size: clamp(36px, 5vw, 88px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.04em;
  color: #ffffff;
}

/* "Real" in an italic serif, as the source had it. No web font is
   involved — the source used Georgia, so this is the same local stack. */
.ai-statement__em {
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
  color: #ffffff;
}

.ai-statement__text {
  margin-top: 36px;
  margin-left: auto;
  margin-right: auto;
  max-width: 520px;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.6;
  color: #9a9a9a;
}

/* ----- AI, in practice ----- */
.ai-projects {
  padding: 96px var(--gutter) 120px;
  background: #f1f0ec;
}

/* This section carries its own gutter, so its inner wrapper drops both
   the shared 2000px cap and the shared side padding — the header row
   and the grid run the full width between the gutters, like the hero
   copy. Every other section keeps .ai-lab__inner as it is. */
.ai-projects > .ai-lab__inner {
  max-width: none;
  margin: 0;
  padding: 0;
}

/* Eyebrow and headline stack on the left; the "view all" link sits on
   the right, on the headline's baseline. */
.ai-projects__head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 24px;
  padding-bottom: 48px;
}

.ai-projects__head .ai-eyebrow {
  grid-column: 1;
  grid-row: 1;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #1a1a1a;
}

.ai-projects__title {
  grid-column: 1;
  grid-row: 2;
  margin-top: 4px;
  font-size: clamp(32px, 3.6vw, 64px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.04em;
  color: #000000;
}

.ai-projects__all {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: end;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #000000;
  border-bottom: 1px solid currentColor;
  padding-bottom: 4px;
}

.ai-projects__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  width: 100%;
}

/* The card is itself a grid: the media spans the full width, then the
   category and title stack in the left column while "Explore" sits in
   the right one, pulled down to the title's baseline. The children are
   appended in source order by js/ai-lab.js — placement is done here so
   the script stays a plain list. */
.ai-project-card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-content: start;
  color: #000000;
}

.ai-project-card__media-wrap {
  grid-column: 1 / -1;
  grid-row: 1;
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 8px;
  background: #e4e3df;
}

.ai-project-card__media {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 8px;
  transition: transform 600ms ease;
}

.ai-project-card:hover .ai-project-card__media {
  transform: scale(1.03);
}

/* The card's index, as a pill over the top-left of the media. */
.ai-project-card__num {
  position: absolute;
  top: 16px;
  left: 16px;
  padding: 6px 10px;
  border-radius: 999px;
  background: #ffffff;
  color: #1a1a1a;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
}

.ai-project-card__cat {
  grid-column: 1;
  grid-row: 2;
  margin-top: 18px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #6b6b6b;
}

.ai-project-card__title {
  grid-column: 1;
  grid-row: 3;
  margin-top: 8px;
  font-size: clamp(22px, 2vw, 32px);
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -0.03em;
}

/* The registry still carries a description; the card doesn't show it. */
.ai-project-card__desc {
  display: none;
}

.ai-project-card__more {
  grid-column: 2;
  grid-row: 2 / span 2;
  align-self: end;
  padding-left: 16px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 0;
}

/* ----- Contact ----- */
.ai-contact {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 var(--gutter);
  background: #f8f8f6;
  text-align: center;
}

/* The section carries its own gutter and centring, so the shared
   wrapper drops its cap and padding here. */
.ai-contact > .ai-lab__inner {
  max-width: none;
  margin: 0;
  padding: 0;
}

.ai-contact .ai-eyebrow {
  margin-bottom: 12px;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #6b6b6b;
}

/* inline-flex so the trailing arrow sits on the text's own line box;
   the auto margins keep the whole lockup centred. The arrow is part of
   the link text, so it inherits this weight — nothing bolds it. */
.ai-contact__link {
  display: inline-flex;
  align-items: center;
  gap: 0.2em;
  margin: 0 auto;
  font-size: clamp(40px, 5.6vw, 96px);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.04em;
  color: #000000;
  text-decoration: none;
  border-bottom: 3px solid #000000;
  padding-bottom: 6px;
}

/* ============================================================
   BREAKPOINTS — 1300 / 900 / 700, as everywhere else.
   ============================================================ */
@media (max-width: 1300px) {
  .ai-hero__text {
    margin-top: 24px;
  }

  .ai-statement {
    padding: 120px 0;
  }

  .ai-projects {
    padding: 96px var(--gutter) 120px;
  }

  .ai-contact {
    padding: 0 var(--gutter);
  }
}

@media (max-width: 900px) {
  .ai-hero__inner {
    padding-bottom: 48px;
  }

  /* Radius and card scale down together, so the wheel keeps its
     proportions in the shorter viewport. */
  .ai-orbit {
    height: 650vh;
  }

  .ai-orbit__wheel {
    top: 93%;
    width: min(120vw, 130vh);
  }

  .ai-orbit__card {
    width: clamp(96px, 14vw, 140px);
  }

  .ai-orbit__focus {
    top: 86%;
    width: 72vw;
  }


  /* One up, with air between the stacked cards. */
  .ai-projects__grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  .ai-projects__head {
    grid-template-columns: 1fr;
  }

  .ai-projects__all {
    grid-column: 1;
    grid-row: auto;
    justify-self: start;
    margin-top: 20px;
  }

}

@media (max-width: 700px) {
  /* Full viewport here too, so the hero and the orbit read as one
     surface with no seam — svh keeps mobile browser chrome from
     pushing the scroll note off screen. */
  .ai-hero,
  .ai-hero__inner {
    min-height: 100svh;
  }

  .ai-hero__inner {
    padding-bottom: 72px;
  }

  /* Still the orbit — the source keeps the wheel at every width, so
     there is no stacked fallback here; it just gets smaller. */
  .ai-orbit__wheel {
    top: 91%;
    width: min(150vw, 118vh);
  }

  .ai-orbit__card {
    width: 22vw;
    min-width: 79px;
    max-width: 114px;
  }

  .ai-orbit__focus {
    top: 84%;
    width: 72vw;
  }

  .ai-orbit__count {
    right: 16px;
    bottom: 18px;
  }

  .ai-lightbox__inner {
    height: 78svh;
    max-width: 92vw;
  }

  .ai-lightbox__close {
    top: 16px;
    right: 12px;
  }

  .ai-lightbox__nav {
    font-size: 18px;
    padding: 10px 12px;
  }


  /* A forced viewport height crowds the copy on a phone. */
  .ai-statement {
    min-height: 0;
    padding: 120px 0;
  }

  .ai-projects {
    padding: 72px var(--gutter) 90px;
  }

  .ai-contact {
    min-height: 0;
    padding: 120px var(--gutter);
  }
}
