/* Craft layer — interaction polish on top of the ported design.
 *
 * Everything here is progressive enhancement: the page is complete and usable
 * without it. Nothing in this file styles the design itself (that lives in
 * Bricks global classes) — it only adds affordances the template never had.
 *
 * Gating: the cursor and magnet effects are pointer- and motion-gated in CSS as
 * well as in JS, so a touch device or a reduced-motion preference never even
 * gets the custom properties, let alone the listeners.
 */

/* ---------- custom cursor ------------------------------------------------ */

/* Not a dot-with-trailing-ring: that is the default custom cursor of the entire
 * internet. This is a CAPSULE — the shape this design already speaks in (the nav
 * pills, the tool chips at 250px radius, the buttons) — and it behaves like a
 * physical object:
 *
 *   - it squashes and stretches along its direction of travel, so flicking the
 *     pointer across the page elongates it and stopping lets it settle round;
 *   - it rotates to the angle you are actually moving in;
 *   - over anything interactive it inflates into a labelled pill in the same
 *     accent orange as the focus ring, so the cursor and the keyboard affordance
 *     are visibly one system.
 *
 * Position is 1:1 with the pointer — only the deformation lags — which is what
 * makes hiding the system cursor honest rather than a precision tax. */
/* TWO sibling layers on <body>, and the split is load-bearing:
 *
 *   .craft-cursor     carries `mix-blend-mode: difference` and holds ONLY the
 *                     capsule, so the capsule blends against the PAGE.
 *   .craft-cursor-ui  carries no blending and holds the label pill.
 *
 * They cannot be one element. `mix-blend-mode` on a child blends against its
 * parent's stacking context, and this layer needs `z-index` + `will-change:
 * transform` (and GSAP writes a transform on it) — each of which creates a
 * stacking context. Putting the blend on the capsule instead of the layer made
 * it blend against its own empty parent group, so it stayed pure white and was
 * invisible on every white section. Keep the blend on the OUTER element. */
.craft-cursor,
.craft-cursor-ui {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2147483000;      /* above #brx-header, below nothing that matters */
  pointer-events: none;
  will-change: transform;
  opacity: 0;
  transition: opacity .25s ease;
}

.craft-cursor {
  /* difference blending is what lets ONE cursor read on both the near-black hero
     and the white editorial sections with no per-section colour switching. */
  mix-blend-mode: difference;
}

.craft-cursor.is-live,
.craft-cursor-ui.is-live { opacity: 1; }

/* The capsule itself. Sized small and round at rest; JS drives scaleX/scaleY and
   rotation. No blend mode here — see the note above. */
.craft-cursor__cap {
  position: absolute;
  top: 0;
  left: 0;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;    /* centre on the hotspot */
  border-radius: 999px;
  background: #fff;
  will-change: transform;
}

/* The labelled state, built from the site's OWN tokens rather than a new colour:
 * `--primary-color` fill with `--color-for-dark-bg` cream text is exactly the
 * treatment of the "let's get started" button, and the cream hairline border is
 * the treatment of the GITHUB / LINKEDIN pills on the dark hero. Together they
 * read on both grounds — the dark fill carries it on white sections, the cream
 * text and border carry it on the near-black hero.
 *
 * Blending is deliberately OFF here: a white pill under `difference` inverts to
 * black, and text on it would be invisible.
 *
 * Type is copied exactly from `rt-small-tag-v2` (Goli 12px/600, 0.12px tracking,
 * uppercase) so the label belongs to the same type system as every other small
 * label on the page. */
.craft-cursor__label {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%) scale(0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding: 0 22px;
  border-radius: 999px;
  background: var(--primary-color, #12151a);
  border: 1px solid rgba(255, 235, 215, .45);
  color: var(--color-for-dark-bg, #ffebd7);
  font-family: Goli, Arial, sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12px;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  will-change: transform, opacity;
}

/* Only hide the real cursor where we actually drew a replacement. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  html.craft-cursor-active,
  html.craft-cursor-active body,
  html.craft-cursor-active a,
  html.craft-cursor-active [role="button"] {
    cursor: none;
  }

  /* …but never over text you might want to select, or a real control. */
  html.craft-cursor-active :is(input, textarea, select, [contenteditable]) {
    cursor: auto;
  }
}

/* ---------- focus visibility -------------------------------------------- */

/* The ported design shipped with NO focus styling of any kind — an audit of
   every loaded stylesheet found 25 `:focus` rules and all 25 belonged to the
   WordPress admin bar, i.e. nothing at all for a logged-out visitor. That is
   worth fixing on any site and doubly so here, because craft.js hides the
   system cursor: for a keyboard user the focus ring is the ONLY affordance.
 *
 * `:focus-visible`, not `:focus`, so a mouse click never leaves a ring behind.
 *
 * The colour is chosen to clear 3:1 non-text contrast against BOTH grounds this
 * page uses — white sections and the near-black #12151a hero/footer — because a
 * single-colour ring on a two-tone page is invisible on one of them. #ff5c1a
 * gives ~3.0:1 on white and ~5.5:1 on #12151a. The outline-offset keeps it clear
 * of the glyphs on the very large headings. */
:where(#brx-content, #brx-header, #brx-footer) :focus-visible,
.menu-button-main:focus-visible {
  outline: 3px solid #ff5c1a;
  outline-offset: 3px;
}
/* Deliberately NO border-radius here. `outline` already follows the element's
   own radius, and setting one would reshape the pill-shaped nav and tool chips
   the moment they took focus. */

/* Nothing here for the marquee. `.rt-merquee-item` and `.rt-tool-chip` are plain
   divs with tabIndex -1, so they can never take focus, and they inherit
   `cursor: none` from body without needing their own selector — an earlier
   version listed them in both places, which was dead CSS twice over. */

/* Bricks' skip link is present but unstyled; make it land somewhere legible
   instead of appearing as a bare string over the hero. */
.skip-link:focus,
a.skip-link:focus-visible {
  position: fixed !important;
  top: 12px;
  left: 12px;
  z-index: 2147483001;
  width: auto;
  height: auto;
  padding: 12px 18px;
  clip: auto;
  clip-path: none;
  background: #12151a;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  outline: 3px solid #ff5c1a;
  outline-offset: 3px;
}

/* ---------- load intro --------------------------------------------------- */

/* Injected and removed by craft.js. Deliberately has no CSS-only fallback: if
   the script never runs, no overlay is ever created, so the page cannot be left
   covered by something with nothing to remove it. */
.craft-intro {
  position: fixed;
  inset: 0;
  z-index: 2147482000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #12151a;
  will-change: transform;
}

.craft-intro__mark {
  color: #fff;
  font-family: Goli, Arial, sans-serif;
  font-size: clamp(38px, 7vw, 88px);
  font-weight: 600;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  line-height: 1;
  will-change: transform, opacity;
}

/* ---------- word reveal -------------------------------------------------- */

/* craft.js wraps each word of a [data-craft-reveal] heading in one of these.
   inline-block is what makes yPercent work on a word; the negative-tracking
   headings keep their exact spacing because the gap between words is a real
   space character in a sibling .craft-space element — never a margin, which
   would not match the font's own space advance. */
.craft-word {
  display: inline-block;
  will-change: transform, opacity;
}

/* The word separators are elements, not text nodes — see splitWords() in
   craft.js for why. They stay `inline` (never inline-block) so the line-break
   opportunity between words survives and multi-line headings wrap as before.
 *
 * `pre-wrap`, not `pre`. With `pre` the space is preserved even when it lands
 * at a soft wrap, so it carried onto the next line and indented it by 5px —
 * visible on every two-line heading ("ONE PERSON, END / TO END"). Under
 * `pre-wrap` a preserved space at the end of a line hangs instead, so the space
 * keeps its exact width mid-line and contributes nothing at a break. */
.craft-space {
  white-space: pre-wrap;
}

/* ---------- magnetic targets -------------------------------------------- */

/* JS writes --craft-mx / --craft-my (with px units). Using a custom property
   rather than writing `transform` directly means this can never collide with a
   GSAP tween on the same element's transform, and it composites on the GPU. */
.craft-magnetic {
  transform: translate3d(var(--craft-mx, 0px), var(--craft-my, 0px), 0);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .craft-magnetic { transform: none; }
  .craft-cursor { display: none; }
}

/* ---------- mobile navigation ------------------------------------------- */

/* The ported mobile menu opened as a 215x116px white box in the top-left corner
   with 16px links — `inset: 0 0 auto` was being beaten by a width from the
   design's own nav class, so it never went full-width. This makes it a real
   full-screen sheet.
 *
 * Specificity is matched to rebuild.css's `.w-nav[data-collapse] .w-nav-menu.is-open`
 * (0,4,0) and wins on load order, because craft.css is enqueued after rebuild.css.
 * Don't lower it: the design's `.w-nav[data-collapse="medium"] .w-nav-menu`
 * rule is 0,3,0 and silently beat a plain `.w-nav-menu.is-open` once before. */
@media (max-width: 991px) {
  .w-nav-menu.is-open,
  .w-nav[data-collapse] .w-nav-menu.is-open {
    position: fixed;
    inset: 0;
    z-index: 90;
    width: 100%;
    max-width: none;
    height: 100dvh;
    max-height: none;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: clamp(4px, 1.6vh, 16px);
    padding: max(96px, 14vh) 24px 48px;
    background: #12151a;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* the burger stays on top and keeps working as the close button; its lines are
     already white, so they read against the dark sheet without restyling */
  .menu-button-main {
    position: relative;
    z-index: 100;
  }

  /* editorial scale for the links themselves */
  .w-nav-menu.is-open .rt-dropdown-toggle,
  .w-nav[data-collapse] .w-nav-menu.is-open .rt-dropdown-toggle {
    padding: 0;
    width: 100%;
  }

  .w-nav-menu.is-open .rt-small-tag,
  .w-nav[data-collapse] .w-nav-menu.is-open .rt-small-tag {
    color: #fff;
    font-size: clamp(34px, 11vw, 64px);
    line-height: 1.04;
    letter-spacing: -0.02em;
    text-transform: uppercase;
  }

  /* the dropdown panels sit inline under their link rather than floating */
  .w-nav-menu.is-open .w-dropdown-list,
  .w-nav[data-collapse] .w-nav-menu.is-open .w-dropdown-list {
    position: static;
    background: transparent;
  }
}

/* Reduced motion is NOT handled here. init.css seeds `opacity: 0` on ~100
   [data-w-id] elements as pre-animation state, so a blanket
   `opacity: 1 !important` would also un-hide things the design means to stay
   hidden (the landscape stat variants, the brand overlays). anim.js resolves
   each record to its own final keyframe instead — see REDUCED there. */
