/* ============================================================================================
   AGENT SHOWCASE - scroll-choreographed section (index.html)
   --------------------------------------------------------------------------------------------
   DESIGN CONTRACT. Break any of these and the page regresses:

   1. THE STACKED LAYOUT IS THE DEFAULT. Without JS this renders as five ordinary cards -
      readable, crawlable, keyboard-navigable. JS adds .is-on for the pinned version. A crawler
      that never runs JS still gets every word, so this cannot cost us Iris score or traffic.

   2. NO TRANSFORM ON AN ANCESTOR OF A FIXED ELEMENT. A transform on an ancestor re-roots
      position:fixed descendants onto it. The scene transform is scoped inside .hoff-sticky,
      which contains no fixed element; the nav, to-top and tiQ bubble all live outside <main>.

   3. REDUCED MOTION WINS. The block at the bottom restores the stacked page outright.

   4. ONE ANIMATED TRANSFORM, on .hoff-scene. Everything else in the scroll path is opacity.
      All the "premium" here is STATIC paint - borders, gradients, type, shadow - which costs
      nothing per frame. Do not move the decoration; move the camera.
   ============================================================================================ */

.hoff{position:relative}
.hoff-sticky{position:relative}

/* ---- default / no-JS: five plain stacked cards ---- */
.hoff-panel{margin:0 0 18px}
/* THE HANDOVER FADE. Time-based on purpose - see the long note in nx-handoff.js. A scroll-linked
   crossfade always has a band of scroll positions showing two panels at once, and a person can
   stop in it. A CSS transition completes on its own wherever the scroll stops.
   visibility is delayed by the transition duration so the outgoing panel is still painted while
   it fades; without the delay it would vanish instantly and the fade would never be seen. */
.hoff.is-on .hoff-panel{opacity:0;visibility:hidden;
  transition:opacity .26s ease, visibility 0s linear .26s}
.hoff.is-on .hoff-panel.is-shown{opacity:1;visibility:visible;
  transition:opacity .26s ease, visibility 0s linear 0s}
.hoff-card{
  position:relative;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:30px 36px;display:grid;gap:14px;max-width:1180px;margin:0 auto;
}
.hoff-eyebrow{display:flex;align-items:center;gap:12px;font-family:var(--mono);font-size:11.5px;
  font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--muted-2)}
.hoff-eyebrow b{color:#DE6A1E;font-weight:700}
.hoff-eyebrow span{flex:1;height:1px;background:var(--line)}
.hoff-eyebrow{gap:12px}
.hoff-head{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.hoff-ava{width:66px;height:66px;flex:0 0 66px;display:grid;place-items:center;border-radius:22px;
  background:var(--panel-2);border:1px solid var(--line)}
.hoff-ava img{width:42px;height:42px}
.hoff-name{font-family:var(--display);font-size:clamp(32px,4.4vw,52px);line-height:1;letter-spacing:-.035em}
.hoff-role{font-size:15px;color:#DE6A1E;font-weight:600;margin-top:6px;letter-spacing:.01em}
.hoff-verb{font-family:var(--display);font-size:clamp(22px,2.6vw,34px);line-height:1.18;
  letter-spacing:-.02em;color:var(--text)}
.hoff-desc{color:var(--muted);font-size:16.5px;line-height:1.66;max-width:62ch}
.hoff-go{display:inline-flex;align-items:center;gap:9px;font-weight:600;font-size:14.5px;color:#DE6A1E;
  text-decoration:none;width:fit-content}
.hoff-go:hover{text-decoration:underline}
.hoff-tag{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--muted);
  background:var(--panel-2);border:1px solid var(--line);border-radius:100px;padding:5px 11px}
.hoff-tag i{width:7px;height:7px;border-radius:50%;background:#3FA46A;box-shadow:0 0 0 3px rgba(63,164,106,.18)}

/* ---- the step list ----------------------------------------------------------------------
   Vertical, not a horizontal strip. A strip of five columns gives each step ~116px, which is a
   ribbon of words, not an explanation. Vertical rows give the label room and let the DETAIL for
   the running step open beneath it.

   Only one detail is ever open, so the card height is bounded: all labels plus one paragraph.
   The open/close is a CLASS TOGGLE with a CSS transition, fired only when the active step
   changes - roughly 23 times across the whole section - never a per-frame style write. Layout
   animation is affordable at that rate and would not be at 60fps. */
.hoff-steps{list-style:none;display:grid;gap:2px;margin:2px 0 0;padding:0;counter-reset:none}
.hoff-bar{
  display:grid;grid-template-columns:26px 1fr;gap:0 12px;align-items:start;
  padding:10px 0 11px;border-top:1px solid var(--line);position:relative;
}
.hoff-bar:first-child{border-top:0}
.hoff-n{font-family:var(--mono);font-size:11.5px;font-weight:700;color:var(--muted-2);
  line-height:1.5;padding-top:2px;transition:color .3s ease}
.hoff-t b{display:block;font-size:16px;font-weight:600;color:var(--muted);letter-spacing:-.01em;
  transition:color .3s ease}
/* grid-template-rows 0fr -> 1fr animates to CONTENT height without guessing a max-height, and
   keeps the text in the DOM the whole time, which is what Iris and Googlebot need. */
.hoff-d{display:grid;grid-template-rows:0fr;transition:grid-template-rows .42s cubic-bezier(.2,.8,.2,1),opacity .3s ease;opacity:0}
.hoff-d>span{overflow:hidden;font-size:15px;line-height:1.62;color:var(--muted);
  display:block;padding-top:0;max-width:64ch}
.hoff-bar.is-cur .hoff-d{grid-template-rows:1fr;opacity:1}
.hoff-bar.is-cur .hoff-d>span{padding-top:7px}
.hoff-bar.is-cur .hoff-t b{color:var(--text)}
.hoff-bar.is-cur .hoff-n{color:#DE6A1E}
.hoff-bar.is-done .hoff-n{color:#3FA46A}
.hoff-bar.is-done .hoff-t b{color:var(--muted-2)}
/* the fill line sits on the row's own top border */
.hoff-bar i{position:absolute;left:0;top:-1px;height:1px;width:var(--fill,0%);background:var(--grad)}
.hoff-bar:first-child i{top:0}
@supports not (grid-template-rows:0fr){
  .hoff-d{display:block;max-height:0;overflow:hidden;transition:max-height .42s ease,opacity .3s ease}
  .hoff-bar.is-cur .hoff-d{max-height:180px}
}


/* ---- two-column body: steps on the left, the step's own glyph on the right ------------------
   The card was using 43% of a wide viewport while its text shrank to fit. Horizontal space is
   free here - height is the scarce resource - so the glyph pane costs nothing vertically. */
.hoff-body{display:grid;grid-template-columns:1fr;gap:18px;align-items:start}
@media(min-width:1040px){ .hoff-body{grid-template-columns:minmax(0,1fr) 330px;gap:34px} }
@media(min-width:1400px){ .hoff-body{grid-template-columns:minmax(0,1fr) 380px;gap:42px} }
.hoff-viz{position:relative;display:none;aspect-ratio:4/3;align-self:center}
.hoff-steps{align-self:start}
/* Scoped to .is-on AND to width. Specificity is deliberately higher than a bare
   .hoff-viz rule, so a later blanket display:none cannot silently win - which is exactly what
   happened the first time and left 23 glyphs in the DOM and invisible. */
@media(min-width:1040px){ .hoff.is-on .hoff-viz{display:block} }
/* PHONES AND TABLETS. The pane was desktop-only, so a phone got the choreography with no visuals
   at all - the parity gap. Here the glyph sits ABOVE the steps as a wide, short band: a 330px
   square column cannot share a 390px screen with readable text, but a 96px band can, and the
   zoom, assemble stagger and halo are identical to desktop. */
@media(max-width:1039px){
  .hoff.is-on .hoff-viz{display:block;aspect-ratio:auto;height:clamp(78px,13svh,112px);order:-1;margin-bottom:2px}
  .hoff.is-on .hoff-viz::before{border-radius:var(--r-sm)}
  .hoff.is-on .hoff-vz{inset:9% 30%}
  .hoff.is-on .hoff-viz::after{width:38%;margin:-19% 0 0 -19%}
  .hoff.is-on .hoff-body{gap:12px}
}
@media(max-width:520px){
  .hoff.is-on .hoff-viz{height:clamp(66px,11svh,88px)}
  .hoff.is-on .hoff-vz{inset:8% 26%}
}
.hoff-viz::before{
  content:'';position:absolute;inset:0;border-radius:var(--r-md);border:1px solid var(--line);
  background:radial-gradient(85% 70% at 50% 42%,rgba(222,106,30,.07),transparent 70%);
}
.hoff-vz{
  position:absolute;inset:14%;display:grid;place-items:center;
  /* ZOOM IN / ZOOM OUT, done with a CSS transition on a class - never a per-frame write. The
     driver already toggles is-cur when the step changes, so the browser interpolates this on the
     compositor and the scroll loop stays at exactly one transform. */
  opacity:0;transform:scale(.82);
  transition:opacity .45s ease,transform .55s cubic-bezier(.2,.9,.25,1);
}
.hoff-vz svg{width:100%;height:100%;color:var(--muted-2)}
.hoff-vz.is-cur{opacity:1;transform:scale(1)}
/* the step just finished pushes PAST the viewer rather than simply fading - the zoom-out half */
.hoff-vz.is-past{opacity:0;transform:scale(1.22)}


/* ---- making the glyphs feel alive ---------------------------------------------------------
   Static line art in a big pane reads as a placeholder. Three layers of motion fix that, and all
   three are pure CSS on the ACTIVE glyph only - the driver already toggles .is-cur, so this costs
   nothing per frame and nothing at all for the 22 glyphs that are not on screen.

   1. ASSEMBLE - children fade and rise in a short stagger, so the diagram builds itself rather
      than appearing. This is the "system doing work" read.
   2. BREATHE  - a very slow float on the whole glyph. Long period and tiny amplitude on purpose:
      enough that the pane is not dead, not enough to pull the eye off the text.
   3. PULSE    - a soft halo behind it, offset from the float so the two never beat together.
   No shake or vibration: it draws attention to itself rather than to the step, and on a diagram
   it reads as an error state. */
@keyframes hoffFloat{0%,100%{transform:translate3d(0,-4px,0)}50%{transform:translate3d(0,4px,0)}}
@keyframes hoffAssemble{from{opacity:0}to{opacity:1}}
@keyframes hoffHalo{0%,100%{opacity:.30;transform:scale(.94)}50%{opacity:.62;transform:scale(1.04)}}

.hoff-viz::after{
  content:'';position:absolute;left:50%;top:50%;width:62%;aspect-ratio:1;margin:-31% 0 0 -31%;
  border-radius:50%;pointer-events:none;opacity:0;
  background:radial-gradient(circle,rgba(222,106,30,.30),transparent 64%);
  transition:opacity .5s ease;
}
.hoff-panel.is-live .hoff-viz::after{opacity:1;animation:hoffHalo 9s ease-in-out infinite}
.hoff-vz.is-cur svg{animation:hoffFloat 8s ease-in-out infinite}
.hoff-vz.is-cur svg>*{animation:hoffAssemble .45s ease backwards}
.hoff-vz.is-cur svg>*:nth-child(1){animation-delay:.04s}
.hoff-vz.is-cur svg>*:nth-child(2){animation-delay:.10s}
.hoff-vz.is-cur svg>*:nth-child(3){animation-delay:.16s}
.hoff-vz.is-cur svg>*:nth-child(4){animation-delay:.22s}
.hoff-vz.is-cur svg>*:nth-child(5){animation-delay:.28s}
.hoff-vz.is-cur svg>*:nth-child(6){animation-delay:.34s}
.hoff-vz.is-cur svg>*:nth-child(n+7){animation-delay:.40s}

.hoff-rail,.hoff-scenebg,.hoff-chips{display:none}

/* ============================ choreographed mode (JS only) ============================ */
.hoff.is-on{height:320vh}
.hoff.is-on .hoff-sticky{
  /* 100svh, not 100vh: on mobile 100vh is the LARGEST viewport height, so the frame would
     exceed the screen while browser chrome is showing. */
  position:sticky;top:0;height:100svh;min-height:560px;overflow:hidden;display:block;
}
/* Static premium backdrop. Never animated - it is painted once and composited thereafter. */
.hoff.is-on .hoff-scenebg{
  display:block;position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(120% 80% at 50% 0%,rgba(240,168,92,.10),transparent 60%),
    radial-gradient(90% 70% at 50% 108%,rgba(222,106,30,.10),transparent 62%);
}
.hoff.is-on .hoff-scene{
  position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;
  padding:96px max(18px,3vw) 104px;
  /* THE one animated transform in the whole section. */
  transform-origin:50% 50%;will-change:transform;
}
.hoff.is-on .hoff-panel{
  /* inset:0, not left/right alone. Without top/bottom each panel took its STATIC position in the
     flex scene, so a 6-step card and a 3-step card sat at different heights and the content
     jumped vertically every time the panel changed. Filling the scene and centring inside it
     puts every card in the same place regardless of how many steps it has. */
  position:absolute;inset:0;margin:0;padding:0 max(18px,3vw);
  display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;
  contain:layout paint;
}
.hoff.is-on .hoff-panel.is-live{pointer-events:auto}
/* Panels that are not on screen must not spend anything. Two costs were measured on the section
   the user reported as rough:
   1. .hoff-d animates grid-template-rows - a LAYOUT property. Necessary for the accordion look on
      the visible panel, pure waste on the four hidden ones, which were still animating their rows
      every time the step index moved.
   2. The is-live halo and the viz SVG animations kept running inside panels at opacity 0.
   Hidden panels now have transitions cut and animations paused; the shown panel is untouched. */
.hoff.is-on .hoff-panel:not(.is-shown) .hoff-d{transition:none}
.hoff.is-on .hoff-panel:not(.is-shown) *{animation-play-state:paused}
.hoff.is-on .hoff-card{
  width:min(1180px,100%);
  /* Premium finish, all static: a hairline top highlight, a soft inner rim and one deep shadow.
     Three --glow layers at 46px blur were measurably worse for one more halo nobody asked for. */
  background:linear-gradient(180deg,color-mix(in srgb,var(--panel) 96%,#fff 4%),var(--panel));
  border:1px solid var(--line);
  box-shadow:0 1px 0 rgba(255,255,255,.05) inset,0 26px 70px rgba(0,0,0,.34);
}
@supports not (background:color-mix(in srgb,red 50%,#fff 4%)){
  .hoff.is-on .hoff-card{background:var(--panel)}
}
.hoff.is-on .hoff-card::before{
  /* Hairline gradient rule along the top edge - reads as machined rather than drawn. */
  content:'';position:absolute;left:34px;right:34px;top:-1px;height:1px;
  background:linear-gradient(90deg,transparent,rgba(222,106,30,.55),transparent);
}

/* ---- agent chips: queued -> working -> ready ---- */
.hoff.is-on .hoff-chips{
  display:flex;gap:8px;position:absolute;left:0;right:0;bottom:24px;z-index:5;
  justify-content:center;flex-wrap:wrap;padding:0 18px;
}
.hoff-chip{
  display:flex;align-items:center;gap:10px;padding:6px 12px 6px 7px;border-radius:12px;
  background:var(--panel);border:1px solid var(--line);cursor:pointer;text-align:left;
  transition:border-color .35s ease,background .35s ease,transform .35s ease;
}
/* will-change promotes the chip for the duration of the lift so its 1px border is rasterised
   once and moved by the GPU, rather than re-snapped to device pixels every frame. See the long
   note at the end of nx-2.css. */
.hoff-chip:hover{transform:translateY(-2px)}
@media (hover:hover) and (pointer:fine){ .hoff-chip:hover{will-change:transform} }
.hoff-chip:focus-visible{outline:2px solid #DE6A1E;outline-offset:3px}
.hoff-chip.is-active{border-color:rgba(222,106,30,.45);background:var(--panel-2)}
.hoff-chip.is-done{border-color:rgba(63,164,106,.34)}
.hoff-ring{position:relative;width:26px;height:26px;flex:0 0 26px}
.hoff-ring svg{width:26px;height:26px;transform:rotate(-90deg)}
.hoff-ring [data-glyph]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:700;color:var(--muted-2);font-family:var(--mono)}
.hoff-chip.is-active [data-glyph]{color:#DE6A1E}
.hoff-chip.is-done [data-glyph]{color:#3FA46A}
.hoff-chip b{display:block;font-size:12.5px;font-weight:700;color:var(--text);letter-spacing:-.01em}
.hoff-chip [data-status]{display:block;font-size:10.5px;color:var(--muted-2);font-family:var(--mono)}

.hoff.is-on .hoff-rail{
  display:block;position:absolute;left:0;top:0;height:2px;z-index:5;
  width:calc(var(--p,0) * 100%);background:var(--grad);
}
@media(max-width:900px){
  .hoff.is-on .hoff-scene{padding:100px 18px 150px}
  .hoff.is-on .hoff-card{padding:28px 22px}
  .hoff-chip b{font-size:11.5px}
  .hoff-chip [data-status]{display:none}
}
@media(max-width:430px){
  /* 320-430px: iPhone SE through Pro Max. Type steps down rather than letting rows wrap to three
     lines, which is what pushes a six-step card past the frame on a short phone. */
  .hoff.is-on .hoff-card{padding:18px 16px;border-radius:var(--r-md)}
  .hoff-name{font-size:clamp(26px,8vw,34px)}
  .hoff-verb{font-size:clamp(16px,4.6vw,20px)}
  .hoff-t b{font-size:13.5px}
  .hoff-d>span{font-size:12.5px;line-height:1.5}
  .hoff-bar{grid-template-columns:19px 1fr;gap:0 8px;padding:6px 0 7px}
  .hoff-eyebrow{font-size:10px;letter-spacing:.14em}
  .hoff-chip b{font-size:11px}
  .hoff.is-on .hoff-scene{padding:88px 12px 74px}
}
@media(max-width:560px){
  .hoff.is-on{height:300vh}
  .hoff-ava{width:58px;height:58px;flex:0 0 58px}
  .hoff-ava img{width:38px;height:38px}
  .hoff-bar{grid-template-columns:22px 1fr;gap:0 9px;padding:8px 0 9px}
  .hoff-t b{font-size:13px}
  .hoff-d>span{font-size:12.5px}
  .hoff.is-on .hoff-chips{gap:6px;bottom:22px}
  .hoff-chip{padding:6px 10px 6px 7px}
}

/* SHORT WINDOWS. A six-step card needs ~540px; a 700px-tall browser window leaves ~500px after
   the nav clearance and the chip bar. Rather than clip the last step, compact at these heights. */
@media(max-height:820px){
  .hoff-t b{font-size:14.5px}
  .hoff-bar{padding:7px 0 8px}
  .hoff.is-on .hoff-scene{padding:98px max(18px,3vw) 92px}
  .hoff.is-on .hoff-card{padding:22px 26px;gap:10px}
  .hoff-name{font-size:clamp(28px,3.6vw,40px)}
  .hoff-verb{font-size:clamp(17px,2vw,22px)}
  .hoff-ava{width:54px;height:54px;flex:0 0 54px}
  .hoff-ava img{width:34px;height:34px}
  .hoff-bar{padding:5px 0 6px}
  .hoff-d>span{font-size:13.5px;line-height:1.55}
}
@media(max-height:660px){
  .hoff.is-on .hoff-scene{padding:94px max(18px,3vw) 76px}
  .hoff-eyebrow,.hoff-tag{display:none}
  .hoff-bar{padding:4px 0 5px}
  .hoff-chip [data-status]{display:none}
}


/* HEIGHT, not just width, decides whether the glyph band fits. An iPhone SE (568px tall) and an
   iPad in landscape (768px) both have room for the steps or the band, not both - and on a page
   whose job is explaining, the words win. Six steps plus an open detail need roughly 480px;
   below that the band is the first thing to go. 820px catches an iPad in landscape (1024x768), which
   was the last configuration still clipping. */
/* Short screens: hide the glyph ONLY where it is the STACKED BAND (below 1040px), because that
   is the layout where it costs vertical height. At 1040px and up the glyph is a SIDE COLUMN and
   costs no height at all, so hiding it there was simply wrong - it stripped the visual from a
   1280x720 laptop, one of the most common desktop sizes there is, and left dead space behind.
   Hiding a grid child also does not reclaim its track, hence the second line. */
@media(max-height:820px) and (max-width:1039px){
  .hoff.is-on .hoff-viz{display:none}
  .hoff.is-on .hoff-body{grid-template-columns:minmax(0,1fr)!important}
}
@media(max-width:560px){
  .hoff.is-on .hoff-card{padding:16px 14px}
  .hoff-bar{padding:5px 0 6px}
  .hoff-t b{font-size:13px}
}
@media(max-width:360px){
  /* 320-360px. Every row must stay one line; two-line labels are what tips a six-step card over. */
  .hoff.is-on .hoff-scene{padding:84px 10px 68px}
  .hoff.is-on .hoff-card{padding:14px 12px}
  .hoff-name{font-size:26px}
  .hoff-verb{font-size:16px}
  .hoff-t b{font-size:12.5px;letter-spacing:-.015em}
  .hoff-d>span{font-size:12px;line-height:1.45}
  .hoff-bar{padding:4px 0 5px;grid-template-columns:17px 1fr;gap:0 7px}
  .hoff-ava{width:46px;height:46px;flex:0 0 46px}
  .hoff-ava img{width:30px;height:30px}
  .hoff-eyebrow,.hoff-tag{display:none}
  .hoff.is-on .hoff-chips{bottom:14px;gap:5px}
  .hoff-chip{padding:5px 8px 5px 6px}
  .hoff-chip b{font-size:10.5px}
}

/* ============================ accessibility overrides ============================
   Last on purpose. Someone who asked their OS for less motion gets the plain stacked page. */
@media(prefers-reduced-motion:reduce){
  .hoff.is-on{height:auto!important}
  .hoff.is-on .hoff-panel{opacity:1!important;visibility:visible!important;transition:none!important}
  .hoff.is-on .hoff-sticky{position:relative;height:auto;min-height:0;display:block;overflow:visible}
  .hoff.is-on .hoff-scene{position:relative;inset:auto;display:block;padding:0;transform:none!important;will-change:auto}
  .hoff.is-on .hoff-panel{
    position:relative;inset:auto;opacity:1!important;transform:none!important;
    pointer-events:auto;margin:0 0 18px;padding:0;visibility:visible!important;display:block;
  }
  .hoff.is-on .hoff-card{opacity:1!important;transform:none!important;filter:none!important;will-change:auto}
  .hoff.is-on .hoff-scenebg,.hoff.is-on .hoff-chips,.hoff.is-on .hoff-rail{display:none}
  .hoff-viz{display:none!important}
  .hoff-body{grid-template-columns:minmax(0,1fr)!important}   /* collapse the track too */
  .hoff-bar i{width:100%!important}
  .hoff-d{grid-template-rows:1fr!important;max-height:none!important;opacity:1!important}
  .hoff-d>span{padding-top:7px}
  .hoff-chip{transition:none}
  .hoff-vz.is-cur svg,.hoff-vz.is-cur svg>*,.hoff-panel.is-live .hoff-viz::after{animation:none!important}
}
