/* ==========================================================================
   Home — the hero stage
   Two intentional compositions, not one that shrinks. They are selected by
   media query rather than by class — see the two blocks at the foot of this
   file — and body[data-layout] carries the current one for scripts.
   ========================================================================== */

@font-face {
  font-family: "OrticaLinear-Light";
  src: url("/assets/fonts/OrticaLinear-Light.otf") format("opentype");
  font-weight: 300;
}

.hero {
  position: fixed; inset: 0; z-index: var(--z-plate);
  overflow: hidden;
}

/* --- the plate ----------------------------------------------------------
   Everything pinned to the artwork lives inside this box, so the camera can
   move artwork and annotations as one object. */
.plate {
  position: absolute;
  container-type: size;
  container-name: plate;
  transform-origin: calc(var(--fx) * 100%) calc(var(--fy) * 100%);
  transform: translate3d(var(--cam-x, 0px), var(--cam-y, 0px), 0) scale(var(--cam-s, 1));
  opacity: var(--plate-out, 1);
  will-change: transform, opacity;
}

.plate__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;           /* a cut-out with real edges; never stretch it */
  user-select: none; -webkit-user-drag: none;
}
/* Pre-blurred twin. Cross-fading to a small blurred bitmap costs nothing;
   filter:blur() on an 800px plate scaled 3x costs a frame budget. */
/* The pre-blurred twin is gone: the cut-out has no background of its own, so
   there is nothing to cross-fade to. Depth at the end of the push-in comes
   from the plate dissolving (--plate-out) while the veil peaks and the
   destination rises behind it. */

/* --- the brain: the primary call to action ------------------------------- */
.brain {
  position: absolute;
  left: 27%; top: 6%; width: 62%; height: 52%;
  border-radius: 54% 50% 46% 52% / 56% 52% 48% 44%;
  z-index: 2;
}
.brain::after {
  content: ""; position: absolute; inset: -2%;
  border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, .5);
  box-shadow: 0 0 0 1px rgba(22, 25, 30, .05), 0 12px 60px -18px rgba(12, 16, 22, .55);
  opacity: 0; transform: scale(.97);
  transition: opacity var(--dur-m) var(--ease-out), transform var(--dur-m) var(--ease-out);
}
.brain:hover::after,
.brain:focus-visible::after,
.hero[data-brain-active="true"] .brain::after { opacity: 1; transform: none; }

/* --- annotations: the four worlds ---------------------------------------- */
.annot {
  opacity: var(--annot-out, 1);
  position: absolute;
  left: calc(var(--x) * 100%); top: calc(var(--y) * 100%);
  width: 0; height: 0; z-index: 3;
  --line: 16;                    /* leader length, in % of plate width */
  --dot: 9px;
}

.annot__hit {
  position: absolute; left: 50%; top: 50%;
  width: 2.75rem; height: 2.75rem;      /* 44px touch target around a 9px dot */
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.annot__dot {
  position: absolute; left: 50%; top: 50%;
  width: var(--dot); height: var(--dot);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(22, 25, 30, .22), 0 2px 10px rgba(12, 16, 22, .35);
  transition: transform var(--dur-s) var(--ease-out), box-shadow var(--dur-s) var(--ease-out);
}
.annot__dot::before {                    /* halo, only on interest */
  content: ""; position: absolute; inset: -7px;
  border: 1px solid rgba(255, 255, 255, .8);
  border-radius: 50%;
  opacity: 0; transform: scale(.72);
  transition: opacity var(--dur-s) var(--ease-out), transform var(--dur-m) var(--ease-out);
}

.annot__line {
  position: absolute; top: 50%; height: 1px;
  width: calc(var(--line) * 1cqw);
  transform-origin: var(--line-origin, left) center;
  transform: scaleX(var(--line-in, 0));
  transition: transform var(--dur-l) var(--ease-out);
  pointer-events: none;
}
.annot__label {
  position: absolute; top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  cursor: pointer;              /* the label is part of the target */
  opacity: var(--label-in, 0);
  transition: opacity var(--dur-m) var(--ease-out) 120ms;
}
.annot__title { display: block; color: var(--ink); }
.annot__sub   { display: block; color: var(--ink-muted); font-size: var(--t-micro);
                letter-spacing: var(--track-label); text-transform: uppercase; margin-top: .15rem; }

/* leader + label to the left of the dot */
.annot[data-side="left"]  .annot__line  { right: 0; background: linear-gradient(to left,  rgba(255,255,255,.95), rgba(255,255,255,.25)); --line-origin: right; }
.annot[data-side="left"]  .annot__label { right: calc(var(--line) * 1cqw + .75rem); text-align: right; }
/* leader + label to the right of the dot */
.annot[data-side="right"] .annot__line  { left: 0;  background: linear-gradient(to right, rgba(255,255,255,.95), rgba(255,255,255,.25)); --line-origin: left; }
.annot[data-side="right"] .annot__label { left: calc(var(--line) * 1cqw + .75rem); }

/* interest states — hover, focus, and the touch equivalent (data-active) */
.annot:is(:hover, :focus-within)   .annot__dot,
.annot[data-active="true"]         .annot__dot { transform: translate(-50%, -50%) scale(1.25); }
.annot:is(:hover, :focus-within)   .annot__dot::before,
.annot[data-active="true"]         .annot__dot::before { opacity: 1; transform: none; }
.annot:is(:hover, :focus-within)   .annot__title,
.annot[data-active="true"]         .annot__title { color: var(--focus); }

/* --- copy ---------------------------------------------------------------- */
.hero__copy {
  position: absolute; z-index: var(--z-copy);
  max-width: 38rem;
  opacity: var(--copy-out, 1);
  transform: translate3d(0, var(--copy-y, 0px), 0);
  will-change: transform, opacity;
}
.hero__eyebrow {
  display: flex; align-items: center; gap: .75rem;
  color: var(--ink-soft); margin: 0 0 clamp(1.25rem, 2.4vw, 2rem);
}
/* One step darker than the decorative grey. These separators are the only
   thing in this column that was forcing the sky behind them to be washed out,
   and the difference between the two greys is imperceptible at 11px. */
.hero__eyebrow span[aria-hidden] { color: var(--ink-muted); }

.hero__title {
  margin: 0;
  font-size: var(--t-display);
  font-weight: 300;
  font-family: OrticaLinear-Light;
  line-height: 1.045;
  letter-spacing: var(--track-tight);
  color: var(--ink);
}
.hero__lede {
  margin: clamp(1.25rem, 2.2vw, 1.75rem) 0 0;
  max-width: 27rem;
  font-size: var(--t-lede);
  line-height: 1.62;
  color: var(--ink-soft);
}

/* Staggered entrance.
   Gated on .js, which an inline script in <head> sets before first paint. The
   hidden state is therefore opt-in: with scripting off the copy is simply
   visible, instead of being invisible forever waiting for a class that never
   arrives. */
.js .reveal { opacity: 0; transform: translate3d(0, 1.1rem, 0); }
.js .is-ready .reveal {
  opacity: 1; transform: none;
  transition: opacity var(--dur-l) var(--ease-out) var(--delay, 0ms),
              transform var(--dur-l) var(--ease-out) var(--delay, 0ms);
}

/* --- enter cue ----------------------------------------------------------
   Doubles as the accessible text CTA: the brain is discoverable, this is
   unmissable, and both run the same transition. */
.enter-cue {
  position: absolute; z-index: var(--z-copy);
  display: flex; align-items: center; gap: 1rem;
  color: var(--ink-soft);
  opacity: var(--copy-out, 1);
}
.enter-cue__ring { flex: none; display: block; overflow: visible; }
.enter-cue__ring circle { fill: none; stroke-width: 1; }
.enter-cue__ring .track { stroke: var(--rule); }
.enter-cue__ring .fill {
  stroke: var(--ink);
  stroke-dasharray: var(--ring-len, 100);
  stroke-dashoffset: calc(var(--ring-len, 100) * (1 - var(--p, 0)));
  transform: rotate(-90deg); transform-origin: center;
}
.enter-cue__stem {
  position: absolute; left: 1.03rem; top: 2.9rem;
  width: 1px; height: 2.1rem; background: var(--rule);
}
.enter-cue__stem::after {
  content: ""; position: absolute; inset: 0 auto auto 0;
  width: 1px; height: 100%; background: var(--ink);
  transform: scaleY(var(--p, 0)); transform-origin: top;
}
.enter-cue:hover { color: var(--ink); }

/* ==========================================================================
   Composition A — cinematic (wide landscape)
   ========================================================================== */
@media (min-width: 1180px) and (min-aspect-ratio: 3/2) {
  .hero { --plate-gap: 13vw; }

  /* The cut-out is trimmed to the artwork, so unlike the old plate it carries
     no empty margin on its left to buffer the headline. Its width is capped
     against the viewport rather than driven purely by height, which keeps the
     face clear of the type at every aspect ratio. */
  .plate {
    right: var(--plate-gap); bottom: 0;
    width: min(47vw, calc(98svh * 1195 / 1202));
    aspect-ratio: 1195 / 1202;
    height: auto;
  }
  .hero__copy {
    left: var(--gutter); top: 50%;
    transform: translate3d(0, calc(-50% + var(--copy-y, 0px)), 0);
  }
  .enter-cue   { left: var(--gutter); bottom: clamp(2.5rem, 6vh, 4.5rem); }

  .hero__mobile-index { display: none; }
}

/* Very wide / short screens: stop the plate growing past the copy. */
@media (min-width: 1180px) and (min-aspect-ratio: 21/9) {
  .hero { --plate-gap: 20vw; }
}

/* Just over the cinematic threshold the plate is proportionally at its widest
   relative to the copy, and the headline starts running into its feathered
   edge. Shortening the plate narrows it and gives the words room back. */
@media (min-width: 1180px) and (max-width: 1400px) and (min-aspect-ratio: 3/2) {
  .plate { width: min(44vw, calc(88svh * 1195 / 1202)); }
  .hero__title { font-size: clamp(2.4rem, 4vw, 3.2rem); }
}

/* ==========================================================================
   Composition B — stacked (tablet, mobile, portrait, short windows)
   The artwork becomes the header image; the four worlds become an index you
   can actually read and tap. Nothing here depends on hover.
   ========================================================================== */
@media not all and (min-width: 1180px) and (min-aspect-ratio: 3/2) {
  body { overflow: auto; }

  .hero { position: relative; inset: auto; min-height: 100svh; overflow: clip; }

  .plate {
    position: relative; margin-left: auto;
    width: min(118%, 40rem);
    right: -7%;
    aspect-ratio: 1195 / 1202;
    height: auto;
    max-height: 62svh;
    margin-top: calc(var(--header-h) * -.2);
    -webkit-mask-image: linear-gradient(to bottom, #000 76%, transparent 99%);
            mask-image: linear-gradient(to bottom, #000 76%, transparent 99%);
  }
  /* The annotation layer is hover-dependent and cramped at this size: the
     index below replaces it. Dots stay as visual anchors only. */
  .annot__line, .annot__label { display: none; }
  .annot { --dot: 7px; pointer-events: none; }   /* the index below is the control */

  .hero__copy {
    position: relative; margin: -8svh var(--gutter) 0; max-width: 30rem;
  }
  .enter-cue { position: relative; margin: 2.25rem var(--gutter) 0; }
  .enter-cue__stem { display: none; }

  .hero__mobile-index {
    margin: clamp(2.5rem, 7vh, 4rem) var(--gutter) clamp(3rem, 9vh, 5rem);
    border-top: 1px solid var(--rule-soft);
  }
}

/* Phones and tablets: the worlds live on the head, exactly as on the desktop:
   the same labels (title and discipline, in the desktop type, no cards), the
   same white leader lines out to each point in the hair. The list of rows
   under the portrait goes. Tapping a label opens that world; tapping or
   pinching the head zooms into all of them. Nested so it applies only to the
   stacked composition below the desktop, or on touch screens. */
@media not all and (min-width: 1180px) and (min-aspect-ratio: 3/2) {
  @media (max-width: 1179px), (hover: none) and (pointer: coarse) {
    .hero__mobile-index { display: none; }
    .annot { pointer-events: auto; }
    .annot__line, .annot__label { display: block; }
    .annot__label::after { content: ""; position: absolute; inset: -.5rem -.4rem; }   /* finger-sized */
    /* the portrait's soft lower edge belongs to the photograph, so the
       labels can sit beside it in the sky without being faded with it */
    .plate { -webkit-mask-image: none; mask-image: none; }
    .plate__img {
      -webkit-mask-image: linear-gradient(to bottom, #000 76%, transparent 99%);
              mask-image: linear-gradient(to bottom, #000 76%, transparent 99%);
    }
    /* a two-finger pinch here zooms into the worlds (camera.js), so the
       browser's own pinch-zoom stands aside on the portrait only */
    .plate { touch-action: pan-x pan-y; }
    /* each point, its line and its label drift very slightly, out of step
       with one another, as if afloat in the city */
    @media (prefers-reduced-motion: no-preference) {
      .annot { animation: abt-annot-drift 9s ease-in-out infinite alternate; }
      .annot[data-world="ai"]       { animation-duration: 11s; animation-delay: -4s; }
      .annot[data-world="product"]  { animation-duration: 10s; animation-delay: -7s; }
      .annot[data-world="creative"] { animation-duration: 12s; animation-delay: -2s; }
    }
  }

  /* Tablets (a large one in landscape too): the portrait moves left, below
     the navigation, leaving the desktop's sky on the right, so the labels
     sit exactly where the desktop puts them. */
  @media (min-width: 46.01rem) and (max-width: 1179px),
         (min-width: 46.01rem) and (hover: none) and (pointer: coarse) {
    /* the whole composition sits in the middle of a tall screen rather than
       at the top of it; a screen it already fills is left as it is */
    .hero { display: flex; flex-direction: column; justify-content: safe center; }
    .plate {
      margin-left: 5vw; right: auto;
      margin-top: calc(var(--header-h) * .7);
      width: min(calc((100vw - 18rem) / .945), 40rem, calc(64svh * 1195 / 1202));
      max-height: none;
    }
  }

  /* Phones: there is no sky beside the head, so the four labels form an
     evenly spaced column in the sky at the right edge, each joined to its
     point by a leader line (angled where the point sits above or below its
     label): the desktop's arrangement, folded to fit. The portrait is sized
     so the column clears the hair; the opening is centred on the screen.
     --lx/--ly place the label relative to its point; the line is drawn from
     the point to the label with hypot() and atan2(). */
  @media (max-width: 46rem) {
    .hero { display: flex; flex-direction: column; justify-content: center; }
    .plate {
      width: calc(104% - 7.86rem);          /* the hair ends just short of the column */
      right: auto; margin-left: -2%;
      max-height: none;
    }
    .hero__copy { margin-top: 1.75rem; }    /* beneath the labels, not over them */
    .annot {
      --lx: calc(102vw - 7.1rem - var(--x) * 100cqw);
      --dx: calc(var(--lx) - .5rem);
      --dy: calc(var(--ly) - var(--y) * 100cqh);
    }
    .annot[data-world="healthcare"] { --ly: -8cqh; }
    .annot[data-world="ai"]         { --ly: 22cqh; }
    .annot[data-world="product"]    { --ly: 50cqh; }
    .annot[data-world="creative"]   { --ly: 80cqh; }
    .annot[data-side] .annot__line {
      left: 0; right: auto; top: 0;
      width: hypot(var(--dx), var(--dy));
      rotate: atan2(var(--dy), var(--dx));
      --line-origin: left;
      background: linear-gradient(to right, rgba(255, 255, 255, .95), rgba(255, 255, 255, .35));
    }
    .annot[data-side] .annot__label {
      left: var(--lx); right: auto; top: var(--dy);
      text-align: left; white-space: normal;
      width: max-content; max-width: 6.5rem;
    }
  }
}


/* Under the desktop width the artwork starts below the navigation, so the
   links sit on sky rather than on the city in her hair. */
@media (max-width: 1179px) {
  .plate { margin-top: calc(var(--header-h) * .7); }
}
@media (hover: none) and (pointer: coarse) {
  .enter-cue { min-height: 44px; }
}
/* Phones: the cue's words stop short of the small portrait in the corner,
   and where they need two lines, the two are even. */
@media (max-width: 46rem) {
  .enter-cue { padding-right: calc(46px + .5rem); }
  .enter-cue .u-label { text-wrap: balance; text-align: left; }
}

@media (max-width: 640px) {
  /* sized so each of the headline's three lines holds on a phone, rather
     than breaking into single words */
  .hero__title { font-size: clamp(1.65rem, 8.5vw, 2.75rem); line-height: 1.08; }
  .hero__lede { max-width: 24rem; }
  .world-row { grid-template-columns: 2rem 1fr; }
  .world-row__go { display: none; }        /* the whole row is the target */
}

@keyframes abt-annot-drift {
  0%   { translate: 0 0; }
  50%  { translate: 1.5px -2.5px; }
  100% { translate: -1.5px 1.5px; }
}
