/* ============================================================================
   site.css: shared chrome + the service-page layout.

   Class names describe the design, not the tool that used to generate it. The
   only Webflow-era names kept are the four behaviour hooks the ported scripts
   query: .tsv-page (theme root), .toai-rv (reveal target), .toai-w-vid (lazy
   video gate), .toai-form-root (Formspree AJAX root).

   Mobile first. The single breakpoint is 768px, matching the baseline.
   ========================================================================== */

/* --------------------------------------------------------------- 1. reset */

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

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--void);
  color: var(--bright);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 20px;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}

img,
video,
canvas {
  max-width: 100%;
  vertical-align: middle;
}

figure {
  margin: 0 0 10px;
}

figcaption {
  text-align: center;
  margin-top: 5px;
}

p {
  margin: 0 0 10px;
}

ul,
ol {
  margin: 0 0 10px;
  padding-left: 40px;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

td,
th {
  padding: 0;
}

b,
strong {
  font-weight: 700;
}

a {
  background-color: transparent;
}

[hidden] {
  display: none !important;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0 0 10px;
  color: var(--white);
  font-weight: 700;
  line-height: 1em;
  text-transform: uppercase;
}

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

/* --------------------------------------------------- 2. page theme + shell */

.tsv-page {
  background: var(--void);
  color: var(--white);
  font-family: var(--font-body);
}

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

/* ------------------------------------------------------------- 3. top bar */

.topbar {
  background: var(--void);
  border-bottom: 1px solid var(--rule);
}

.topbar-in {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 18px var(--gutter);
}

.topbar-brand {
  color: var(--cyan);
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: var(--ls-brand);
  text-decoration: none;
}

.topbar-link {
  color: var(--label);
  font-family: var(--font-ui);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-tight);
  text-decoration: none;
}

.topbar-link:hover {
  color: var(--cyan);
}

/* --------------------------------------------------------- 4. section grid */

.svc-hero {
  border-bottom: 1px solid var(--rule);
  padding-top: var(--s-12);
  padding-bottom: var(--s-11);
}

.svc-section {
  position: relative;
  z-index: 5;
  background: var(--void);
  padding-top: var(--s-10);
  padding-bottom: var(--s-10);
}

.svc-section--panel {
  background: var(--panel);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

/* ------------------------------------------------------------ 5. type bits */

.eyebrow {
  margin-bottom: var(--s-4);
  color: var(--label);
  font-family: var(--font-ui);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-label);
}

.eyebrow--cyan {
  color: var(--cyan);
}

.eyebrow--magenta {
  color: var(--magenta);
}

.svc-h1 {
  margin: 0 0 var(--s-5);
  color: var(--white);
  font-family: var(--font-ui);
  font-size: var(--fs-h1);
  font-weight: 700;
  line-height: var(--lh-tight);
}

.svc-h2 {
  margin: 0 0 18px;
  color: var(--white);
  font-family: var(--font-ui);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: var(--lh-head);
}

.svc-h3 {
  margin: var(--s-7) 0 var(--s-2);
  color: var(--cyan);
  font-family: var(--font-ui);
  font-size: var(--fs-h3);
  font-weight: 600;
}

.lede {
  max-width: var(--measure);
  margin: 0 0 var(--s-7);
  color: var(--bright);
  font-size: var(--fs-lede);
  line-height: var(--lh-lede);
}

.prose {
  max-width: var(--measure);
  margin: 0 0 10px;
  color: var(--bright);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.microline {
  color: var(--label);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-tight);
}

.fineprint {
  color: var(--label);
  font-size: var(--fs-meta);
}

.bullets,
.steps {
  max-width: 780px;
  margin: 0 0 10px;
  color: var(--bright);
  font-size: var(--fs-body);
  line-height: var(--lh-list);
}

.bullets {
  padding-left: var(--s-5);
}

.steps {
  padding-left: 22px;
}

.pullquote {
  max-width: var(--measure-wide);
  margin: 0;
  padding: 26px 30px;
  background: var(--panel);
  border-left: 3px solid var(--cyan);
  color: var(--white);
  font-size: 15.5px;
  line-height: var(--lh-list);
}

/* --------------------------------------------------------------- 6. links */

.textlink {
  color: var(--cyan);
  font-family: var(--font-ui);
  font-size: var(--fs-body-sm);
  letter-spacing: var(--ls-tight);
  text-decoration: none;
}

.textlink:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.inlink {
  color: var(--cyan);
  text-decoration: none;
}

.inlink:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.inlink--underline {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ------------------------------------------------------------- 7. buttons */

.btn {
  display: inline-block;
  margin: 0 14px 10px 0;
  padding: 14px 26px;
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-size: var(--fs-body-sm);
  letter-spacing: var(--ls-tight);
  text-decoration: none;
}

.btn--solid {
  background: var(--cyan);
  color: var(--void);
  font-weight: 700;
}

.btn--solid:hover {
  background: var(--white);
}

.btn--ghost {
  border: 1px solid var(--cyan);
  color: var(--cyan);
}

.btn--ghost:hover {
  background: rgba(35, 186, 231, 0.12);
}

.cta-row {
  margin-bottom: 14px;
}

/* ------------------------------------------------------- 8. tier card grid */

.svc-grid {
  display: flex;
  gap: var(--s-5);
  margin-bottom: 18px;
}

.tier {
  flex: 1;
  padding: var(--s-7) var(--s-6);
  background: var(--void);
  border: 1px solid var(--rule);
}

.tier--feature {
  border-color: var(--cyan);
}

.tier-name {
  margin-bottom: 10px;
  color: var(--label);
  font-family: var(--font-ui);
  font-size: var(--fs-fine);
  letter-spacing: var(--ls-wide);
}

.tier-price {
  margin-bottom: var(--s-3);
  color: var(--cyan);
  font-family: var(--font-ui);
  font-size: var(--fs-price);
  font-weight: 700;
  /*
   * The live site inherited 20px of leading on 30px type here, so two-line
   * titles ("THE FOUNDATION", "THE ONGOING PARTNERSHIP") drew on top of
   * themselves. Amir, 2026-09-23, asked whether to keep it: "fix it".
   * QUIRKS row 1.
   */
  line-height: 1.08;
}

.tier-body {
  margin: 0;
  color: var(--bright);
  font-size: var(--fs-card);
  line-height: 1.65;
}

/* --------------------------------------------------------- 9. work proof */

.work {
  margin-top: var(--s-7);
}

.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--s-5);
}

/* This page runs six tiles: two-up from 380px of column width. */
.work-grid--wide {
  /* min(): below 428px of viewport the 380px floor was wider than the
     column and clipped the tiles and captions on the right. */
  grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr));
}

.work-tile {
  margin: 0;
}

.work-shot {
  display: block;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--rule);
  line-height: 0;
}

.work-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: center;
}

.work-cap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-1);
  margin-top: 10px;
}

.work-name {
  color: var(--white);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.work-meta {
  color: var(--label);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

.work-film {
  margin: var(--s-6) 0 0;
}

.work-video {
  display: block;
  width: 100%;
  height: auto;
  background: var(--panel);
  border: 1px solid var(--rule);
}

.scores {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-4);
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}

.score {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-left: 14px;
  border-left: 2px solid var(--cyan);
}

.score-num {
  color: var(--white);
  font-size: var(--fs-stat);
  font-weight: 700;
  line-height: 1.1;
}

.score-label {
  color: var(--label);
  font-size: var(--fs-fine);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.work-note {
  margin: var(--s-3) 0 0;
  color: var(--label);
  font-size: var(--fs-fine);
  line-height: 1.6;
}

/* ---------------------------------------------------- 10. inline FAQ block */

.faq-inline {
  max-width: 780px;
}

/* ------------------------------------------------- 11. AEO overview block */

.aeo,
.faq {
  background: transparent;
}

.aeo-inner,
.faq-inner {
  max-width: var(--wrap-narrow);
  margin: 0 auto;
  padding: 48px var(--s-5);
  color: #fff;
  font-family: var(--font-ui), var(--font-body);
}

.block-tag {
  margin-bottom: 10px;
  color: var(--cyan-hot);
  font-size: var(--fs-fine);
  letter-spacing: var(--ls-label);
}

.aeo-h,
.faq-h {
  margin: 0 0 14px;
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: var(--lh-head);
}

.faq-h {
  margin-bottom: 26px;
}

.aeo-lede {
  max-width: var(--measure);
  margin: 0 0 30px;
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--fs-body);
  line-height: 1.6;
}

.aeo-sub {
  margin: 0 0 14px;
  color: var(--cyan-hot);
  font-size: var(--fs-body);
  font-weight: 700;
  letter-spacing: var(--ls-tight);
}

.cmp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-meta);
}

/* ------------------------------------------------------ 12. accordion FAQ */

.faq-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.faq-item {
  overflow: hidden;
  background: var(--wash-white);
  border: 1px solid var(--hairline-cyan);
  border-radius: var(--radius-lg);
}

.faq-q {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: var(--s-4) 18px;
  font-size: var(--fs-body);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
  transition: background 0.2s;
}

.faq-q::-webkit-details-marker {
  display: none;
}

.faq-q:hover {
  background: rgba(255, 255, 255, 0.04);
}

.faq-a {
  padding: 0 18px 18px;
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--fs-body-sm);
  line-height: 1.6;
}

/* ------------------------------------------- 12b. contact form AJAX states */

.form-success {
  padding: 34px 28px;
  color: var(--cyan-hot);
  font-family: var(--font-ui);
  text-align: center;
}

.form-success-mark {
  margin-bottom: var(--s-3);
  font-size: 40px;
}

.form-success-head {
  margin-bottom: 10px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: var(--ls-wide);
}

.form-success-body {
  color: var(--text-softer);
  font-size: var(--fs-meta);
  line-height: 1.6;
}

.form-success-body a {
  color: var(--cyan-hot);
  text-decoration: none;
}

.form-error {
  margin: 0 0 14px;
  padding: 10px 14px;
  background: rgba(255, 92, 108, 0.08);
  border: 1px solid rgba(255, 92, 108, 0.5);
  color: #ff8a94;
  font-family: var(--font-ui);
  font-size: var(--fs-fine);
  line-height: 1.5;
}

/* -------------------------------------------------------- 13. link band */

.linkband {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4) var(--s-7);
}

.linkband-item {
  color: var(--cyan);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  letter-spacing: var(--ls-tight);
  text-decoration: none;
}

.linkband-item:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ----------------------------------------------------------- 14. footer */

.site-footer {
  border-top: 1px solid var(--rule);
  padding-top: var(--s-8);
  padding-bottom: var(--s-9);
}

.footer-nap {
  margin-bottom: 6px;
  color: var(--white);
  font-family: var(--font-ui);
  font-size: var(--fs-body-sm);
  letter-spacing: var(--ls-tight);
}

.footer-area {
  margin-bottom: 6px;
  color: var(--label);
  font-size: var(--fs-meta);
}

.footer-meta {
  margin: 0;
  color: var(--label);
  font-size: var(--fs-fine);
}

/* --------------------------------------------- 15. Instagram mark and fab */

.ig-mark {
  position: relative;
  display: inline-block;
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  border: 1.5px solid currentColor;
  border-radius: 30%;
  vertical-align: -0.14em;
}

.ig-mark::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46%;
  height: 46%;
  transform: translate(-50%, -50%);
  border: 1.5px solid currentColor;
  border-radius: 50%;
}

.ig-mark::after {
  content: "";
  position: absolute;
  right: 12%;
  top: 10%;
  width: 15%;
  height: 15%;
  background: currentColor;
  border-radius: 50%;
}

.ig-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: inherit;
  text-decoration: none;
}

.ig-link:hover {
  color: var(--cyan-hot);
}

.ig-fab {
  position: fixed;
  right: 18px;
  bottom: 64px;
  z-index: 2147482500;
  justify-content: center;
  width: 38px;
  height: 38px;
  font-size: 17px;
  color: var(--cyan-hot);
  background: var(--overlay-ink);
  border: 1px solid rgba(0, 245, 255, 0.55);
  border-radius: 50%;
}

/* ------------------------------------- 16. landscape-phone home affordance */

.landscape-home {
  display: none;
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 2147483000;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  color: var(--cyan-hot);
  background: rgba(5, 6, 11, 0.72);
  border: 1px solid rgba(0, 245, 255, 0.5);
  border-radius: var(--radius);
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: var(--ls-wide);
  text-decoration: none;
}

@media (orientation: landscape) and (max-height: 600px) {
  .landscape-home {
    display: inline-flex;
  }
}

/* ------------------------------------------------ 17. motion: reveal, fx */

/*
 * Cross-document view transitions. This lives in the stylesheet, not in JS:
 * both documents have to be opted in before the navigation starts, and a
 * rule injected on DOMContentLoaded is too late for the incoming page, which
 * aborted every transition with "ViewTransition opt-in disabled". A browser
 * that does not know @view-transition ignores the whole block, so the static
 * rule needs no feature detection, and navigates plainly.
 */
@view-transition {
  navigation: auto;
}

/*
 * The signature: the portal's flash. Amir, 2026-09-25, cinematic item 3: "a
 * signature page transition (the portal's flash / a ring closing)".
 *
 * The page you leave pushes in a little and brightens while the door's light
 * comes at it from the middle, as the homepage's camera goes through the door;
 * for a beat the screen is the door's flood, a white core going pink at its
 * edges (the colours are read off f_132, the flood frame: #fdfdfd core,
 * #fef2fe, #fc9ef3, #d971c2, #9e4e9e at the rim); and the new page opens out
 * of the light as an iris from the middle, a thin hot ring on its edge in the
 * door's own pink (home.js tints the thinning light 255 118 182), the way the
 * homepage's light lifts off the film from the middle outward. 700ms in all:
 *
 *   0 to 300ms     the old page scales to 1.05 and brightens to 1.35 while a
 *                  soft-edged hole opens in it from the middle (a mask, its
 *                  radius a registered property), so the flood under it takes
 *                  the screen from the centre out and is all there by 300ms.
 *                  A plain burn to white went through a flat grey; light
 *                  arriving does not.
 *   250 to 700ms   the new page: clip-path circle, 0 to 72 percent (72 of the
 *                  reference radius clears every corner at any aspect)
 *   throughout     the ring: drop shadows on the image pair. A shadow falls
 *                  only past an edge of what is drawn, and a full-screen page
 *                  has none on screen, so they show exactly on the light's
 *                  edge going out and on the iris's edge coming in.
 *
 * The flood is the root group's own background, under both pages, so it only
 * shows where neither page is. Animated: transform, filter, mask and
 * clip-path. Arriving at the homepage the iris opens on its dark boot gate
 * (#05060b): the door opening onto the dark.
 *
 * html[data-vt] is set by the head script while a transition runs: "page" for
 * this one, "match" for the match cut below.
 */
@property --vt-light {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

::view-transition-group(root) {
  background: radial-gradient(ellipse 71% 77% at 50% 50%, #fdfdfd 0%, #fdfdfd 52%, #fef2fe 63%, #fc9ef3 76%, #d971c2 89%, #9e4e9e 100%);
}

::view-transition-image-pair(root) {
  filter: drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 12px rgba(255, 118, 182, 0.9));
}

::view-transition-old(root) {
  animation: toaiVtLight 0.3s cubic-bezier(0.5, 0, 0.8, 0.4) both;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent calc(var(--vt-light) - 16%), #000 var(--vt-light));
  mask-image: radial-gradient(circle at 50% 50%, transparent calc(var(--vt-light) - 16%), #000 var(--vt-light));
  mix-blend-mode: normal;
}

::view-transition-new(root) {
  animation: toaiVtIris 0.45s cubic-bezier(0.3, 0, 0.12, 1) 0.25s both;
  mix-blend-mode: normal;
}

@keyframes toaiVtLight {
  from {
    --vt-light: 0%;
    transform: none;
    filter: none;
  }
  to {
    --vt-light: 118%;
    transform: scale(1.05);
    filter: brightness(1.35);
  }
}

@keyframes toaiVtIris {
  from {
    clip-path: circle(0% at 50% 50%);
  }
  to {
    clip-path: circle(72% at 50% 50%);
  }
}

@keyframes toaiVtOut {
  to {
    opacity: 0;
  }
}

@keyframes toaiVtIn {
  from {
    opacity: 0;
  }
}

/*
 * Only the root takes part in the signature: a named element would be drawn
 * over the flash as a box of its own (every service hero is named toai-hero
 * for the match cut). Set only while this transition runs, so a page's own
 * same-document transitions keep their names. [data-vt-keep] opts out.
 */
html[data-vt='page'] :not([data-vt-keep]) {
  view-transition-name: none !important;
}

/*
 * The match cut (the contract in CINEMATIC-PLAN): a card in the homepage film
 * cuts straight into its page. No flash: the two pages cross in 160ms and the
 * one element named toai-hero on each side carries the eye, the card growing
 * into the page's hero in 620ms. Both pictures fill the moving box, cropped
 * rather than stretched.
 */
html[data-vt='match']::view-transition-group(root) {
  background: none;
}

html[data-vt='match']::view-transition-image-pair(root) {
  filter: none;
}

html[data-vt='match']::view-transition-old(root) {
  animation: toaiVtOut 0.16s linear both;
  -webkit-mask-image: none;
  mask-image: none;
}

html[data-vt='match']::view-transition-new(root) {
  animation: toaiVtIn 0.16s linear both;
}

html[data-vt='match']::view-transition-group(toai-hero) {
  animation-duration: 0.62s;
  animation-timing-function: cubic-bezier(0.2, 0.7, 0, 1);
  overflow: clip;
}

html[data-vt='match']::view-transition-old(toai-hero),
html[data-vt='match']::view-transition-new(toai-hero) {
  height: 100%;
  object-fit: cover;
}

/* The hero's words (the heroes package names them toai-hero-copy during a
   match cut): their box travels with the picture's timing, and the words
   cross at their own size rather than being stretched to it. */
html[data-vt='match']::view-transition-group(toai-hero-copy) {
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.2, 0.7, 0, 1);
  overflow: clip;
}

html[data-vt='match']::view-transition-old(toai-hero-copy),
html[data-vt='match']::view-transition-new(toai-hero-copy) {
  width: auto;
  height: auto;
}

/*
 * The business card is kept exactly as it was (the plan leaves /aj-8qf3xa out
 * of every change): arriving there, the plain dissolve it always had.
 */
html:has(> body.card-page)::view-transition-group(root) {
  background: none;
}

html:has(> body.card-page)::view-transition-image-pair(root) {
  filter: none;
}

html:has(> body.card-page)::view-transition-old(root) {
  animation: toaiVtCardOut 0.34s cubic-bezier(0.4, 0, 1, 1) both;
  -webkit-mask-image: none;
  mask-image: none;
}

html:has(> body.card-page)::view-transition-new(root) {
  animation: toaiVtCardIn 0.46s cubic-bezier(0, 0, 0.2, 1) both;
}

@keyframes toaiVtCardOut {
  to {
    opacity: 0;
    transform: scale(1.025);
  }
}

@keyframes toaiVtCardIn {
  from {
    opacity: 0;
    transform: scale(1.012);
  }
}

/* Reduced motion: a 150ms crossfade of the whole page, no flash, no iris, no
   morph. (The card page kept its old rule, which switched transitions off.) */
@media (prefers-reduced-motion: reduce) {
  /* the group's own (identity) animation would hold the page until 250ms */
  html::view-transition-group(root) {
    background: none;
    animation-duration: 0.15s;
  }

  html::view-transition-image-pair(root) {
    filter: none;
  }

  html::view-transition-old(root) {
    animation: toaiVtOut 0.15s linear both;
    -webkit-mask-image: none;
    mask-image: none;
  }

  html::view-transition-new(root) {
    animation: toaiVtIn 0.15s linear both;
  }

  html[data-vt] * {
    view-transition-name: none !important;
  }

  html:has(> body.card-page)::view-transition-old(root),
  html:has(> body.card-page)::view-transition-new(root) {
    animation: none;
  }
}

.atmos {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0.75;
}

/* The business card's dot trail (site.js cardTrail, 5b). The ring below
   replaced it everywhere else; the card is kept as it was. */
.cursor-trail {
  position: fixed;
  z-index: 999999;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%);
  transition: opacity 0.3s ease;
  background-image: url(/assets/img/6a85eedbbdaa0f6ec0a14c0e_toai-trail-128.webp);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

/* Reveal targets are marked in the markup and un-hidden by site.js, so the
   page still reads fine with JavaScript off (see the no-js guard below). */
.js .toai-rv {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s cubic-bezier(0.2, 0.7, 0.2, 1),
    transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.js .toai-rv.toai-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .js .toai-rv {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/*
 * The headlines, line by line (site.js 2b). The head script adds rv-hold
 * before the first paint, only when site.js will split, and drops it by itself
 * after 600ms; site.js drops it the moment the lines are split and hidden. So
 * with JavaScript off, or late, the text simply shows.
 */
html.rv-hold :is(.tsv-page, .room-page) :is(h1, h2):not([data-reveal='none'], [data-reveal='none'] *),
html.rv-hold [data-reveal='lines'],
html.rv-hold [data-reveal='fade'] {
  opacity: 0;
}

/*
 * The hero headline rises on its own (Amir, 2026-09-25, top 5 item 1). It is
 * the largest paint on every service and case page, and the line reveal held
 * it back until site.js and the web fonts were in: at 4x CPU on a phone line
 * the page counted as loaded at about 2.0s. A CSS animation starts with the
 * first paint, so the same rise (as one block, on the lines' curve) now puts
 * it at about 0.5s, the same as no animation at all. It rises from a fifth of
 * its brightness, not from nothing: Chrome only counts a headline that starts
 * invisible partway through its fade (measured: 1.1s from 0, 0.45s from 0.2,
 * on the case pages). The two headlines carry
 * data-reveal="none" so neither the hold nor site.js touches them. Arriving
 * through a page transition it waits for the iris, as the lines did.
 */
@keyframes toai-hero-rise {
  from {
    opacity: 0.2;
    transform: translateY(0.35em);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.svc-hero .svc-h1,
.case-open .case-h1 {
  animation: toai-hero-rise 0.9s cubic-bezier(0.2, 0.7, 0, 1) both;
}

html[data-vt] .svc-hero .svc-h1,
html.hero-cut .svc-hero .svc-h1,
html[data-vt] .case-open .case-h1 {
  animation-delay: 0.45s;
}

@media (prefers-reduced-motion: reduce), print {
  .svc-hero .svc-h1,
  .case-open .case-h1 {
    animation: none;
  }
}

/* a line is a mask: clipped to its own box, with room round it for ascenders,
   descenders, italics and a glow, so only the lift from below is hidden */
toai-line {
  display: block;
  clip-path: inset(-0.5em -1em -0.2em -1em);
}

toai-lift {
  display: block;
}

[data-rv='lines'] toai-lift {
  transform: translateY(105%);
  opacity: 0;
}

[data-rv='lines'][data-rv-go] toai-lift {
  transform: none;
  opacity: 1;
  transition:
    transform 0.8s cubic-bezier(0.2, 0.7, 0, 1) calc(var(--rv-i, 0) * 80ms),
    opacity 0.8s cubic-bezier(0.2, 0.7, 0, 1) calc(var(--rv-i, 0) * 80ms);
}

/* the plain rise, on translate so a transform the element has is kept */
[data-rv='fade'] {
  opacity: 0;
  translate: 0 26px;
}

[data-rv='fade'][data-rv-go] {
  opacity: 1;
  translate: none;
  transition:
    opacity 0.7s cubic-bezier(0.2, 0.7, 0.2, 1),
    translate 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}

@media (prefers-reduced-motion: reduce), print {
  html.rv-hold :is(.tsv-page, .room-page) :is(h1, h2),
  html.rv-hold [data-reveal],
  [data-rv='fade'],
  [data-rv='lines'] toai-lift {
    opacity: 1 !important;
    transform: none !important;
    translate: none !important;
    transition: none !important;
  }
}

/* The ring cursor's styles went with it (2026-09-26, site.js section 5). */

/*
 * The weighted scroll (site.js 14): Lenis's own stylesheet, lenis.css 1.3.26
 * (MIT, darkroom.engineering), less the autoToggle rule it is not run with.
 * Stopped (the menu's lock) the root is clipped; an area marked to scroll
 * itself keeps its overscroll to itself; an iframe takes no pointer while the
 * page glides past it.
 */
html.lenis,
html.lenis body {
  height: auto;
}

.lenis:not(.lenis-autoToggle).lenis-stopped {
  overflow: clip;
}

.lenis [data-lenis-prevent],
.lenis [data-lenis-prevent-wheel],
.lenis [data-lenis-prevent-touch],
.lenis [data-lenis-prevent-vertical],
.lenis [data-lenis-prevent-horizontal] {
  overscroll-behavior: contain;
}

.lenis.lenis-smooth iframe {
  pointer-events: none;
}

/* --------------------------------------------------------- 18. breakpoint */

@media (max-width: 767px) {
  .svc-hero {
    padding-top: var(--s-11);
  }

  .svc-grid {
    display: block;
  }

  .tier {
    margin-bottom: var(--s-4);
  }

  .linkband {
    display: block;
  }

  .linkband-item {
    display: block;
    margin-bottom: 14px;
  }

  .ig-fab {
    right: 12px;
    bottom: 54px;
    width: 34px;
    height: 34px;
    font-size: 15px;
  }
}

/* ------------------------------------------------ 19. the guide, site-wide */

/*
 * The floating "?" button, its panel, the first-visit tip, and the hotspot
 * label styling. The live site injects all of this from two registered scripts
 * (toaiguidestylea + toaiguidestyleb) on every page, business card included,
 * so it is static CSS here: same declarations, no runtime <style> injection.
 * The markup is built by guide() in site.js, which is the one that skips the
 * card page exactly as the original does.
 */

.toai-tip {
  position: fixed;
  left: 50%;
  bottom: 56px;
  z-index: 2147482000;
  transform: translateX(-50%);
  max-width: 88vw;
  padding: 9px 15px;
  font-family: 'Azeret Mono', monospace;
  font-size: 11px;
  letter-spacing: 2px;
  text-align: center;
  text-transform: uppercase;
  color: #00f5ff;
  background: rgba(5, 6, 11, 0.85);
  border: 1px solid rgba(0, 245, 255, 0.45);
  border-radius: 4px;
  pointer-events: none;
  transition: opacity 0.6s ease;
}

.toai-tip.toai-out {
  opacity: 0;
}

.toai-help-btn {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 2147483000;
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  font-family: 'Azeret Mono', monospace;
  font-size: 16px;
  font-weight: 700;
  color: #00f5ff;
  background: rgba(5, 6, 11, 0.85);
  border: 1px solid rgba(0, 245, 255, 0.55);
  cursor: pointer;
}

.toai-help-btn.toai-on {
  display: flex;
}

.toai-help-btn:hover {
  box-shadow: 0 0 26px rgba(0, 245, 255, 0.6);
}

.toai-help-panel {
  position: fixed;
  right: 18px;
  bottom: 66px;
  z-index: 2147483000;
  display: none;
  width: 290px;
  max-width: calc(100vw - 36px);
  padding: 16px;
  font-family: 'Azeret Mono', monospace;
  color: #fff;
  background: rgba(5, 6, 11, 0.94);
  border: 1px solid rgba(0, 245, 255, 0.4);
  border-radius: 5px;
}

.toai-help-panel.toai-on {
  display: block;
}

.toai-help-panel h4 {
  margin: 0 0 10px;
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 3px;
  color: #00f5ff;
}

.toai-help-panel ul {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.toai-help-panel li {
  position: relative;
  padding-left: 14px;
  font-size: 12px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.82);
}

.toai-help-panel li::before {
  content: '>';
  position: absolute;
  left: 0;
  color: #00f5ff;
}

.toai-help-x {
  position: absolute;
  top: 9px;
  right: 11px;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.5);
  background: none;
  border: 0;
  cursor: pointer;
}

.toai-help-x:hover {
  color: #00f5ff;
}

@media (max-width: 767px) {
  .toai-tip {
    bottom: 44px;
    font-size: 10px;
  }

  .toai-help-btn {
    right: 12px;
    bottom: 12px;
    width: 34px;
    height: 34px;
  }

  .toai-help-panel {
    right: 12px;
    bottom: 54px;
    width: 250px;
  }
}

/*
 * The homepage hotspots. These rules are site-wide on the live build because
 * the script that injects them is, and they are inert on any page without the
 * markup. The !important flags are the original's.
 */
.toai-hotspot {
  position: absolute !important;
  overflow: visible !important;
}

.toai-hotspot-dot {
  background: #00f5ff !important;
  box-shadow: 0 0 16px 4px rgba(0, 245, 255, 0.85) !important;
  animation: toaiPing 2.2s ease-out infinite !important;
}

@keyframes toaiPing {
  0% {
    box-shadow: 0 0 0 0 rgba(0, 245, 255, 0.6), 0 0 16px 4px rgba(0, 245, 255, 0.85);
  }
  70% {
    box-shadow: 0 0 0 18px rgba(0, 245, 255, 0), 0 0 16px 4px rgba(0, 245, 255, 0.85);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(0, 245, 255, 0), 0 0 16px 4px rgba(0, 245, 255, 0.85);
  }
}

.toai-hotspot-label {
  position: absolute !important;
  top: 28px !important;
  left: 50% !important;
  transform: translateX(-50%) !important;
  width: auto !important;
  max-width: none !important;
  height: auto !important;
  padding: 6px 10px !important;
  opacity: 1 !important;
  font-family: 'Azeret Mono', monospace !important;
  font-size: 10px !important;
  line-height: 1 !important;
  letter-spacing: 2px !important;
  white-space: nowrap !important;
  text-transform: uppercase !important;
  color: #fff !important;
  background: rgba(5, 6, 11, 0.8) !important;
  border: 1px solid rgba(0, 245, 255, 0.55) !important;
  border-radius: 3px !important;
  /* Amir, 2026-09-18: the words are the navigation now, so the label takes
     clicks. toaiguidestylea set pointer-events:none because only the dot was
     clickable on the old splash. */
  pointer-events: auto !important;
  cursor: pointer;
}

@media (max-width: 767px) {
  .toai-hotspot-label {
    top: 24px !important;
    padding: 4px 7px !important;
    font-size: 9px !important;
  }
}

.toai-popup-hotspot-demo > div:first-child {
  background: #00f5ff !important;
  box-shadow: 0 0 12px 3px rgba(0, 245, 255, 0.8) !important;
}

/* ------------------------------------------------------ 20. touch targets

   Coarse pointers only. Every control that is drawn shorter than 44px keeps
   its drawing and grows its hit area with a transparent ::after, so nothing
   moves and a mouse sees none of it. The one visible change is the footer
   link band: its rows sit 34px apart, so on a touch screen the row gap grows
   to 26px and the rows clear each other at 44.
   Links inside running text are left alone, per the inline exception. */

@media (pointer: coarse) {
  .topbar-brand,
  .topbar-link,
  .linkband-item {
    position: relative;
  }

  .topbar-brand::after,
  .topbar-link::after,
  .linkband-item::after {
    content: '';
    position: absolute;
    inset: -12px 0;
  }

  /* the bare Instagram glyph in the top bar is 13px square */
  .ig-link.topbar-link::after { inset: -16px; }

  .linkband { row-gap: 26px; }

  /* both are already fixed, so they carry their own containing block */
  .landscape-home::after {
    content: '';
    position: absolute;
    inset: -4px 0;
  }

  /* the fab is drawn 33.5px square, so -6 clears 44 on both axes */
  .ig-fab::after {
    content: '';
    position: absolute;
    inset: -6px;
  }
}

/* under 768 the band is not a flex row any more: the items stack with a
   margin, so the row gap above does nothing and the margin grows instead */
@media (pointer: coarse) and (max-width: 767px) {
  .linkband-item { margin-bottom: 25px; }
}

/* ------------------------------------------------------- 21. the scroll cue

   Amir, 2026-09-21: "make sure scroll indicators are very visible all over the
   site". 2026-09-22, of the chip, the corner dock and the stacked badge: "very
   ugly, make them fit the website better", and his pick: "a small icon in the
   center of the screen like we did for the splash concept but digital".

   So it is the Splash cue (splash-scroll/index.html, .scrollcue) in this
   site's chrome. The same stack, a mouse, the word, a chevron, pulsing over a
   dark glow with no edge, with every part made digital: the mouse is a cyan
   hairline capsule, its wheel is a lit block that STEPS down rather than
   glides, the word is the mono face tracked wide, the chevron is two hairline
   strokes that light in turn like a cursor, and the pulse is a clean flash
   with a one frame flicker at the top. About 60 by 61px. No box, no border
   round the whole, no plate, no pill. Picked from three drawn over the
   homepage intro and a service page at both sizes (qa/out/cue-v2-variants-*):
   a scanline and caret version read as typed text, and chevrons inside the
   mouse lost the Splash silhouette.

   One spot: centred, low on the screen. site.js section 11 gives it its
   states (the icon, the words, the link, the film's dock) and lifts it just
   clear of a button when one is in that band. */

.toai-cue {
  --cue-ink: #00f5ff;
  position: fixed;
  left: 50%;
  bottom: calc(var(--cue-bottom, 26px) + var(--cue-lift, 0px) + env(safe-area-inset-bottom, 0px));
  z-index: 2147482400;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform: translateX(-50%);
  color: var(--cue-ink);
  text-decoration: none;
  /* a sign, not a control: it must not eat a click meant for whatever is
     behind it. The link state takes its clicks back below. */
  pointer-events: none;
  transition: opacity 0.45s ease;
}

.toai-cue[hidden] {
  display: none;
}

/* the first scroll puts it out, as the Splash cue goes */
.toai-cue.is-out {
  opacity: 0;
  pointer-events: none;
}

/* It never goes out any more (Amir, 2026-09-26): scrolling only dims it, and
   it is back to full strength a quarter second after the visitor stops. */
.toai-cue.is-moving {
  opacity: 0.42;
}

/* The homepage's film (home.js): the full cue, never out, in the bottom right
   corner. Centred it sat on the film's service headlines and its cards
   (measured at 393x659 and 1440x900); that corner is the one the film keeps
   clear. */
.toai-cue.toai-cue--corner {
  left: auto;
  right: calc(22px + env(safe-area-inset-right, 0px));
  transform: none;
}

/* The film's title card fills the bottom band down to the edge, so there the
   cue is the icon alone, low, where the film used to print its own faint
   SCROLL: the same parts, smaller, at full strength. */
.toai-cue.toai-cue--low {
  --cue-bottom: 6px;
}

.toai-cue--low::before {
  width: 96px;
  height: 80px;
}

.toai-cue--low .toai-cue-label {
  display: none;
}

.toai-cue--low .toai-cue-icon {
  gap: 4px;
}

.toai-cue--low .toai-cue-mouse {
  width: 14px;
  height: 22px;
  border-width: 1px;
  border-radius: 7px;
}

.toai-cue--low .toai-cue-wheel {
  top: 4px;
  height: 4px;
  animation-name: cueWheelDock;
}

.toai-cue--low .toai-cue-word {
  font-size: 8px;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
}

.toai-cue--low .toai-cue-chev i {
  width: 5px;
  height: 5px;
  border-width: 1px;
}

.toai-cue--low .toai-cue-chev i + i {
  margin-top: -2px;
}

/* the room pages draw a 30px bar across the bottom: sit clear above it */
.room-page .toai-cue {
  --cue-bottom: 48px;
}

/* The Splash glow: a soft dark ellipse with no edge behind the whole stack,
   so it survives the portal's bright pink frames and reads over copy "as a
   vignette rather than a badge". Not part of the pulse: the ink flashes, the
   shade holds. */
.toai-cue::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: -1;
  width: 150px;
  height: 118px;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(3, 5, 9, 0.62), rgba(3, 5, 9, 0.36) 52%, rgba(3, 5, 9, 0));
  pointer-events: none;
}

/* ---------------------------------------------------------------- the icon */

.toai-cue-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  animation: cueFlash 1.6s ease-in-out infinite;
}

.toai-cue-mouse {
  position: relative;
  box-sizing: border-box;
  display: block;
  width: 18px;
  height: 28px;
  border: 1.5px solid rgba(0, 245, 255, 0.92);
  border-radius: 9px;
  box-shadow: 0 0 7px rgba(0, 245, 255, 0.38), inset 0 0 5px rgba(0, 245, 255, 0.14), 0 0 0 4px rgba(3, 5, 9, 0.22);
}

/* the wheel: a lit block that steps down four rows and fades, then snaps back */
.toai-cue-wheel {
  position: absolute;
  left: 50%;
  top: 5px;
  width: 2px;
  height: 6px;
  margin-left: -1px;
  background: #e6feff;
  box-shadow: 0 0 5px rgba(0, 245, 255, 0.9);
  animation: cueWheel 1.6s steps(4, jump-none) infinite;
}

.toai-cue-word {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.32em;
  text-indent: 0.32em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.86);
  text-shadow: 0 0 9px rgba(0, 245, 255, 0.5), 0 1px 2px rgba(0, 0, 0, 0.95);
}

/* two hairline strokes that light one after the other */
.toai-cue-chev {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: -2px;
}

.toai-cue-chev i {
  display: block;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--cue-ink);
  border-bottom: 1.5px solid var(--cue-ink);
  transform: rotate(45deg);
  opacity: 0.22;
  filter: drop-shadow(0 0 3px rgba(0, 245, 255, 0.7));
  animation: cueChev 1.6s steps(1, end) infinite;
}

.toai-cue-chev i + i {
  margin-top: -3px;
  animation-delay: 0.4s;
}

/* the deck counts itself out in the chevron's place: 03/07 */
.toai-cue-count {
  display: none;
  font-family: var(--font-ui);
  font-size: 9px;
  line-height: 1;
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  color: var(--cue-ink);
  text-shadow: 0 0 6px rgba(0, 245, 255, 0.55), 0 1px 2px rgba(0, 0, 0, 0.95);
}

.toai-cue--count .toai-cue-chev {
  display: none;
}

.toai-cue--count .toai-cue-count {
  display: block;
}

@keyframes cueFlash {
  0%, 100% { opacity: 0.45; }
  46% { opacity: 1; }
  48% { opacity: 0.7; }
  50% { opacity: 1; }
}

@keyframes cueWheel {
  0% { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(9px); opacity: 0.3; }
}

@keyframes cueChev {
  0% { opacity: 1; }
  32% { opacity: 0.22; }
}

/* eight seconds still with more page below: it flashes at twice the rate for
   two cycles, and nothing moves */
.toai-cue.is-urging .toai-cue-icon,
.toai-cue.is-urging .toai-cue-wheel,
.toai-cue.is-urging .toai-cue-chev i {
  animation-duration: 0.8s;
}

.toai-cue.is-urging .toai-cue-chev i + i {
  animation-delay: 0.2s;
}

/* the whole instruction: what a screen reader hears, drawn by the icon */
.toai-cue-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 0 10px rgba(0, 245, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.95), 0 0 7px rgba(0, 0, 0, 0.75);
}

.toai-cue-arrow {
  display: none;
}

/* ------------------------------------------------ the words and the link

   An instruction that is not scrolling (TAP A SCREEN, USE THE ARROWS, TAP A
   MISSION) is said, not drawn: the words and a terminal caret. The page's
   next action is a real link: the words and a thin arrow. Same spot, same
   glow, no box, no capsule, no corner brackets. */

.toai-cue--says,
.toai-cue[href] {
  flex-direction: row;
  gap: 10px;
}

.toai-cue--says .toai-cue-icon,
.toai-cue[href] .toai-cue-icon {
  display: none;
}

.toai-cue--says .toai-cue-label,
.toai-cue[href] .toai-cue-label {
  position: static;
  width: auto;
  height: auto;
  overflow: visible;
  clip-path: none;
}

.toai-cue--says::before,
.toai-cue[href]::before {
  width: calc(100% + 110px);
  height: 88px;
}

.toai-cue--says .toai-cue-label::after {
  content: '';
  display: inline-block;
  width: 6px;
  height: 10px;
  margin-left: 4px;
  vertical-align: -1px;
  background: var(--cue-ink);
  box-shadow: 0 0 6px rgba(0, 245, 255, 0.6);
  animation: cueCaret 1.1s steps(1, end) infinite;
}

@keyframes cueCaret {
  0% { opacity: 1; }
  50% { opacity: 0; }
}

.toai-cue[href] {
  padding: 12px 8px;
  pointer-events: auto;
}

.toai-cue.is-out[href] {
  pointer-events: none;
}

/* a thin arrow: along for another page, down for further down this one */
.toai-cue[href] .toai-cue-arrow {
  position: relative;
  display: block;
  width: 18px;
  height: 1px;
  background: currentColor;
  box-shadow: 0 0 5px rgba(0, 245, 255, 0.6);
  transition: transform 0.2s ease;
}

.toai-cue[href] .toai-cue-arrow::after {
  content: '';
  position: absolute;
  right: 0;
  top: -3px;
  width: 6px;
  height: 6px;
  box-sizing: border-box;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
  transform: rotate(45deg);
}

.toai-cue--down[href] .toai-cue-arrow {
  width: 14px;
  transform: rotate(90deg);
}

.toai-cue[href]:hover .toai-cue-label,
.toai-cue[href]:focus-visible .toai-cue-label {
  color: #fff;
}

.toai-cue[href]:hover .toai-cue-arrow,
.toai-cue[href]:focus-visible .toai-cue-arrow {
  transform: translateX(4px);
}

.toai-cue--down[href]:hover .toai-cue-arrow,
.toai-cue--down[href]:focus-visible .toai-cue-arrow {
  transform: translateY(3px) rotate(90deg);
}

.toai-cue:focus-visible {
  outline: 1px solid var(--cue-ink);
  outline-offset: 2px;
}

/* ------------------------------------------------------------- docked

   The homepage's film draws its own type across the bottom band: its kicker,
   its promise, its ticker and, on a phone, its own SCROLL word. The cue steps
   out of that band into the corner the film keeps clear, on
   window.toaiCue.dock(true): the same icon, smaller. */

.toai-cue--dock {
  left: auto;
  right: calc(26px + env(safe-area-inset-right, 0px));
  bottom: calc(26px + env(safe-area-inset-bottom, 0px));
  transform: none;
}

.toai-cue--dock::before {
  width: 110px;
  height: 92px;
}

.toai-cue--dock .toai-cue-icon {
  gap: 5px;
}

.toai-cue--dock .toai-cue-mouse {
  width: 14px;
  height: 22px;
  border-width: 1px;
  border-radius: 7px;
}

.toai-cue--dock .toai-cue-wheel {
  top: 4px;
  height: 4px;
  animation-name: cueWheelDock;
}

@keyframes cueWheelDock {
  0% { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(7px); opacity: 0.3; }
}

.toai-cue--dock .toai-cue-word {
  font-size: 8px;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
}

.toai-cue--dock .toai-cue-chev i {
  width: 5px;
  height: 5px;
  border-width: 1px;
}

.toai-cue--dock .toai-cue-chev i + i {
  margin-top: -2px;
}

/* While site.js measures the spot it must read where the cue is, not where a
   transition is carrying it. */
.toai-cue.is-measuring {
  transition: none !important;
}

/*
 * First paint, away from the homepage: the page's opening block keeps the
 * cue's height clear underneath it, so on a screen where the opening block
 * ends on screen nothing sits under the cue. Static, keyed off the cue being in
 * the markup, so nothing moves once the page has painted.
 */
:root {
  --cue-space: 92px;
}

:root:has(a.toai-cue) .svc-hero,
:root:has(a.toai-cue) .mission-intro,
:root:has(a.toai-cue) .case-head,
:root:has(a.toai-cue) .welcome-page .film {
  padding-bottom: calc(var(--cue-space) + 16px);
}

@media (max-width: 479.98px) {
  .toai-cue {
    --cue-bottom: 30px;
  }

  .room-page .toai-cue {
    --cue-bottom: 46px;
  }

  .toai-cue--says,
  .toai-cue[href] {
    gap: 9px;
  }

  .toai-cue--says .toai-cue-label,
  .toai-cue[href] .toai-cue-label {
    font-size: 10.5px;
    letter-spacing: 0.22em;
  }
}

/*
 * A short landscape phone is nearly all viewport: the cue would sit on the
 * copy. Same rule the frame follows, it stays out of the way until the visitor
 * has moved (site.js adds the class past 0.8 of a viewport).
 */
@media (orientation: landscape) and (max-height: 600px) {
  .toai-cue {
    --cue-bottom: 10px;
    display: none;
  }

  .toai-cue .toai-cue-chev {
    display: none;
  }

  html.cue-landscape .toai-cue {
    display: flex;
  }
}

/* reduced motion: a static icon. No pulse, no stepping wheel, no caret blink */
@media (prefers-reduced-motion: reduce) {
  .toai-cue {
    transition: opacity 0.2s ease;
  }

  .toai-cue-icon,
  .toai-cue-wheel,
  .toai-cue-chev i,
  .toai-cue--says .toai-cue-label::after {
    animation: none;
  }

  .toai-cue-icon {
    opacity: 0.92;
  }

  .toai-cue-chev i {
    opacity: 0.85;
  }

  .toai-cue[href] .toai-cue-arrow {
    transition: none;
  }
}

/* --------------------------------------------------------- 22. the menu

   Amir, 2026-09-21: "let's add a click through hamburger menu now that leads
   to important parts of the site". One button, one overlay, mounted by site.js
   on every page: into [data-menu-slot] when the page offers one (the homepage
   frame does), otherwise into the top bar, otherwise fixed to the corner the
   room pages keep free. */

/* the shared scroll lock (site.js scrollLock, window.toaiLock) */
html.is-locked,
html.is-locked body {
  overflow: hidden;
}

.toai-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-width: 44px;
  min-height: 44px;
  padding: 0 14px;
  color: var(--cyan-hot);
  background: rgba(5, 6, 11, 0.72);
  border: 1px solid rgba(0, 245, 255, 0.45);
  border-radius: var(--radius);
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.toai-menu-btn--fixed {
  position: fixed;
  top: 20px;
  right: 10px;
  z-index: 2147483100;
}

.toai-menu-btn:hover,
.toai-menu-btn:focus-visible {
  color: var(--white);
  border-color: var(--cyan-hot);
  background: rgba(0, 245, 255, 0.12);
}

.toai-menu-btn:focus-visible {
  outline: 2px solid var(--cyan-hot);
  outline-offset: 3px;
}

/* three hairlines, the middle one shorter, the whole thing 18px wide */
.toai-menu-ico {
  position: relative;
  display: block;
  width: 18px;
  height: 12px;
  flex: 0 0 auto;
}

.toai-menu-ico::before,
.toai-menu-ico::after,
.toai-menu-ico > i {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transition: transform 0.25s ease, opacity 0.25s ease, width 0.25s ease;
}

.toai-menu-ico::before { top: 0; }
.toai-menu-ico > i { top: 50%; width: 70%; }
.toai-menu-ico::after { bottom: 0; }

.toai-menu-btn[aria-expanded='true'] .toai-menu-ico::before {
  transform: translateY(5px) rotate(45deg);
}

.toai-menu-btn[aria-expanded='true'] .toai-menu-ico > i {
  opacity: 0;
}

.toai-menu-btn[aria-expanded='true'] .toai-menu-ico::after {
  transform: translateY(-6px) rotate(-45deg);
}

@media (max-width: 479.98px) {
  .toai-menu-label {
    display: none;
  }

  .toai-menu-btn {
    padding: 0;
  }
}

/* the top bar's Instagram glyph grows a 44px hit area on touch: keep clear */
.topbar-in .toai-menu-btn {
  margin-left: 18px;
}

/*
 * The room pages keep a control in that corner. The button takes the corner
 * and the room control steps aside, far enough that their touch areas do not
 * touch either. /robot's loose variant sets its own right, so it is named.
 */
html.has-menu .room-btn--corner,
html.has-menu .room-btn--loose {
  right: var(--menu-gap, 72px);
}

@media (max-width: 991px) {
  html.has-menu .room-btn--loose {
    top: 0;
  }
}

/* ------------------------------------------------------------- the overlay */

.toai-menu {
  position: fixed;
  inset: 0;
  z-index: 2147483200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 72px 24px 40px;
  background: rgba(3, 4, 8, 0.975);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.toai-menu.is-open {
  opacity: 1;
  visibility: visible;
  /* visible at once on the way in, so the first link can take focus */
  transition: opacity 0.28s ease, visibility 0s;
}

.toai-menu-in {
  position: relative;
  width: 100%;
  max-width: 860px;
  margin: auto;
}

.toai-menu-group + .toai-menu-group {
  margin-top: 34px;
}

/* The way back to the control room, first in the menu (Amir, 2026-09-25:
   "give them a menu option to go back to the screen room so they are not
   confused"). Above the lists rather than in them, so the work still leads
   the menu; the interface face, cyan, with an arrow that steps back on hover.
   On the homepage it waits until the visitor has been in the room
   (html.guide-ready): before that there is nothing to go back to. */
.toai-menu-back {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 30px;
  padding: 10px 0;
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.2;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--cyan-hot);
  text-decoration: none;
  opacity: 0;
  transform: translateY(14px);
}

.toai-menu.is-open .toai-menu-back {
  opacity: 1;
  transform: none;
  transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.toai-menu-back-arrow {
  font-size: 18px;
  line-height: 1;
  transition: transform 0.25s ease;
}

.toai-menu-back:hover,
.toai-menu-back:focus-visible {
  color: var(--white);
}

.toai-menu-back:hover .toai-menu-back-arrow {
  transform: translateX(-4px);
}

.toai-menu-back:focus-visible {
  outline: 2px solid var(--cyan-hot);
  outline-offset: 4px;
}

html:not(.guide-ready) body.home-page .toai-menu-back {
  display: none;
}

.toai-menu-eyebrow {
  margin-bottom: 14px;
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

.toai-menu-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.toai-menu-link {
  display: inline-block;
  padding: 6px 0;
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 44px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.01em;
  color: var(--white);
  text-decoration: none;
  opacity: 0;
  transform: translateY(14px);
}

.toai-menu.is-open .toai-menu-link {
  opacity: 1;
  transform: none;
  transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 45ms);
}

.toai-menu-link:hover,
.toai-menu-link:focus-visible {
  color: var(--cyan-hot);
}

.toai-menu-link:focus-visible {
  outline: 2px solid var(--cyan-hot);
  outline-offset: 4px;
}

.toai-menu-link[aria-current='page'] {
  color: var(--cyan-hot);
}

.toai-menu-link[aria-current='page']::before {
  content: '// ';
  font-family: var(--font-ui);
  font-size: 0.4em;
  letter-spacing: var(--ls-wide);
  vertical-align: middle;
}

.toai-menu-link--action {
  color: var(--void);
  background: var(--cyan-hot);
  padding: 10px 18px;
  margin-top: 6px;
}

.toai-menu-link--action:hover,
.toai-menu-link--action:focus-visible {
  color: var(--void);
  background: var(--white);
}

.toai-menu-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 40px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.toai-menu-foot a {
  color: var(--cyan-hot);
  text-decoration: none;
}

.toai-menu-x {
  position: absolute;
  top: 26px;
  right: 26px;
  z-index: 1;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--cyan-hot);
  background: rgba(5, 6, 11, 0.72);
  border: 1px solid rgba(0, 245, 255, 0.45);
  border-radius: var(--radius);
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

.toai-menu-x:focus-visible {
  outline: 2px solid var(--cyan-hot);
  outline-offset: 3px;
}

@media (orientation: landscape) and (max-height: 600px) {
  .toai-menu {
    padding: 56px 20px 24px;
  }

  .toai-menu-link {
    font-size: clamp(20px, 3.4vw, 28px);
  }

  .toai-menu-group + .toai-menu-group {
    margin-top: 20px;
  }

  .toai-menu-back {
    margin-bottom: 14px;
    padding: 6px 0;
  }

  .toai-menu-foot {
    margin-top: 22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .toai-menu,
  .toai-menu-link,
  .toai-menu.is-open .toai-menu-link,
  .toai-menu-back,
  .toai-menu.is-open .toai-menu-back,
  .toai-menu-back-arrow,
  .toai-menu-ico::before,
  .toai-menu-ico::after,
  .toai-menu-ico > i {
    transition: none;
  }

  .toai-menu-link,
  .toai-menu-back {
    opacity: 1;
    transform: none;
  }
}
