/* Liat.ai v2 base: reset, type scale, section chrome, nav, and the shared
   primitives every page uses. Read DESIGN.md before changing anything here. */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 16px);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--pitch-ground);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* The nav is fixed, so the page owes it its own height. The hero's sticky
   stage would hide this on the home page, but not under reduced motion, where
   the stage falls back to static flow and slid under the bar. */
main { padding-top: var(--nav-h); }

img, video, svg, canvas { display: block; max-width: 100%; }
img, video { height: auto; }

button, input, select, textarea { font: inherit; color: inherit; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--cream);
  outline-offset: 3px;
}

::selection { background: var(--orange); color: var(--on-orange); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--pitch-deep); }
::-webkit-scrollbar-thumb { background: var(--chalk-line); border-radius: var(--r-pill); }
::-webkit-scrollbar-thumb:hover { background: var(--amber-dim); }

/* ---------------------------------------------------------------- type ---- */
/* The Two Voices Rule: Oswald is uppercase always, Archivo sentence case always. */

h1, h2, h3, h4 { margin: 0; font-weight: 500; }

.display {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  font-weight: 600;
  line-height: 0.94;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  text-wrap: balance;
}

.headline {
  font-family: var(--font-display);
  font-size: var(--fs-headline);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
}

.title {
  font-family: var(--font-body);
  font-size: var(--fs-title);
  font-weight: 600;
  line-height: 1.3;
}

/* Three marks in the instrument register, because they were one and it did not
   work. A label is one or two words stamped on equipment, so tracked caps suit
   it. A caption is a phrase you read, so it is sentence case with no tracking:
   "A HUMAN COMMENTARY TEAM, PER MATCH" set in 11px tracked caps was the single
   worst legibility fault on the site, and it was everywhere. Micro is for marks
   that only have to be present, never read. */
.label {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

.caption {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0;
}

.micro {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
}

/* The Tabular Rule. Anything that ticks while you watch it lives here. */
.data {
  font-family: var(--font-mono);
  font-size: var(--fs-data);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.lede {
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  color: var(--sage);
  max-width: var(--measure);
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

/* The Sixty-Eight Rule applies to prose, not to every paragraph element.
   Capping every p capped the scoreboard caption and the panel headings too,
   which cut their underlines off halfway across. */
.stack > p, .stack--sm > p, .prose p { max-width: var(--measure); }

.highlight { color: var(--orange); }
.amber { color: var(--amber); }
.sage { color: var(--sage); }

/* ------------------------------------------------------------- layout ---- */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--wide { max-width: var(--container-wide); }

/* The One Cadence Rule. Every section gets the same vertical padding.
   Separation comes from rules and register, never from alternating tone. */
.section {
  padding-block: var(--sp-section);
  position: relative;
}

/* One ground, all the way down, and that now means all the way down.

   There used to be a .section--deep here: a soft vignette at the top and bottom
   edges, applied to every other section. It was written as the gentle answer to
   the old site's flat alternating greens, and softening the edges did avoid the
   hard band. It did not avoid the alternation. Applied to every other section
   it still darkened the page on a two beat rhythm that had nothing to do with
   what the sections contained, which is the thing DESIGN.md rules out twice:
   "Sections do not alternate tone" and "Don't alternate section backgrounds to
   create separation."

   Separation is the full-width chalk rule under .section-head, plus the number
   and the eyebrow beside it. That is enough, and it is tied to the content
   rather than to a section's parity. Ground changes only on a change of
   register: the hero and the demo drop to Pitch Deep because the lights are
   off there, and the reading world inverts to paper entirely. */

.section--tight { padding-block: calc(var(--sp-section) * 0.6); }

/* The chalk rule that separates instrument from editorial.

   The three items used to be the same 11px with the meta pushed out to the far
   margin by an auto margin. That gave the row no internal hierarchy at all, and
   because eyebrows run from six to seventeen characters and metas from ten to
   forty, the gap it opened was a different width in every section. A thin strip
   of identical tiny type, ragged down the page, next to a 44px headline: the
   head read as nothing and the headline carried the whole section on its own.

   Now the block is one left cluster with real size contrast inside it, and the
   rule runs the full width behind it. Nothing is flush right, so every section
   head on the site starts and stacks identically. */
.section-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--sp-xs) 14px;
  padding-bottom: var(--sp-sm);
  margin-bottom: var(--sp-lg);
  border-bottom: 1px solid var(--chalk-line);
}

/* A tally. It counts the sections; it is not one of the words, so it stays
   below the eyebrow beside it.

   It used to take amber-dim, on the reasoning that a tally is hardware. But
   amber-dim is the colour of a segment that is switched off, and this number
   is switched on: it is real text, on every section of every page, at 2.67:1.
   Amber-text is 7.13:1 on the ground and still three and a half stops under
   the eyebrow's 10.60, so the hierarchy that amber-dim was chosen for survives
   at a ratio someone can actually read. */
.section-head__no {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--amber-text);
  flex: none;
}

/* The loud element in the row, and the only one that is the section's name. */
.section-head__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--amber);
}

/* A sentence, so it is set as one. It stays in the instrument register by
   staying mono and sage, but tracked caps at this length were unreadable at
   any size we could have given them. */
.section-head__meta {
  padding-left: 14px;
  border-left: 1px solid var(--chalk-line);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  line-height: 1.35;
  color: var(--sage);
}

/* Once the meta drops to its own line the tick has nothing to divide. */
@media (max-width: 700px) {
  .section-head__meta {
    flex-basis: 100%;
    padding-left: 0;
    border-left: 0;
  }
}

.stack { display: grid; gap: var(--sp-lg); }
.stack--sm { display: grid; gap: var(--sp-md); }

.grid { display: grid; gap: var(--sp-md); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-xl);
  align-items: center;
}

/* ------------------------------------------------------------ controls --- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-decoration: none;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--dur-state) var(--ease-standard),
              color var(--dur-state) var(--ease-standard),
              border-color var(--dur-state) var(--ease-standard);
}

.btn--primary {
  background: var(--orange);
  color: var(--on-orange);
  padding: 16px 30px;
}
.btn--primary:hover { background: var(--amber); }
/* Only the ground moves when pressed. The label used to switch to a lighter
   cream here, which was an undocumented colour and 4.21:1 against the
   pressed ground. DESIGN.md puts near-black on any orange fill, and On
   Orange is already what the button carries at rest. */
.btn--primary:active { background: var(--orange-deep); }

.btn--ghost {
  background: transparent;
  color: var(--cream);
  border: 1px solid var(--chalk-line);
  padding: 15px 29px;
}
.btn--ghost:hover { background: var(--pitch-raised-high); color: var(--amber); border-color: var(--amber); }

.btn--sm { padding: 11px 18px; }

/* An onward link. Sections in this world used to simply stop, which is how
   partners.html ended up reachable from the footer and nowhere else. Not a
   button: a button is the thing you came here to do, and this is the next
   room. Amber informs, orange marks, so it sits in amber until you point at
   it. The rule lengthens on hover the way a beam widens. */
.onward {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--amber-text);
  transition: color var(--dur-state) var(--ease-standard);
}
/* Scaled, not widened. Animating width on hover relayouts the flex row every
   frame; a transform runs on the compositor and the row never moves. */
.onward::after {
  content: "";
  width: 44px;
  height: 1px;
  flex: none;
  background: currentColor;
  transform: scaleX(0.64);
  transform-origin: left center;
  transition: transform var(--dur-state) var(--ease-standard);
}
/* The label is 13px, and orange never goes on text that small. The rule can
   take it: it is a graphic, not type. So the word brightens within amber and
   the orange arrives underneath it, which is the mark the hover needed. */
.onward:hover { color: var(--amber); }
.onward:hover::after { background: var(--orange); transform: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--pitch-raised-high);
  color: var(--sage);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding: 7px 14px;
  border: 0;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background var(--dur-state) var(--ease-standard),
              color var(--dur-state) var(--ease-standard),
              box-shadow var(--dur-state) var(--ease-standard);
}
.chip:hover:not(:disabled) { background: var(--chalk-line); color: var(--cream); }
.chip.is-on { background: var(--orange); color: var(--on-orange); box-shadow: var(--shadow-select); }
.chip:disabled { opacity: 0.4; cursor: not-allowed; }
.chip__soon { color: var(--amber-text); }
.chip.is-on .chip__soon { color: var(--on-orange); opacity: 0.6; }

/* Content is rounded. Equipment is square. */
.card {
  background: var(--pitch-raised);
  border: 1px solid var(--chalk-line);
  border-radius: var(--r-lg);
  padding: 24px;
  box-shadow: var(--shadow-chalk);
  transition: background var(--dur-state) var(--ease-standard),
              border-color var(--dur-state) var(--ease-standard);
}
.card:hover { background: var(--pitch-raised-high); border-color: var(--chalk-line-lit); }
.card__eyebrow { margin: 0 0 12px; color: var(--amber); }
.card__title { margin: 0 0 10px; }
.card__body { margin: 0; color: var(--sage); }

.field__label { display: block; margin-bottom: 8px; color: var(--sage); }
.field__input {
  width: 100%;
  background: var(--pitch-raised-high);
  color: var(--cream);
  border: 1px solid var(--chalk-line);
  border-radius: var(--r-md);
  padding: 13px 14px;
  transition: border-color var(--dur-state) var(--ease-standard),
              box-shadow var(--dur-state) var(--ease-standard);
}
.field__input::placeholder { color: var(--sage); opacity: 0.7; }
.field__input:focus { outline: 0; border-color: var(--orange); box-shadow: var(--shadow-focus); }

/* A genuine live indicator. Never decorative, never twice on one screen.
   Currently unused and that is correct: the hero board runs a simulated
   fixture and says so, so nothing on the marketing pages is actually live.
   Held here for the day a real feed is on screen. Do not spend it on a demo. */
.livedot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--live-red);
  flex: none;
  animation: livepulse 2s var(--ease-standard) infinite;
}
@keyframes livepulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ---------------------------------------------------------------- nav ---- */

.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  height: var(--nav-h);
  background: rgba(4, 26, 9, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--chalk-line);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 28px;
  height: 100%;
}

.nav__brand {
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--cream);
  margin-right: auto;
}
.nav__brand span { color: var(--orange); }

.nav__links { display: flex; align-items: center; gap: 28px; height: 100%; }

.nav__link {
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--sage);
  transition: color var(--dur-state) var(--ease-standard);
}
.nav__link:hover, .nav__link.is-active { color: var(--cream); }
.nav__link.is-active::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 2px;
  background: var(--orange);
}

.nav__cta { flex: none; }

/* The same call, living at the foot of the mobile drawer. The bar CTA has to
   go below 900px because the burger takes its place, and without this the
   phone had no way to act on anything it had just read. Hidden with display
   above 900px so it never becomes a second tab stop on the desktop bar. */
.nav__drawercta { display: none; }

.nav__burger {
  display: none;
  /* The only control in the bar on a phone, so it takes the full 44. */
  width: 44px; height: 44px;
  background: transparent;
  border: 1px solid var(--chalk-line);
  border-radius: var(--r-sm);
  cursor: pointer;
  padding: 0;
  place-items: center;
}
.nav__burger span {
  display: block;
  width: 18px; height: 1.5px;
  background: var(--cream);
  transition: transform var(--dur-state) var(--ease-standard),
              opacity var(--dur-state) var(--ease-standard);
}
.nav__burger span + span { margin-top: 4px; }
.nav.is-open .nav__burger span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav.is-open .nav__burger span:nth-child(2) { opacity: 0; }
.nav.is-open .nav__burger span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

@media (max-width: 900px) {
  .nav__burger { display: grid; }
  .nav__cta { display: none; }
  .nav__inner { gap: 14px; }
  .nav__links {
    position: fixed;
    inset: var(--nav-h) 0 auto;
    height: calc(100dvh - var(--nav-h));
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 4px;
    padding: 0 var(--gutter);
    background: var(--pitch-deep);
    border-top: 1px solid var(--chalk-line);
    transform: translateX(100%);
    /* Off-canvas is not hidden. With transform alone the six links and the CTA
       stayed in the tab order at every width below 900px, so a keyboard user
       on a phone tabbed through a menu that was not on screen. Visibility
       takes them out, and switching it at the end of the slide out and the
       start of the slide in keeps the animation the transform was there for. */
    visibility: hidden;
    transition: transform 280ms var(--ease-arrive),
                visibility 0s linear 280ms;
    overflow-y: auto;
  }
  .nav.is-open .nav__links {
    transform: none;
    visibility: visible;
    transition: transform 280ms var(--ease-arrive), visibility 0s;
  }
  .nav__link {
    height: auto;
    padding: 16px 0;
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-weight: 500;
    letter-spacing: 0.03em;
  }
  .nav__link.is-active::after { inset: auto auto 10px 0; width: 42px; right: auto; }
  .nav__drawercta {
    display: inline-flex;
    align-self: stretch;
    margin-top: var(--sp-md);
  }
}

/* ---------------------------------------------------------- clip facade -- */
/* Used by clip.js. Nothing here loads until the visitor asks for it. */

.clip__poster, .clip__teaser {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.clip__teaser { opacity: 0; transition: opacity 520ms var(--ease-standard); }
.clip__teaser.is-in { opacity: 1; }

body.clip-open { overflow: hidden; }

.lb {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: none;
  place-items: center;
  padding: clamp(16px, 4vw, 56px);
  background: rgba(4, 26, 9, 0.94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.lb.is-open { display: grid; }

.lb__frame {
  width: 100%;
  max-width: 1400px;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--chalk-line);
  border-radius: var(--r-stage);
  overflow: hidden;
  background: var(--pitch-deep);
  box-shadow: var(--shadow-spill);
}
.lb__frame iframe, .lb__frame video { width: 100%; height: 100%; border: 0; display: block; }

.lb__close {
  position: absolute;
  top: clamp(12px, 2vw, 24px);
  right: clamp(12px, 2vw, 24px);
  background: var(--pitch-raised-high);
  color: var(--cream);
  border: 1px solid var(--chalk-line);
  border-radius: var(--r-sm);
  padding: 10px 16px;
  cursor: pointer;
  transition: background var(--dur-state) var(--ease-standard), color var(--dur-state) var(--ease-standard);
}
.lb__close:hover { background: var(--orange); color: var(--on-orange); border-color: var(--orange); }

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

/* One definition, shared by every sub-page. A flat band is allowed here, and
   only here, because it is a page header with a rule on its bottom edge that
   explains where it stops. Sections in the body do not get their own tone. */
.page-hero {
  background: var(--pitch-deep);
  border-bottom: 1px solid var(--chalk-line);
  padding-block: clamp(48px, 6vw, 84px) clamp(32px, 4vw, 52px);
}
/* The page's own name, so it is sized like a section name rather than like a
   caption. Wins over .label on order, both being one class. */
.page-hero__eyebrow {
  display: block;
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  color: var(--amber);
  margin-bottom: var(--sp-md);
}
.page-hero__title { max-width: 18ch; margin-bottom: var(--sp-md); }
.page-hero .lede { max-width: 62ch; }

/* ------------------------------------------------------------- reveal ---- */
/* Motion is a match unfolding. Content arrives once and stays. */

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-arrive) var(--ease-arrive),
              transform var(--dur-arrive) var(--ease-arrive);
}
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--orange);
  color: var(--on-orange);
  padding: 12px 18px;
  border-radius: 0 0 var(--r-sm) 0;
}
.skip-link:focus { left: 0; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
