/* Generated by design-mocks/hero-3d/build-site-css.py from design-mocks/hero-3d/hero.css. Edit the source, then rebuild. */
.hero3d button:focus-visible, .hero3d a:focus-visible, .hero3d .viewport:focus-visible { outline: 2px solid var(--wax); outline-offset: 5px; }
.hero3d .hero-shell { max-width: 1394px; margin: auto; perspective: 2000px; }
.hero3d .hero-card { position: relative; display: grid; grid-template-columns: minmax(0, .94fr) minmax(0, 1fr); gap: 48px; align-items: center; padding: 20px 0; transform-style: preserve-3d; }
.hero3d .visual-column { position: relative; min-width: 0; transform-style: preserve-3d; }
.hero3d .viewport { width: 100%; aspect-ratio: 1; position: relative; perspective: 1200px; transform-style: flat; cursor: grab; touch-action: pan-y pinch-zoom; user-select: none; -webkit-user-select: none; border-radius: 18px; margin: 6px 0 0; }
/* ── Honeycomb: a precise operating diagram with depth ─────────────
   World geometry is in units (--u = viewport px per unit, set by JS), so
   nothing is rasterized at one size and resampled at another. */
.hero3d .fit-world { position: absolute; inset: 0; transform-style: preserve-3d; --u: 1px; }
.hero3d .comb { position: absolute; inset: 0; transform: rotateX(3deg) rotateY(-4deg); transform-style: preserve-3d; }
/* The wiring plane sits inside the slabs: behind every front face (outer 10u, center 22u)
   and in front of every back face (outer -2u, center 6u), so faces hide it from both sides. */
.hero3d .circuits { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; transform: translateZ(calc(var(--u) * 8)); }
/* Opacity sits on the spoke line and the dot, not on their group: the pulse's spoke
   piece lives in the same group, and a group's opacity is not something a child
   can undo. The group carries only width and colour. */
.hero3d .circuits .connection { stroke-width: 1.5; transition: stroke-width .6s ease, stroke .6s ease; }
.hero3d .circuits .connection > path { opacity: .7; transition: opacity .6s ease; }
.hero3d .circuits .connection > circle { opacity: .7; transition: opacity .6s ease, r .6s ease; }
/* The rim: an SVG inside the cell's front face, in the cell's own coordinates, so
   it is part of the hexagon and does whatever the hexagon does. It carries one fixed
   outline, identical on every cell, and the two perimeter arms of the pulse. */
.hero3d .rim { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; overflow: visible; pointer-events: none; }
.hero3d .rim-base { fill: none; stroke: currentColor; stroke-width: 1; opacity: .10; }
/* The pulse. Its profile is overlapping segments rather than one dash, because a
   dash has a hard edge at both ends and reads as a sliding bar. Each segment trails
   the one in front by half its length and is dimmer, thinner and deeper in colour,
   so together they make a soft head with a fading wake. hero.js writes the
   keyframes: one per segment per piece, the same for every area. */
/* The strokes and the arm groups that fade share one duration: travel in the
   first half, rest in the second. */
.hero3d .pulse { fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; }
.hero3d .pulse, .hero3d .fade { animation-duration: var(--route-dur, 1400ms); animation-timing-function: linear; animation-fill-mode: both; }
/* Strip-down for checking the mechanism: every outer cell neutral and bare, the
   rim obvious, the pulse four times slower. */
.hero3d .test .hex-cell:not(.center) { --face: #3b444c; --side: #242a30; --wash: none; --glow: rgba(255, 255, 255, .10); --glow-hi: rgba(255, 255, 255, .16); }
.hero3d .test .cell-label { visibility: hidden; }
.hero3d .test .rim-base { opacity: .45; }
.hero3d .test .pulse, .hero3d .test .fade { animation-duration: 5600ms; }
/* A: what stays after the routing, so the finding does not come loose from its owner. */
.hero3d .circuits .connection.kept { stroke-width: 2; }
.hero3d .circuits .connection.kept > path, .hero3d .circuits .connection.kept > circle { opacity: .95; }
/* B and D: focus is the absence of everything else. Nothing gains an outline.
   A receding area stays fully opaque and simply gets darker. Dropping its opacity
   instead would let its own spoke show through the hexagon, which read as if the
   spoke were drawn over the top of it. The filter goes on the faces and the
   extruded sides, never on the cell, because a filter on the cell would flatten
   the 3D hierarchy inside it. */
.hero3d .hex-cell.is-quiet .hex-front, .hero3d .hex-cell.is-quiet .hex-back { filter: drop-shadow(0 0 calc(var(--u) * 4) var(--glow)) brightness(.4) saturate(.75); animation: none; }
.hero3d .hex-cell.is-quiet .hex-side { filter: brightness(.4); }
.hero3d .hex-side { transition: filter .6s ease; }
.hero3d .circuits .connection.is-quiet > path, .hero3d .circuits .connection.is-quiet > circle { opacity: .16; }
/* The area a visitor picked is their own emphasis, so it wins over whatever the cycle is showing. */
.hero3d .circuits .connection.selected { stroke-width: 2.5; }
.hero3d .circuits .connection.selected > path, .hero3d .circuits .connection.selected > circle { opacity: 1; }
.hero3d .hex-cell { position: absolute; padding: 0; border: 0; background: none; transform-style: preserve-3d; transform: translate3d(calc(var(--in-x, 0) * var(--draw, 0px)), calc(var(--in-y, 0) * var(--draw, 0px)), calc(var(--rest-depth) + max(var(--lift-role, 0px), var(--lift-user, 0px)))) scale(var(--grow, 1)); transition: transform .36s cubic-bezier(.2,.8,.2,1); color: var(--wax);
  --accent: #6bfced; --face: #07a4a6; --side: #045a5c; --glow: rgba(107, 252, 237, .26); --glow-hi: rgba(107, 252, 237, .42);
  --wash: radial-gradient(circle at 50% 50%, rgba(107, 252, 237, .35) 0%, rgba(7, 164, 166, .2) 60%, transparent 100%); }
.hero3d .hex-cell.amber { --accent: #ffb627; --face: #d97706; --side: #8a4a06; --glow: rgba(255, 182, 39, .2); --glow-hi: rgba(255, 182, 39, .33);
  --wash: radial-gradient(circle at 50% 50%, rgba(255, 233, 168, .4) 0%, rgba(255, 182, 39, .3) 50%, rgba(217, 119, 6, .15) 100%); }
.hero3d .hex-cell.center { --face: #0b1418; --side: #0a2224; --glow: rgba(107, 252, 237, .18); --glow-hi: rgba(107, 252, 237, .3);
  --wash: radial-gradient(circle at 50% 50%, rgba(107, 252, 237, .12) 0%, transparent 65%); }
.hero3d .hex-cell:hover, .hero3d .hex-cell:focus-visible { --lift-user: calc(var(--u) * 10); }
.hero3d .hex-cell.selected { --lift-user: calc(var(--u) * 30); }
.hero3d .hex-cell:focus-visible { outline: none; }
/* Faces: an unclipped plane carries the glow (a drop-shadow follows the hexagon
   silhouette, like the live hero); the clipped .hex-face inside carries the fill. */
.hero3d .hex-front, .hero3d .hex-back { position: absolute; inset: 0; backface-visibility: hidden; filter: drop-shadow(0 0 calc(var(--u) * 10) var(--glow)); animation: glow-pulse 5s ease-in-out infinite; transition: filter .6s ease; }
.hero3d .hex-back { transform: translateZ(calc(-1 * var(--thickness))) rotateY(180deg); }
.hero3d .hex-cell:nth-child(3n + 1) .hex-front, .hero3d .hex-cell:nth-child(3n + 1) .hex-back { animation-delay: -1.2s; }
.hero3d .hex-cell:nth-child(3n + 2) .hex-front, .hero3d .hex-cell:nth-child(3n + 2) .hex-back { animation-delay: -2.4s; }
/* Hit-testing: in a preserve-3d context a transparent ancestor plane can sit in front of
   cells that lean away from the viewer and swallow their clicks. Only the clipped face
   takes the pointer, so every click lands on the hexagon itself. */
.hero3d .fit-world, .hero3d .comb, .hero3d .hex-cell, .hero3d .hex-front, .hero3d .hex-back { pointer-events: none; }
.hero3d .hex-face { position: absolute; inset: 0; clip-path: var(--hex); background: var(--face); display: grid; place-items: center; pointer-events: auto; cursor: pointer; }
.hero3d .hex-face::before { content: ""; position: absolute; inset: 0; background: var(--wash); pointer-events: none; }
.hero3d .hex-cell:hover .hex-front, .hero3d .hex-cell.selected .hex-front { filter: drop-shadow(0 0 calc(var(--u) * 16) var(--glow-hi)); animation: none; }
.hero3d .hex-cell:focus-visible .hex-front::after { content: ""; position: absolute; inset: 0; clip-path: var(--hex); background: var(--wax); }
.hero3d .hex-cell:focus-visible .hex-face { inset: 2.5px; z-index: 1; }
/* The tagline no longer restyles a node. A cell changes only when a visitor
   hovers or selects it, or when a variant quiets the areas around the subject. */
.hero3d .hex-cell { transition: transform .36s cubic-bezier(.2,.8,.2,1), opacity .7s ease; }
.hero3d .hex-cell.selected .hex-front { filter: drop-shadow(0 0 calc(var(--u) * 16) var(--glow-hi)); animation: none; }
@keyframes glow-pulse { 0%, 100% { filter: drop-shadow(0 0 calc(var(--u) * 9) var(--glow)); } 50% { filter: drop-shadow(0 0 calc(var(--u) * 15) var(--glow-hi)); } }
.hero3d .hex-side { position: absolute; left: 0; top: 0; transform-origin: 0 0; background: var(--side); pointer-events: none; }
.hero3d .cell-label { position: relative; display: flex; flex-direction: column; align-items: center; gap: 5px; white-space: nowrap; z-index: 1; font: 600 13px/1.15 "Space Grotesk", sans-serif; letter-spacing: -.01em; color: var(--wax); }
.hero3d .cell-index, .hero3d .mobile-functions { display: none; }
.hero3d .cell-label svg { width: 22px; height: 22px; stroke: rgba(245, 235, 215, .92); margin-bottom: 2px; }
.hero3d .cell-label .status { font: 500 9px/1 Inter, sans-serif; letter-spacing: 0; color: rgba(245, 235, 215, .58); }
.hero3d .center .cell-label { gap: 10px; font: 700 12.5px "Space Grotesk", sans-serif; letter-spacing: -.02em; text-transform: uppercase; }
.hero3d .center .cell-label svg { width: 58px; height: 58px; fill: var(--cyan); stroke: none; margin: 0; animation: mark-pulse 4s ease-in-out infinite; }
@keyframes mark-pulse { 0%, 100% { filter: drop-shadow(0 0 12px rgba(107, 252, 237, .65)) drop-shadow(0 0 26px rgba(107, 252, 237, .25)); } 50% { filter: drop-shadow(0 0 16px rgba(107, 252, 237, .9)) drop-shadow(0 0 36px rgba(107, 252, 237, .4)); } }
.hero3d .hex-back .cell-label { opacity: .75; }
.hero3d .viewport.dragging, .hero3d .viewport.dragging * { cursor: grabbing; }
.hero3d .pitch { padding: 0; min-width: 0; }
/* Sized to stand level with the honeycomb: 87px at 1920 wide, scaling with the
   viewport below that. Balanced so the two lines break the same way at every
   width ("Maitrium unsticks / the business.") rather than shifting with size. */
.hero3d h1 { font: 600 clamp(34px, 4.55vw, 87px)/1 "Space Grotesk", sans-serif; letter-spacing: -.055em; margin: 0; text-wrap: balance; }
.hero3d h1 span { display: block; }
.hero3d h1 span:first-child { color: var(--cyan); text-shadow: 0 0 60px rgba(107, 252, 237, .35); }
/* ── The second line: four principles stacked in one grid cell, in a box exactly one
   line tall, so nothing below it moves and the box itself is the mask. Sized so the
   longest principle stays on one line at every width: it needs (column / 14.07) px,
   and every value here leaves at least 7% of room. A principle never wraps, so copy
   that outgrows the box spills into view instead of vanishing behind the mask. ── */
.hero3d .principles { display: grid; grid-template-areas: "line"; align-content: start; height: 1.06em; margin: 14px 0 27px; font: 500 clamp(24px, 2.5vw, 48px)/1.06 "Space Grotesk", sans-serif; letter-spacing: -.045em; color: var(--honey); text-shadow: 0 0 40px rgba(240, 169, 26, .15); clip-path: inset(0 -50vmax -.09em -50vmax); }
.hero3d .principle { grid-area: line; white-space: nowrap; }
/* Until the script splits the lines into characters, only the first one shows. */
.hero3d .principles:not(.is-split) .principle { opacity: 0; }
.hero3d .principles:not(.is-split) .principle:first-child { opacity: 1; }
/* Each word masks its own characters, so a character travels one line box and no
   further, and a line that wraps behaves the same as one that does not. The mask
   is open at the sides for the glow and reaches below the baseline for descenders. */
.hero3d .is-split .word { display: inline-block; }
.hero3d .is-split .char { display: inline-block; transform: translateY(var(--y, 225%)); transition: transform .3s cubic-bezier(.33, 1, .68, 1) var(--d, 0s); }
.hero3d .is-split .principle.is-parking .char { transition: none; }
.hero3d .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.hero3d .ctas { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.hero3d .ctas a { padding: 12px 17px; border-radius: 8px; font-size: 13px; font-weight: 600; min-height: 44px; display: inline-flex; gap: 14px; align-items: center; }
.hero3d .ctas .primary { background: var(--cyan); color: #092523; }
.hero3d .ctas .primary:hover { background: #a2fff3; }
.hero3d .ctas .secondary { border: 1px solid #d7dfcf26; }
.hero3d .ctas .secondary:hover { border-color: #d7dfcf80; }
.hero3d .detail { display: none; border-top: 1px solid #ffffff1c; margin-top: 29px; padding-top: 17px; min-height: 163px; }
.hero3d .has-selection .detail { display: block; }
.hero3d .detail-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 10px; text-transform: uppercase; letter-spacing: .09em; color: #a4b4ac; }
.hero3d .detail.amber .detail-state { color: var(--honey); }
.hero3d .detail.flow .detail-state { color: var(--cyan); }
.hero3d .detail h2 { font: 500 18px/1.35 "Space Grotesk", sans-serif; letter-spacing: -.025em; margin: 12px 0 6px; }
.hero3d .detail p { color: #abb7b0; font-size: 13px; line-height: 1.6; margin: 0; max-width: 44ch; }
.hero3d .detail a { display: inline-block; font-size: 12px; color: var(--cyan); margin-top: 13px; }
.hero3d .detail a:hover { text-decoration: underline; text-underline-offset: 4px; }
/* Entrance: the operating environment assembles around Maitrium, once, on load.
   Two classes. `.entering` holds the before state with no transition; removing it
   while `.enters` is on plays the whole sequence. hero.js sets --enter-delay per
   cell, so the areas arrive one after another rather than all at once. */
.hero3d .comb.entering .hex-cell:not(.center) { --draw: calc(var(--u) * 66); --grow: .78; opacity: 0; }
.hero3d .comb.entering .hex-cell.center { opacity: 0; }
.hero3d .comb.entering .connection > path { stroke-dashoffset: 275; }
.hero3d .comb.entering .connection > circle { opacity: 0; }
.hero3d .comb.entering .status { opacity: 0; }
.hero3d .comb.enters .hex-cell { transition: transform .75s cubic-bezier(.22,.61,.36,1) var(--enter-delay, 0ms), opacity .5s ease var(--enter-delay, 0ms); }
.hero3d .comb.enters .hex-cell.center { transition: opacity .35s ease; }
.hero3d .comb.enters .hex-face { pointer-events: none; }
.hero3d .comb.enters .connection > path { transition: stroke-dashoffset .62s ease calc(var(--enter-delay, 0ms) + 250ms); }
.hero3d .comb.enters .connection > circle { transition: opacity .3s ease calc(var(--enter-delay, 0ms) + 690ms); }
.hero3d .comb.enters .status { transition: opacity .35s ease 1150ms; }
@media (max-width: 1100px) {
  .hero3d .hero-card { gap: 32px; }
  .hero3d .pitch { padding-top: 13px; }
  .hero3d h1 { font-size: clamp(34px, 4vw, 44px); }
  .hero3d .principles { font-size: clamp(18px, 2.6vw, 32px); margin: 12px 0 24px; }
}
@media (max-width: 800px) {
  .hero3d .hero-shell { max-width: 620px; padding: 0; }
  /* One column. The two columns dissolve so their children can interleave:
     headline, principle, graphic, detail, buttons. */
  .hero3d .hero-card { display: flex; flex-direction: column; gap: 0; }
  .hero3d .pitch, .hero3d .visual-column { display: contents; }
  .hero3d h1 { order: 2; font-size: clamp(36px, 9vw, 48px); }
  /* The card centres its children in one column. The line is now narrower than the
     column, so without this it would sit centred under a left-aligned headline. */
  .hero3d .principles { order: 2; font-size: clamp(17px, 5.6vw, 30px); margin: 10px 0 10px; align-self: stretch; }
  .hero3d .viewport { order: 3; margin: 4px auto 0; width: min(100%, 420px); }
  .hero3d .detail { order: 4; border-top: 0; border-bottom: 1px solid #ffffff1c; margin: 6px 0 22px; padding: 0 0 18px; min-height: 118px; }
  .hero3d .detail h2 { font-size: 17px; margin-top: 8px; }
  .hero3d .ctas { order: 6; }
  .hero3d .mobile-functions { display: none; }
  /* Cells: icon and a short name, status hidden. Sized to clear the hexagon's points. */
  .hero3d .cell-label { gap: 4px; }
  .hero3d .cell-label svg { width: 20px; height: 20px; margin-bottom: 1px; }
  .hero3d .cell-name { display: block; font-size: 9px; letter-spacing: -.01em; }
  .hero3d .cell-label .status, .hero3d .cell-index { display: none; }
  .hero3d .center .cell-label { gap: 6px; font-size: 8.5px; }
  .hero3d .center .cell-label svg { width: 36px; height: 36px; }
}
@media (max-width: 420px) {
  .hero3d .detail h2 { font-size: 16px; }
}
@media (hover: none) {
  /* Touch: the model never claims a gesture, so scrolling over it is always scrolling. */
  .hero3d .viewport { touch-action: auto; cursor: default; }
  .hero3d .hex-cell:hover { --lift-user: 0px; }
  .hero3d .hex-cell.selected { --lift-user: 38px; }
}
@media (prefers-reduced-motion: reduce) {
  .hero3d *, .hero3d *::before, .hero3d *::after { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
  /* Nothing travels. The line simply changes, on the same cadence. */
  .hero3d .is-split .char { transform: none !important; }
  .hero3d .is-split .principle { opacity: 0; transition: opacity .4s ease !important; }
  .hero3d .is-split .principle.is-current { opacity: 1; }
}

/* ── Tokens and resets the standalone study gets from its own :root ── */
.hero3d { --hex: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); --cyan: #6bfced; --muted: #b8b7ae; color: var(--wax); }
.hero3d a { color: inherit; text-decoration: none; }
.hero3d button { font: inherit; color: inherit; cursor: pointer; }
.hero3d button, .hero3d a { -webkit-tap-highlight-color: transparent; }

/* ── Placement on the homepage ─────────────────────────────────── */
.hero.hero3d { position: relative; z-index: 2; min-height: 100vh; display: flex; align-items: center; padding: 96px 80px 48px; }
.hero3d .hero-shell { width: 100%; }
@media (max-width: 1100px) { .hero.hero3d { padding: 96px 40px 40px; } }
@media (max-width: 900px) { .hero.hero3d { min-height: auto; padding: 90px 24px 40px; } }

/* ── Fluid Field under the hero. The canvas is a child of <body>, placed over the
   hero's box by hero-field.js, behind the particle layer (z 1) and the hero (z 2),
   and screen-blended onto the page background so it only ever adds light. The masks
   decide where it shows; --fx/--fy/--fr are the honeycomb's centre and half-width. */
.field { position: absolute; z-index: 0; display: block; pointer-events: none; mix-blend-mode: screen; }
.field[data-field="baseline"] { display: none; }
/* 1. Under the honeycomb only: solid to 85% of its radius, gone by 135%. */
.field[data-field="localized"] { -webkit-mask-image: radial-gradient(circle at var(--fx) var(--fy), #000 calc(var(--fr) * .85), transparent calc(var(--fr) * 1.35)); mask-image: radial-gradient(circle at var(--fx) var(--fy), #000 calc(var(--fr) * .85), transparent calc(var(--fr) * 1.35)); }
/* 2. Farther out, still centred on the honeycomb: half strength by 1.3 radii, under
   a fifth by 1.9, which is past the headline's left edge, and nothing by 2.8. */
.field[data-field="expanded"] { -webkit-mask-image: radial-gradient(circle at var(--fx) var(--fy), #000 calc(var(--fr) * .9), rgba(0, 0, 0, .5) calc(var(--fr) * 1.3), rgba(0, 0, 0, .18) calc(var(--fr) * 1.9), transparent calc(var(--fr) * 2.8)); mask-image: radial-gradient(circle at var(--fx) var(--fy), #000 calc(var(--fr) * .9), rgba(0, 0, 0, .5) calc(var(--fr) * 1.3), rgba(0, 0, 0, .18) calc(var(--fr) * 1.9), transparent calc(var(--fr) * 2.8)); }
/* 3. The whole hero, feathered at the top and bottom so it has no edge. The one in use. */
.field[data-field="full"] { -webkit-mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent); mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent); }
.field-control { position: fixed; left: 16px; bottom: 16px; z-index: 50; display: flex; gap: 6px; padding: 6px; border-radius: 10px; background: rgba(7, 9, 12, .85); border: 1px solid #ffffff22; font: 600 12px/1 Inter, sans-serif; }
.field-control button { padding: 8px 10px; border-radius: 6px; border: 1px solid transparent; background: none; color: var(--muted); cursor: pointer; text-transform: capitalize; }
.field-control button[aria-pressed="true"] { color: var(--cyan); border-color: #6bfced55; background: #6bfced14; }
.field-control label { display: flex; align-items: center; gap: 8px; padding: 0 6px 0 10px; border-left: 1px solid #ffffff22; color: var(--muted); font-weight: 500; }
.field-control input { width: 110px; accent-color: var(--cyan); }
.field-control output { min-width: 3ch; color: var(--wax); font-variant-numeric: tabular-nums; }
