/* ══════════════════════════════════════════════════════════════════
   /platform/accessibility — page-specific styles (.p-capability--accessibility)
   on top of the shared capability.css.

   § axh · the hero morph phone (Arturo 2026-08-09, taipei). The hero
   splits copy | visual (the wfbh-hero precedent) and the visual is the
   REAL face-capture screen (Selfie3Screen, the vector twin of selfie-3
   the home/use-case phones wear) re-rendering itself under different
   user settings — the page promise ("one flow that adapts") as motion:

     state .is-a   Default — the capture screen as shipped, wearing
                   the LIVE caption (.axh-livecap — plain-language
                   copy over the hidden baked paths, 2026-08-10
                   feedback issues 1-2)
     state .is-b   Larger text — the live caption scales up;
                   transform-only, no reflow (labelled "Larger
                   text", NOT "200%": the render is 1.3× —
                   truthfulness rule, 2026-08-09)
     state .is-c   Screen reader on — the spoken cue lands as a
                   visible caption toast (types itself) and the focus
                   ring lands on the screen's own caption line
                   (labelled "Screen reader", NOT "VoiceOver" — only
                   claim tools we've tested per module/version)
     state .is-d   No gestures needed — the screen's OWN dormant
                   layers wake: the blue scan ring sweeps and the
                   "Get ready…" caption crossfades in — capture
                   progresses while the user only looks (passive
                   liveness, the differentiator)

   Morph grammar borrowed from the how-it-works .wfh card next door on
   workflow-builder: 0.45s cubic-bezier(0.23,1,0.32,1) morphs, 0.2s out
   / 0.35s (+0.05s) in fades. State classes set by
   /js/behaviors/accessibility-hero.js (runs only in view, ~10.4s
   loop). No JS → .is-a paints. Reduced motion → the composed
   VoiceOver frame, no cycling (media block backup below mirrors what
   the JS sets via .is-still). Phone chrome + skeleton status bar
   mirror solution.css § sol-stage__frame / sol-skelbar (the baked
   .s3-status is hidden, per the site-wide 2026-08-07 retirement).
   ══════════════════════════════════════════════════════════════════ */

/* --- split the family hero: copy left · visual right (≥1024) --- */
.p-capability--accessibility .axh-hero { display: grid; gap: 40px; align-items: center; }
.p-capability--accessibility .axh-copy { min-width: 0; }
.p-capability--accessibility .axh {
  width: 100%;
  max-width: 340px;
  margin-top: 8px;
  justify-self: center;
  /* proportional step-down into the shared /platform/ visual band —
     the phone is fixed-px inside, so the scale is the honest lever —
     stepped to fit the canon 444px box floor (Sofia 2026-08-17) */
  zoom: 0.75;
}
@media (min-width: 1024px) {
  .p-capability--accessibility .axh-hero {
    /* 1.1/0.9 holds the h1's 2-line gate at 1280 (the tightest column —
       see the comment below); the family 1.04/0.96 the canon 500px box
       wants takes over at 1440 where the title has room either way */
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: 48px;
  }
}
@media (min-width: 1440px) {
  .p-capability--accessibility .axh-hero {
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
  }
  /* The copy column narrows beside the visual, so the 24ch clamp comes off
     and the title takes the column. It KEEPS the family 56px: the size
     step-down that used to live here (40px @1024 / 44px @1440, copied from
     the workflow-builder split) was retired 2026-08-10 — the h1 was
     shortened instead, so every /platform/ page shares one scale
     (36 / 48 / 56 from capability.css).
     Retitling? Re-measure: the h1 must hold 2 lines at 1024, 1280 AND 1440.
     1280 is the tightest gate (480px column) and the limit is rendered
     width, not character count. */
  .p-capability--accessibility .axh-copy .cap-hero__title { max-width: 100%; }
  .p-capability--accessibility .axh-copy .cap-hero__sub { max-width: 100%; }
  .p-capability--accessibility .axh {
    max-width: 340px;
    margin-top: 0;
    /* centered in its column, not pinned to the stage edge — the narrow
       phone strands against the right otherwise (Sofia 2026-08-17) */
    justify-self: center;
  }
}

/* --- standards chips under the hero actions (claims-safe wording) --- */
.p-capability--accessibility .axh-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 20px;
}
.p-capability--accessibility .axh-chip {
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--color-background);
  border: 1px solid var(--color-border-light);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-grey-500);
  white-space: nowrap;
}

/* --- the phone (house bezel: solution.css sol-stage__frame recipe) --- */
.p-capability--accessibility .axh-phone {
  position: relative;
  width: 264px;
  margin-inline: auto;
  padding: 9px;
  border-radius: 42px;
  border: 1px solid var(--color-grey-100);
  background: var(--color-white);
  transition: border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1),
    box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1);
}
.p-capability--accessibility .axh.is-b .axh-phone,
.p-capability--accessibility .axh.is-c .axh-phone {
  border-color: var(--color-blue-200);
  box-shadow: none; /* hard shadow, site rule */
}
.p-capability--accessibility .axh-screen {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 34px;
}

/* the baked iOS status bar retires; the frame wears the skeleton pills
   (geometry copied from solution.css § sol-skelbar) */
.p-capability--accessibility .axh .s3-status { display: none; }

/* the screen's dormant capture-progress layers — parked until .is-d */
.p-capability--accessibility .axh .s3-caption-ready,
.p-capability--accessibility .axh .s3-ring-scan {
  opacity: 0;
  transition: opacity 0.2s ease;
}
.p-capability--accessibility .axh-skelbar {
  position: absolute;
  inset: 9px 9px auto;
  z-index: 2;
  aspect-ratio: 390 / 844;
  pointer-events: none;
}
.p-capability--accessibility .axh-skelbar i {
  position: absolute;
  top: 3.04%;
  height: 1.43%;
  border-radius: 999px;
  background: var(--color-grey-200);
}
.p-capability--accessibility .axh-skelbar i:nth-child(1) { left: 8.53%; width: 10.85%; }
.p-capability--accessibility .axh-skelbar i:nth-child(2) {
  left: 78.3%;
  width: 3.1%;
  height: auto;
  aspect-ratio: 1;
  border-radius: 50%;
}
.p-capability--accessibility .axh-skelbar i:nth-child(3) { left: 83.72%; width: 7.75%; }

/* --- the live caption (2026-08-10 feedback, issues 1-2) ---
   the screen's baked caption ("Align your face within the silhouette…",
   outlined vector paths — jargon, uneditable, unlocalizable) is hidden
   on BOTH of this page's instances and replaced by .axh-livecap: live
   HTML text laid over the screen's caption band, plain-language copy in
   two bite-size sentences. The component itself is untouched — every
   other page still wears the product-verbatim paths. */
.p-capability--accessibility .s3-caption { display: none; }
.p-capability--accessibility .axh-livecap {
  position: absolute;
  left: 9px;
  right: 9px;
  top: 60.5%;
  z-index: 1;
  margin: 0;
  padding: 0 26px;
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--color-rich-black);
  pointer-events: none;
}

/* --- state .is-b · Larger text ---
   the live caption scales around its center — transform-only, no
   reflow. 1.3 keeps the block inside the screen edges — hence the chip
   says "Larger text", never "200%" */
.p-capability--accessibility .axh .axh-livecap {
  transform-origin: center;
  transition: transform 0.45s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.2s ease;
}
.p-capability--accessibility .axh.is-b .axh-livecap { transform: scale(1.3); }

/* --- state .is-c · With VoiceOver ---
   the focus ring lands on the screen's caption line (zero-blur rings
   only); positioned over the SVG's caption band (y ≈ 515-545 / 844) */
.p-capability--accessibility .axh-focus {
  position: absolute;
  left: 7%;
  right: 7%;
  top: 51.5%;
  height: 21%;
  border-radius: 14px;
  border: 3px solid var(--color-rich-black);
  box-shadow: 0 0 0 2px var(--color-white), inset 0 0 0 2px var(--color-white);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.p-capability--accessibility .axh.is-c .axh-focus {
  opacity: 1;
  transition: opacity 0.35s ease 0.05s;
}

/* the spoken cue as a visible caption toast, overlaid at the phone
   foot — transform+opacity only (it overlays; nothing reflows) */
.p-capability--accessibility .axh-caption {
  position: absolute;
  left: 22px;
  right: 22px;
  bottom: 26px;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--color-blue-100);
  border: 1px solid var(--color-blue-200);
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.p-capability--accessibility .axh.is-c .axh-caption--sr {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.35s ease 0.05s,
    transform 0.45s cubic-bezier(0.23, 1, 0.32, 1) 0.05s;
}

/* --- state .is-d · No gestures needed ---
   the real capture-progress layers wake: the live caption crossfades
   to "Get ready…" and the gradient scan ring sweeps (constant motion →
   linear is correct); capture advances with zero user gestures */
.p-capability--accessibility .axh.is-d .axh-livecap { opacity: 0; }
.p-capability--accessibility .axh.is-d .s3-caption-ready {
  opacity: 1;
  transition: opacity 0.35s ease 0.05s;
}
.p-capability--accessibility .axh.is-d .s3-ring-scan {
  opacity: 1;
  transform-box: fill-box;
  transform-origin: center;
  animation: axh-scan-spin 2.4s linear infinite;
  transition: opacity 0.35s ease 0.05s;
}
@keyframes axh-scan-spin {
  to { transform: rotate(360deg); }
}
.p-capability--accessibility .axh-caption svg {
  flex-shrink: 0;
  stroke: var(--color-blue-500);
}
.p-capability--accessibility .axh-caption__txt {
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: var(--leading-snug);
  color: var(--color-rich-black);
  min-height: 1.5em; /* holds the row while the JS types */
}

/* --- the floating setting chips (the state indicator) ---
   dim while parked; the active one lights up as its setting turns on
   and the screen morphs in sync — cause, then effect */
.p-capability--accessibility .axh { position: relative; }
.p-capability--accessibility .axh-chipfloat {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: 999px;
  background: var(--color-white);
  border: 1px solid var(--color-grey-100);
  box-shadow: none; /* hard shadow, site rule */
  opacity: 0.45;
  transform: scale(0.96);
  pointer-events: none;
  transition: opacity 0.35s ease, transform 0.45s cubic-bezier(0.23, 1, 0.32, 1),
    border-color 0.35s ease, box-shadow 0.35s ease;
}
.p-capability--accessibility .axh-chipfloat--b { left: -14px; top: 27%; }
.p-capability--accessibility .axh-chipfloat--c { right: -14px; top: 47%; }
.p-capability--accessibility .axh-chipfloat--d { left: -14px; top: 73%; }
.p-capability--accessibility .axh-chipfloat__glyph {
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--color-blue-500);
}
.p-capability--accessibility .axh-chipfloat svg { stroke: var(--color-blue-500); flex-shrink: 0; }
.p-capability--accessibility .axh-chipfloat__lbl {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-rich-black);
  white-space: nowrap;
}
.p-capability--accessibility .axh.is-b .axh-chipfloat--b,
.p-capability--accessibility .axh.is-c .axh-chipfloat--c,
.p-capability--accessibility .axh.is-d .axh-chipfloat--d {
  opacity: 1;
  transform: scale(1);
  border-color: var(--color-blue-200);
  box-shadow: none;
}

/* --- reduced motion: the composed VoiceOver frame, no cycling ---
   (backup for the JS .is-still path — mirrors .is-c composed) */
@media (prefers-reduced-motion: reduce) {
  .p-capability--accessibility .axh-phone,
  .p-capability--accessibility .axh .axh-livecap,
  .p-capability--accessibility .axh .s3-caption-ready,
  .p-capability--accessibility .axh .s3-ring-scan,
  .p-capability--accessibility .axh-focus,
  .p-capability--accessibility .axh-caption,
  .p-capability--accessibility .axh-chipfloat {
    transition: none;
    animation: none;
  }
  .p-capability--accessibility .axh .axh-focus { opacity: 1; }
  .p-capability--accessibility .axh .axh-caption--sr {
    opacity: 1;
    transform: none;
  }
  .p-capability--accessibility .axh .axh-chipfloat--c {
    opacity: 1;
    transform: none;
    border-color: var(--color-blue-200);
    box-shadow: none;
  }
}

/* ══════════════════════════════════════════════════════════════════
   § axw · How it works — the morphing session stage (Arturo
   2026-08-09, Paper direction "How B · One session, three moments",
   file 01KZMD9VT8K4RFFKMF8EZGCT5J). The wfh/at-how morph mechanic,
   but with ONE persistent phone: the hero's Selfie3Screen worn a
   second time (uid axw), progressing through one verification
   session while a side companion narrates each step —

     state .is-s0  Guided — the real capture screen; beside it the
                   SAME instruction as a spoken cue plus an announced
                   status row (see, hear, understand: one message,
                   every channel)
     state .is-s1  Hands-free — the screen's own dormant capture
                   layers wake (scan ring + "Get ready…", the axh
                   .is-d recipe); the companion lists what is NOT
                   asked, struck through, then the passive check
     state .is-s2  A path forward — the REAL result screen
                   (FaceNotAlignedScreen, the canonical "Face not
                   aligned" error) crossfades over the capture screen
                   and its anatomy staggers in: badge pops,
                   heading/fix-it/attempts/Try-again rise; the
                   companion offers the alternative path last
     state .is-s3  Robust (the 2026-08-10 POUR re-lens, issue 8) —
                   the phone re-dresses as its own markup: a dark
                   sheet fills the screen with the semantic structure
                   a screen reader reads (aria-label, live region,
                   described-by; the cue line mirrors the live
                   caption), lines cascading in; the companion shows
                   the tested-with AT and aligned-with standards

   Morph grammar (site-wide): 0.45s cubic-bezier(0.23,1,0.32,1)
   morphs, 0.2s-out / 0.35s(+0.05s)-in fades. Inner one-shots replay
   per activation, keyed to the state class: entrances ease-out-cubic
   cubic-bezier(0.215,0.61,0.355,1), strikes ease-out-quad, the check
   pops with overshoot cubic-bezier(0,0.75,0.25,1); the scan ring is
   constant motion → linear (animations.dev blueprint). State classes
   set by /js/behaviors/accessibility-how.js (scroll-walk ≥1024,
   click + 6s auto-advance fallback). No JS → .is-s0 paints baked.
   Reduced motion → static composed frames, states still clickable.
   ══════════════════════════════════════════════════════════════════ */

/* --- jump-free rail (the wfh/at-how override): every description
   opens to the same measured height (--axw-reveal-h, tallest line,
   set by JS) so a collapse+expand pair cancels and the title holds */
.p-axw .sol-how__reveal {
  display: block;
  height: 0;
  overflow: hidden;
  transition: height 0.45s cubic-bezier(0.23, 1, 0.32, 1);
}
.p-axw .sol-how__step.is-active .sol-how__reveal {
  height: var(--axw-reveal-h, 78px);
}
.p-axw .sol-how__line { padding-top: 10px; }
/* float mode: solution.css's fixed 78px assumes the solution pages'
   lines — ours vary; the measured var wins (this sheet loads after
   solution.css, doubled scope keeps the tie unambiguous) */
.p-solution.p-axw .sol-flow-wrap.is-float .sol-how__step.is-active .sol-how__reveal {
  height: var(--axw-reveal-h, 78px);
}
/* seat: the pin centers this walk; the stage seats at true 0 (the
   data-sol-standalone opt-out already skips the traveler guards) */
.p-axw .sol-flow-wrap.is-float .sol-how__stage.is-revealed {
  opacity: 1;
  transform: none;
}

/* --- the stage: phone + companion side by side, centered --- */
.p-axw .axw { display: flex; justify-content: center; }
.p-axw .axw__duo {
  display: flex;
  align-items: center;
  gap: 20px;
}
/* the persistent phone (house bezel via .axh-phone) — narrower than
   the hero's 264px so the companion breathes beside it */
.p-axw .axw__phone {
  width: 228px;
  margin-inline: 0;
  flex-shrink: 0;
}
/* this instance never lights the hero's setting-chip border states */
.p-axw .s3-status { display: none; }
/* the live caption on the narrower walk phone (228px vs the hero's
   264px) steps its type down to hold the same optical size */
.p-axw .axw__phone .axh-livecap {
  padding: 0 20px;
  font-size: 13px;
  transition: opacity 0.2s ease;
}
/* solution.css parks the dormant layers with display:none for its own
   decks (.p-solution .s3-*) — this section lives inside .p-solution,
   so restore paint here and park them on opacity instead (this sheet
   loads after solution.css; the hero's .axh copy never needed this) */
.p-axw .s3-caption-ready,
.p-axw .s3-ring-scan {
  display: inline;
  opacity: 0;
  transition: opacity 0.2s ease;
}

/* --- state .is-s1 · hands-free: the real capture-progress layers
   wake (the axh .is-d recipe, shared keyframes) --- */
.p-axw .axw.is-s1 .axh-livecap { opacity: 0; }
.p-axw .axw.is-s1 .s3-caption-ready {
  opacity: 1;
  transition: opacity 0.35s ease 0.05s;
}
.p-axw .axw.is-s1 .s3-ring-scan {
  opacity: 1;
  transform-box: fill-box;
  transform-origin: center;
  animation: axh-scan-spin 2.4s linear infinite;
  transition: opacity 0.35s ease 0.05s;
}

/* --- state .is-s2 · the recovery beat: the REAL result screen ---
   FaceNotAlignedScreen (the canonical "Face not aligned" error, live
   HTML text — only the Status icon is SVG) crossfades over the
   capture screen inside the same bezel — what the product actually
   does. The band is vertically inset past the wordmark and above the
   verified footer, so the capture screen's own chrome shows through —
   the same chrome the real result screen renders. Its anatomy then
   tells the WALK line in order: what happened (badge + heading), what
   to try (the fix-it line), the path (Try again) — staggered
   one-shots, transform+opacity only. Geometry: phone 228px → screen
   210x454 at (9,9); wordmark ends ~y58, verified footer starts ~y430;
   the band spans y62-428 and the real screen's cluster/actions split
   maps to flex + margin-top:auto. */
.p-axw .axw__error {
  /* un-hides the markup's inline display:none (the !important beats
     the inline style — the hidden ATTRIBUTE can't be used, its UA
     style is display:none !important per the current HTML spec) — the
     band paints ONLY once these overlay rules are in force, so a
     stale cached stylesheet degrades to no-error-state instead of an
     in-flow content block (cache-skew bug, 2026-08-10) */
  display: flex !important;
  position: absolute;
  left: 9px;
  right: 9px;
  top: 62px;
  bottom: 42px;
  z-index: 2;
  flex-direction: column;
  align-items: center;
  /* the real screen seats the badge at ~32% of the screen (y149 at
     this scale) — 78px into the band */
  padding: 78px 16px 10px;
  text-align: center;
  background: var(--color-white);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.p-axw .axw.is-s2 .axw__error {
  opacity: 1;
  transition: opacity 0.35s ease 0.05s;
}
.p-axw .axw__error .fe-badge {
  width: 16px;
  height: 16px;
}
.p-axw .axw__error .fe-heading {
  margin: 10px 0 0;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: var(--leading-snug);
  color: var(--color-rich-black);
}
.p-axw .axw__error .fe-sub {
  margin: 5px 0 0;
  max-width: 190px; /* two wrapped lines, like the real screen */
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: var(--leading-snug);
  color: var(--color-grey-500);
}
.p-axw .axw__error .fe-attempts {
  margin: auto 0 12px; /* the actions cluster seats low, like the real
                          screen */
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-grey-500);
}
.p-axw .axw__error .fe-btn {
  display: block;
  width: 100%;
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--color-blue-500);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-white);
}
.p-axw .axw.is-s2 .fe-badge { animation: axw-pop 0.45s cubic-bezier(0, 0.75, 0.25, 1) 0.2s both; }
.p-axw .axw.is-s2 .fe-heading { animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.35s both; }
.p-axw .axw.is-s2 .fe-sub { animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.45s both; }
.p-axw .axw.is-s2 .fe-attempts { animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.6s both; }
.p-axw .axw.is-s2 .fe-btn { animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.7s both; }

/* --- the companion deck: one narration per step, crossfading in
   place (transparent stack — the stage wash is the background) --- */
.p-axw .axw__side {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
  width: 212px;
  flex-shrink: 0;
}
.p-axw .axw__co {
  grid-area: 1 / 1;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.p-axw .axw__co.is-active {
  opacity: 1;
  transition: opacity 0.35s ease 0.05s;
}

/* 01 · guided — the spoken cue (the screen's caption, heard) over the
   announced status row */
.p-axw .axw__cue {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--color-blue-100);
  border: 1px solid var(--color-blue-200);
}
.p-axw .axw__cue svg {
  flex-shrink: 0;
  margin-top: 2px;
  stroke: var(--color-blue-500);
}
.p-axw .axw__cue-txt {
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: var(--leading-snug);
  color: var(--color-rich-black);
}
.p-axw .axw__status {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 9px 14px;
  border-radius: 999px;
  background: var(--color-white);
  border: 1px solid var(--color-grey-100);
  box-shadow: none; /* hard shadow, site rule */
}
.p-axw .axw__status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-blue-500);
  animation: axw-pulse 2s ease-in-out infinite;
}
.p-axw .axw__status-lbl {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-grey-400);
}
.p-axw .axw__status-pill {
  margin-left: auto;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-grey-100);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-grey-500);
}
@keyframes axw-pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}
/* the cue and status enter as a pair on activation — same easing,
   short stagger (rows cascade, never block) */
.p-axw .axw.is-s0 .axw__cue {
  animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.1s both;
}
.p-axw .axw.is-s0 .axw__status {
  animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.22s both;
}
@keyframes axw-rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* 02 · hands-free — what the flow does NOT ask, struck one by one,
   then the passive check pops */
.p-axw .axw__not {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--color-white);
  border: 1px solid var(--color-grey-100);
  box-shadow: none; /* hard shadow, site rule */
}
.p-axw .axw__not-h {
  margin: 0 0 2px;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-grey-400);
}
.p-axw .axw__not-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-grey-400);
}
.p-axw .axw__not-x {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--color-grey-100);
  color: var(--color-grey-400);
}
/* the strike draws itself (a scaleX overlay — <s> keeps the
   semantics, the pseudo carries the motion) */
.p-axw .axw__not-row s {
  position: relative;
  text-decoration: none;
}
.p-axw .axw__not-row s::after {
  content: "";
  position: absolute;
  left: -1px;
  right: -1px;
  top: 50%;
  height: 1.5px;
  background: var(--color-grey-400);
  transform: scaleX(0);
  transform-origin: left center;
}
.p-axw .axw__not-row--yes {
  margin-top: 3px;
  padding-top: 11px;
  border-top: 1px solid var(--color-grey-100);
  font-weight: 600;
  color: var(--color-rich-black);
}
.p-axw .axw__not-check {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--color-blue-100);
  color: var(--color-blue-500);
}
.p-axw .axw__not-check svg,
.p-axw .axw__not-check img {
  width: 11px;
  height: 11px;
}
/* the one-shot: rows cascade in, strikes chase them, the check lands
   last with a small overshoot — settled well inside the 6s hold */
.p-axw .axw.is-s1 .axw__not-row:nth-of-type(1) { animation: axw-rise 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0.15s both; }
.p-axw .axw.is-s1 .axw__not-row:nth-of-type(2) { animation: axw-rise 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0.27s both; }
.p-axw .axw.is-s1 .axw__not-row:nth-of-type(3) { animation: axw-rise 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0.39s both; }
.p-axw .axw.is-s1 .axw__not-row:nth-of-type(1) s::after { animation: axw-strike 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.55s both; }
.p-axw .axw.is-s1 .axw__not-row:nth-of-type(2) s::after { animation: axw-strike 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.67s both; }
.p-axw .axw.is-s1 .axw__not-row:nth-of-type(3) s::after { animation: axw-strike 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.79s both; }
.p-axw .axw.is-s1 .axw__not-row--yes { animation: axw-pop 0.45s cubic-bezier(0, 0.75, 0.25, 1) 1.05s both; }
@keyframes axw-strike {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
@keyframes axw-pop {
  0% { opacity: 0; transform: scale(0.94); }
  60% { transform: scale(1.02); }
  100% { opacity: 1; transform: none; }
}

/* --- state .is-s3 · Robust: the markup behind the screen ---
   (2026-08-10 feedback, issue 8) the phone re-dresses one last time:
   a dark markup sheet fills the screen — the semantic structure a
   screen reader actually reads (aria-label, the live region, the
   described-by wiring; the cue line mirrors the live caption). Same
   bezel, same surface; lines cascade in like the error anatomy. */
.p-axw .axw__code {
  position: absolute;
  inset: 9px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  justify-content: center; /* the sheet reads as one centered block */
  border-radius: 34px;
  background: var(--color-rich-black);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.p-axw .axw.is-s3 .axw__code {
  opacity: 1;
  transition: opacity 0.35s ease 0.05s;
}
.p-axw .axw.is-s3 .axh-livecap { opacity: 0; }
.p-axw .axw__code-bar {
  margin: 0;
  padding: 0 22px 12px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-grey-400);
}
.p-axw .axw__code-pre {
  margin: 0;
  padding: 0 22px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 10.5px;
  line-height: 1.9;
  color: var(--color-grey-200);
  white-space: pre;
  overflow: hidden;
}
.p-axw .axw__code-ln { display: block; }
/* the cascade: each line rises on activation (the fe-anatomy grammar,
   compressed stagger so 12 lines settle inside ~1.3s) */
.p-axw .axw.is-s3 .axw__code-ln { animation: axw-rise 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) both; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(1) { animation-delay: 0.2s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(2) { animation-delay: 0.28s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(3) { animation-delay: 0.36s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(4) { animation-delay: 0.44s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(5) { animation-delay: 0.52s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(6) { animation-delay: 0.6s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(7) { animation-delay: 0.68s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(8) { animation-delay: 0.76s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(9) { animation-delay: 0.84s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(10) { animation-delay: 0.92s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(11) { animation-delay: 1s; }
.p-axw .axw.is-s3 .axw__code-ln:nth-child(12) { animation-delay: 1.08s; }

/* 03 · a path forward — the alternative beside the recovery sheet */
.p-axw .axw__alt {
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--color-blue-100);
  border: 1px solid var(--color-blue-200);
}
.p-axw .axw__alt-eyebrow {
  margin: 0 0 4px;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-blue-500);
}
.p-axw .axw__alt-line {
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: var(--leading-snug);
  color: var(--color-rich-black);
}
/* enters once the result screen's story has told what happened —
   cause, then the way out */
.p-axw .axw.is-s2 .axw__alt {
  animation: axw-rise 0.35s cubic-bezier(0.215, 0.61, 0.355, 1) 0.85s both;
}

/* 04 · Robust — the evidence beside the markup: the AT it's tested
   with, the standards it aligns with (chips, claims-safe wording) */
.p-axw .axw__proof {
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--color-white);
  border: 1px solid var(--color-grey-100);
  box-shadow: none; /* hard shadow, site rule */
}
.p-axw .axw__proof-h {
  margin: 0 0 8px;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-grey-400);
}
.p-axw .axw__proof-h--gap { margin-top: 14px; }
.p-axw .axw__proof-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.p-axw .axw__proof-chip {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--color-grey-100);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-grey-500);
  white-space: nowrap;
}
.p-axw .axw__proof-chip--std {
  background: var(--color-blue-100);
  color: var(--color-blue-500);
}
/* the two groups land in sequence after the code sheet settles */
.p-axw .axw.is-s3 .axw__proof-h,
.p-axw .axw.is-s3 .axw__proof-chips { animation: axw-rise 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) both; }
.p-axw .axw.is-s3 .axw__proof-h:nth-of-type(1) { animation-delay: 0.25s; }
.p-axw .axw.is-s3 .axw__proof-chips:nth-of-type(1) { animation-delay: 0.35s; }
.p-axw .axw.is-s3 .axw__proof-h:nth-of-type(2) { animation-delay: 0.5s; }
.p-axw .axw.is-s3 .axw__proof-chips:nth-of-type(2) { animation-delay: 0.6s; }

/* --- narrow viewports: static mode; the duo stacks --- */
@media (max-width: 1023px) {
  .p-axw .axw { margin-top: 34px; }
}
@media (max-width: 639px) {
  .p-axw .axw__duo {
    flex-direction: column;
    gap: 18px;
  }
  .p-axw .axw__side { width: min(100%, 280px); }
}

/* --- reduced motion: composed static frames — states still swap on
   click, nothing animates, the strikes read struck. !important beats
   the stateful (.is-sN) selectors, the wfh precedent --- */
@media (prefers-reduced-motion: reduce) {
  .p-axw .sol-how__reveal,
  .p-axw .axw__co,
  .p-axw .axw__error,
  .p-axw .axw__code,
  .p-axw .axh-livecap,
  .p-axw .s3-caption-ready,
  .p-axw .s3-ring-scan {
    transition: none !important;
  }
  .p-axw .axw__cue,
  .p-axw .axw__status,
  .p-axw .axw__status-dot,
  .p-axw .axw__not-row,
  .p-axw .axw__not-row--yes,
  .p-axw .axw__not-row s::after,
  .p-axw .axw__alt,
  .p-axw .axw__code-ln,
  .p-axw .axw__proof-h,
  .p-axw .axw__proof-chips,
  .p-axw .fe-badge,
  .p-axw .fe-heading,
  .p-axw .fe-sub,
  .p-axw .fe-attempts,
  .p-axw .fe-btn,
  .p-axw .s3-ring-scan {
    animation: none !important;
  }
  .p-axw .axw__not-row s::after { transform: scaleX(1); }
}
