/* Flow AI texture layer.

   The ground the type sits on, in the same language as the card kit and the
   Profound reference the site already borrows its rails from: a lit ground
   (soft light behind the focal object), a quiet dot sheet, frosted glass
   panels, pill tags, and the canvas dot field from /assets/dotfield.js.

   Loaded after site.css by pages that opt in. Every rule is additive and
   decorative: nothing here changes a text colour, so the accessibility
   baseline holds; nothing here hides content, so a blocked stylesheet or
   script leaves the plain page. Amber keeps its one job (the button). */

/* ---- Hosts: the section becomes a stage for a ground layer ------------- */
[data-dotfield], .lit, .sheet {
  position: relative;
  isolation: isolate;
  overflow: clip;
}
@supports not (overflow: clip) {
  [data-dotfield], .lit, .sheet { overflow: hidden; }
}
[data-dotfield] > .wrap, .lit > .wrap, .sheet > .wrap {
  position: relative;
  z-index: 1;
}

/* ---- Dot field: the canvas fills its section ---------------------------- */
.dotfield {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---- Glass panel: the double-bezel card from the kit, as a live surface.
   A hairline, a whisper of fill, a highlight along the top edge, and a light
   that brightens under the cursor. Frosted so the dot sheet blurs behind it. */
/* A framed panel is a hairline frame now, nothing more: no fill, no
   blur, no highlight. The grid between panels is a hairline too. */
.glass {
  position: relative;
  padding: var(--s-6);
  border: 1px solid var(--hair);
  border-radius: 0;
  transition: border-color 220ms ease, transform 240ms var(--ease);
}
.glass > *, .glass::before { position: relative; z-index: 1; }
.glass:hover { border-color: var(--hair-strong); }
.glass-grid { gap: 0; }
.glass-grid > .glass + .glass { margin-left: -1px; }
@media (max-width: 720px) { .glass-grid > .glass + .glass { margin-left: 0; margin-top: -1px; } }

/* ---- Tag: the eyebrow, in the mono annotation layer, no pill --------- */
.tag, .eyebrow.tag { display: inline; padding: 0; border: 0; background: none; border-radius: 0; min-height: 0; }
.tag::before { content: none; }
.tag-sm { font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--soft); }
.part > .tag { display: block; margin-bottom: var(--s-4); }

/* ---- Scroll-fill: type lights up in reading order.
   Each block brightens from its first line down to its last as it scrolls
   up into the reading zone, so a heading lights before its lead and a
   paragraph before the one beneath it. Nobody reads a paragraph left to
   right in one sweep; they read it top to bottom, and the light follows.
   Gated to browsers with scroll-driven animations and to visitors who
   allow motion; everyone else reads the settled colour. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .fill-on-scroll:not([data-words="ready"]), .fill-prose > p:not(.small) {
      background: linear-gradient(to bottom, var(--fill-to, var(--fg)) 46%, var(--fill-from, rgba(250, 248, 243, 0.28)) 54%) 0 100% / 100% 200% no-repeat;
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
      animation: texture-scrollfill linear both;
      animation-timeline: view();
      animation-range: entry 30% cover 45%;
    }
    @keyframes texture-scrollfill { to { background-position: 0 0; } }
  }
}

/* ---- Life: entrance, light and touch ------------------------------------
   The ground above is what the page sits on. This is what moves.
   Everything here is gated to visitors who allow motion. Entrance states
   apply only once alive.js has flagged the document (html.js), so a
   blocked script shows the page at rest, never hidden. */

@media (prefers-reduced-motion: no-preference) {
  /* Headlines arrive line by line, top to bottom: every word on a line
     shares one index, so a line rises as a unit and the next follows.
     The hero does it on load; section headings do it as they scroll in
     (held paused while their reveal block is still hidden). The lead and
     the buttons follow, the portrait settles into place. */
  .js [data-words] .w {
    display: inline-block; overflow: hidden; vertical-align: top;
    padding-bottom: 0.12em; margin-bottom: -0.12em;
  }
  .js [data-words] .w > span {
    display: inline-block; transform: translateY(112%);
    animation: texture-rise 880ms var(--ease) forwards;
    animation-delay: calc(var(--i, 0) * 130ms + 60ms);
  }
  .js .is-hidden [data-words] .w > span { animation-play-state: paused; }
  /* until alive.js has split the words, hold the heading back; if the
     script never arrives, show it anyway after a beat */
  .js [data-words]:not([data-words="ready"]) { opacity: 0; animation: texture-fadein 300ms ease 2.4s forwards; }
  @keyframes texture-rise { to { transform: translateY(0); } }

  .js .hero .eyebrow, .js .hero .lead, .js .hero .cta-row, .js .hero .facts, .js .hero figcaption {
    opacity: 0; transform: translateY(14px);
    animation: texture-arrive 800ms var(--ease) forwards;
  }
  .js .hero .eyebrow { animation-delay: 40ms; }
  .js .hero .lead { animation-delay: 480ms; }
  .js .hero .cta-row { animation-delay: 620ms; }
  .js .hero figcaption { animation-delay: 900ms; }
  .js .hero .facts { animation-delay: 760ms; }
  .js .hero .hero-art { opacity: 0; scale: 0.985; animation: texture-settle 1100ms var(--ease) 380ms forwards; }
  .js .hero .dotfield { opacity: 0; animation: texture-fadein 1600ms ease 520ms forwards; }
  .js .hero .system__agents, .js .hero .system__arcs { opacity: 0; animation: texture-arrive 900ms var(--ease) 1200ms forwards; }
  @keyframes texture-arrive { to { opacity: 1; transform: none; } }
  @keyframes texture-settle { to { opacity: 1; scale: 1; } }
  @keyframes texture-fadein { to { opacity: 1; } }

}


/* ---- Ticker: a slow, continuous line of proof under the hero ------------
   alive.js builds the loop from one list, so the text exists once for
   readers and crawlers; the copies are hidden from assistive tech. */
.ticker {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
}
.ticker__inner { display: flex; width: max-content; }
.ticker__group { display: flex; flex: none; }
.ticker .hero-proof {
  flex: none; flex-wrap: nowrap; justify-content: flex-start;
  margin: 0; padding-inline: calc(var(--s-6) / 2);
}
.ticker .hero-proof li { white-space: nowrap; }
.ticker .hero-proof li:first-child::before {
  content: ""; position: absolute; left: calc(var(--s-6) / -2); top: 50%;
  width: 3px; height: 3px; border-radius: 50%; background: var(--hair-strong); transform: translateY(-50%);
}
@media (prefers-reduced-motion: no-preference) {
  .ticker__inner { animation: texture-ticker var(--ticker-duration, 48s) linear infinite; }
  .ticker:hover .ticker__inner { animation-play-state: paused; }
  @keyframes texture-ticker { to { transform: translateX(-50%); } }
}

/* ---- Scroll-fill on a split headline ------------------------------------
   A heading that has been split into words for the entrance carries its
   text inside inline-block spans, which a text-clip on the heading cannot
   see. So the fill moves onto each word: every word on a line sits at the
   same height and so lights at the same moment, the next line follows, and
   the rise and the fill run together on the same span. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .js .fill-on-scroll[data-words="ready"] .w > span {
      background: linear-gradient(to bottom, var(--fill-to, var(--fg)) 46%, var(--fill-from, rgba(250, 248, 243, 0.28)) 54%) 0 100% / 100% 200% no-repeat;
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
      animation: texture-rise 880ms var(--ease) forwards, texture-scrollfill linear both;
      animation-delay: calc(var(--i, 0) * 130ms + 60ms), 0s;
      animation-timeline: auto, view();
      animation-range: normal, entry 30% cover 45%;
    }
  }
}

/* ---- The system: the agent team as one object ----------------------------
   A master agent at the centre, the three outcomes as arcs around it, the
   specialist agents on the outer ring, and the review pass on the rim.
   dotfield.js draws the geometry and places these labels on it; hovering
   or focusing an agent lights its path from the centre and opens its
   reason. Below 720px the labels become a list under the object, every
   reason open, since there is no hover to find them with. */
.system { position: relative; width: min(100%, 70rem); margin: var(--space-band) auto 0; }
.system__stage { position: relative; width: 100%; aspect-ratio: 1.55 / 1; max-height: 46rem; }
.system__arcs, .system__agents { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; pointer-events: none; }
.system__arcs li {
  position: absolute; transform: translate(-50%, -50%);
  padding: 3px 10px; background: var(--bg);
  color: var(--soft); font-family: var(--mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; white-space: nowrap;
}

.system__agents li {
  position: absolute; max-width: 16rem; padding: 9px 13px; margin: -9px -13px;
  border-radius: var(--radius); pointer-events: auto; cursor: pointer; outline: none;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}
/* The card: the title never moves. On hover a surface opens around it
   and unfolds downward, and the description slides in underneath, so the
   label expands in place and never swaps for something else. */
.system__agents li { --card-w: 15.5rem; --drop: 0px; transition: opacity 360ms ease; }
.system__agents li::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 100%; z-index: -1; pointer-events: none;
  border-radius: inherit; border: 1px solid var(--hair);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.03) inset, 0 22px 44px -20px rgba(0, 0, 0, 0.75);
  opacity: 0;
  transition: opacity 260ms ease, bottom 560ms var(--ease-out), width 560ms var(--ease-out);
}
.system__agents li.is-left::before { left: auto; right: 0; }
.system__agents li.is-top::before, .system__agents li.is-bottom::before, .system__agents li.is-core::before { left: 50%; translate: -50% 0; }
.system__agents li.is-active::before { opacity: 1; bottom: calc(-1 * var(--drop)); width: max(100%, var(--card-w)); }
.system__agents li .small { display: none; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; }
.system__agents li b { transition: color 320ms ease; display: inline-flex; align-items: center; gap: 0.5em; color: var(--fg); font-size: var(--t-label); font-weight: 500; white-space: nowrap; }
.system__agents li p {
  position: absolute; top: 100%; left: 13px; width: calc(var(--card-w) - 26px); margin: 0; padding-top: 2px;
  color: var(--muted); font-size: var(--t-small); line-height: 1.45; white-space: normal; text-wrap: pretty; text-align: left;
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(-8px);
  transition: opacity 220ms ease, transform 420ms var(--ease-out), visibility 0s linear 420ms;
}
.system__agents li.is-left p { left: auto; right: 13px; text-align: right; }
.system__agents li.is-top p, .system__agents li.is-bottom p, .system__agents li.is-core p { left: 50%; translate: -50% 0; text-align: center; }
.system__agents li.is-active p {
  opacity: 1; visibility: visible; pointer-events: auto; transform: none;
  transition: opacity 380ms ease 140ms, transform 560ms var(--ease-out) 100ms, visibility 0s;
}
.system__agents li.is-left b { flex-direction: row-reverse; }
.system__agents li.is-core b { justify-content: center; }
.agent-ico { width: 15px; height: 15px; flex: none; color: var(--soft); transition: color 320ms ease, transform 520ms var(--ease-out, ease); }
.system__agents li.is-active .agent-ico, .system__agents li:hover .agent-ico { color: var(--fg); }
.system__agents li.is-core .agent-ico { width: 18px; height: 18px; color: var(--accent); }
.system__agents li.is-active, .system__agents li:focus-visible { z-index: 2; }
.system__agents li:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Focus: while one agent is open, everything else steps back */
.system.has-active .system__agents li:not(.is-active):not(.is-core) { opacity: 0.2; }
.system.has-active.core-active .system__agents li:not(.is-active):not(.is-core) { opacity: 0.55; }
.system__agents li.is-core > b, .system__agents li.is-core > .small { transition: opacity 360ms ease; }
.system.has-active .system__agents li.is-core:not(.is-active) > b, .system.has-active .system__agents li.is-core:not(.is-active) > .small { opacity: 0.4; }
.system__arcs li { transition: opacity 360ms ease; }
.system__arcs li.is-quiet { opacity: 0.18; }
@media (prefers-reduced-motion: reduce) {
  .system__agents li::before, .system__agents li p, .agent-ico { transition: opacity 200ms ease, visibility 0s; transform: none !important; }
}
.system__agents li.is-top { transform: translate(-50%, -100%) translateY(-24px); text-align: center; }
.system__agents li.is-bottom { transform: translate(-50%, 0) translateY(24px); text-align: center; }
.system__agents li.is-right { transform: translate(0, -50%) translateX(26px); text-align: left; }
.system__agents li.is-left { transform: translate(-100%, -50%) translateX(-26px); text-align: right; }
.system__agents li.is-core {
  transform: translate(-50%, -50%); max-width: 17rem; padding: 18px 26px; margin: 0; text-align: center;
  background: radial-gradient(closest-side, rgba(14, 14, 13, 0.96) 55%, rgba(14, 14, 13, 0));
}
.system__agents li.is-core b { font-size: var(--lead); font-weight: 560; letter-spacing: -0.02em; }
.system__agents li.is-core .small { display: block; margin-top: 4px; color: var(--soft); font-family: var(--mono); letter-spacing: 0.12em; }
.system__agents li.is-core { border-radius: calc(var(--radius) + 8px); --card-w: 19rem; }
.system__agents li.is-core p { width: calc(var(--card-w) - 52px); }
/* Agent numbers and section counts, in the annotation layer */
.agent-num { font-family: var(--mono); font-size: 10px; font-style: normal; font-weight: 400; letter-spacing: 0.08em; color: var(--soft); opacity: 0.75; }
.system__arcs li[data-count]::after { content: " \00b7  " attr(data-count); color: var(--soft); opacity: 0.7; }
/* The build: while the figure assembles, each label waits for its node */
.js .hero .system.is-staged .system__agents, .js .hero .system.is-staged .system__arcs, .js .hero .system.is-staged .dotfield { animation: none; opacity: 1; }
.system.is-staged .system__agents li, .system.is-staged .system__arcs li {
  transition: opacity 640ms cubic-bezier(0.22, 1, 0.36, 1), translate 760ms cubic-bezier(0.22, 1, 0.36, 1), filter 640ms ease;
}
@media (min-width: 721px) {
  .system.is-staged .system__agents li:not(.is-in), .system.is-staged .system__arcs li:not(.is-in) { opacity: 0; translate: 0 6px; filter: blur(3px); }
}
.system__agents li.is-core::before { background: rgba(14, 14, 13, 0.94); }
.system__agents li.is-core.is-active .agent-ico { transform: rotate(90deg); }
@media (max-width: 720px) {
  .system__stage { aspect-ratio: 1 / 1; max-height: 24rem; }
  .system__arcs, .system__hint { display: none; }
  .system__agents { position: static; display: grid; gap: var(--s-3); margin-top: var(--s-6); text-align: left; }
  .system__agents li, .system__agents li.is-top, .system__agents li.is-bottom, .system__agents li.is-right, .system__agents li.is-left {
    position: static; transform: none; max-width: none; margin: 0; padding: var(--s-4) 0; border: 0; border-top: 1px solid var(--hair); border-radius: 0; text-align: left;
  }
  .system__agents li.is-left b { flex-direction: row; }
  .system__agents li .small, .system__agents li p { display: block; }
  .system__agents li.is-core { position: absolute; transform: translate(-50%, -50%); max-width: 12rem; padding: 12px 16px; }
  .system__agents li.is-core p { display: none; }
  .system__agents li:not(.is-core)::before { display: none; }
  .system__agents li:not(.is-core) p { position: static; width: auto; margin-top: var(--s-2); padding: 0; opacity: 1; visibility: visible; pointer-events: auto; transform: none; translate: none; text-align: left; }
  .system.has-active .system__agents li:not(.is-active) { opacity: 1; }
}
