/* Path of Living · quiz screen. Adapted from prototype.html v2, the reference
   implementation (DECISIONS §8). Two rules below are MEASUREMENT GUARDS, not
   styling choices, recorded in DECISIONS §8 — do not polish them away:
   · the two option boxes are visually IDENTICAL (visual asymmetry between
     poles is a bias);
   · the four circles differ in visual size but their hit areas are equal and
     ≥44pt, or slight answers cost more effort than strong ones and
     extremeness inflates. */

* { box-sizing: border-box; margin: 0; touch-action: manipulation; }
html { -webkit-text-size-adjust: 100%; }
body { font-family: system-ui, sans-serif; background: #06090f; color: #cfd6e4;
       display: flex; justify-content: center;
       -webkit-tap-highlight-color: transparent; }

#frame { position: relative; width: 100%; max-width: 430px;
         min-height: 100vh; min-height: 100dvh; /* vh fallback for pre-dvh browsers */
         overflow: hidden; display: flex; flex-direction: column; gap: 12px;
         padding: calc(16px + env(safe-area-inset-top)) 18px
                  calc(60px + env(safe-area-inset-bottom));
         background:
           radial-gradient(ellipse 120% 45% at 50% 108%, rgba(24,48,34,.85), rgba(24,48,34,0) 70%),
           linear-gradient(#070c16 0%, #0a1322 55%, #0d1a27 100%); }
@media (min-width: 640px) {
  body { padding: 24px; align-items: flex-start; }
  #frame { min-height: 760px; border: 1px solid #2a3242; border-radius: 12px; }
}

/* fireflies — spawned in top/bottom margins only (quiz.js), so they never
   cross behind text being read (DECISIONS §8) */
.fly { position: absolute; width: 4px; height: 4px; border-radius: 50%; background: #d8f2a8;
       box-shadow: 0 0 8px 2px rgba(205,240,150,.55); opacity: 0; pointer-events: none;
       animation: drift 9s linear infinite; }
@keyframes drift {
  0% { opacity: 0; transform: translate(0,0); }
  12% { opacity: .85; } 45% { opacity: .25; } 60% { opacity: .7; }
  100% { opacity: 0; transform: translate(26px,-58px); } }

/* positioned + raised so fireflies (unpositioned band dwellers) can never
   drift across this text (DECISIONS §8) */
#banner { font-size: 12px; color: #9fb0c8; border-bottom: 1px solid rgba(255,255,255,.14);
          padding-bottom: 6px; position: relative; z-index: 2; }
#progressWrap { font-size: 11px; color: #7787a0; position: relative; z-index: 2; }
#bar { height: 3px; background: rgba(255,255,255,.12); margin-top: 3px; }
#bar div { height: 3px; background: #cde39a; width: 0; transition: width .25s; }

#screen { display: flex; flex-direction: column; flex: 1; z-index: 2; }

/* --qboxH / --optH are measured at runtime from the longest rendered item
   (measure.js), so box and circle positions never shift between items */
.qbox { background: rgba(13,20,34,.62); border: 1px solid rgba(255,255,255,.18);
        -webkit-backdrop-filter: blur(6px);
        backdrop-filter: blur(6px); border-radius: 10px; padding: 16px 15px; min-height: 118px;
        height: var(--qboxH, auto);
        font-size: 19px; line-height: 1.5; color: #e9edf5; margin-top: 6px; }
.blank { border-bottom: 1.5px solid #e9edf5; padding: 0 2px; min-width: 70px; display: inline-block; }
.blank.empty { border-bottom-color: rgba(233,237,245,.5); }

/* MEASUREMENT GUARD: one .opt rule serves both boxes — identical on purpose */
.opts { display: flex; gap: 10px; margin-top: 12px; align-items: stretch; }
.opt { flex: 1 1 0; background: rgba(13,20,34,.55); border: 1px solid rgba(255,255,255,.22);
       -webkit-backdrop-filter: blur(6px);
       backdrop-filter: blur(6px); border-radius: 10px; padding: 12px 11px;
       height: var(--optH, auto);
       font-size: 15px; line-height: 1.35; color: #dfe5f0; display: flex; align-items: center; }
.opt.armedSide { border-color: rgba(214,235,170,.75); }

/* MEASUREMENT GUARD: every .circle button is 64×64 (>44pt) regardless of the
   visual size of the inner disc */
.circles { display: flex; margin-top: 14px; }
.cwrap { flex: 1 1 0; display: flex; align-items: center; justify-content: center; }
.circle { width: 64px; height: 64px; background: none; border: none; cursor: pointer;
          display: flex; align-items: center; justify-content: center; padding: 0; }
.circle i { display: block; border-radius: 50%; border: 1.5px solid #b9c6dd;
            background: rgba(20,30,48,.5); }
.circle.big i { width: 52px; height: 52px; }
.circle.small i { width: 34px; height: 34px; }
.circle.armed i { border-color: #e6f3c0; background: rgba(160,200,110,.25);
                  box-shadow: 0 0 14px 3px rgba(205,240,150,.65);
                  animation: pulse 1.1s ease-in-out infinite; }
@keyframes pulse { 50% { box-shadow: 0 0 22px 6px rgba(205,240,150,.85); } }
#hint { min-height: 16px; font-size: 12px; color: #93a55f; text-align: center; margin-top: 4px; }

/* The orb is a small sun: breathing glow, slow-turning flare rays that fade in
   as it grows (--flare, set per answer), and a hue that warms green→gold via
   an inline hue-rotate. Continuous animation is decorative — off under
   reduced motion and .noanim. */
#orb { position: absolute; left: 50%; bottom: calc(12px + env(safe-area-inset-bottom));
       transform: translateX(-50%); border-radius: 50%;
       background: radial-gradient(circle at 38% 32%, #fdffe9, #e9f7b4 30%, #b9d97e 55%, #5c7a3a 82%);
       box-shadow: 0 0 14px 4px rgba(200,235,140,.5);
       transition: width .3s, height .3s, filter .6s;
       animation: orbBreathe 3.6s ease-in-out infinite; }
#orb::after { content: ''; position: absolute; inset: -60%; border-radius: 50%;
       background: repeating-conic-gradient(rgba(245,255,210,0) 0deg 11deg,
                   rgba(245,255,210,.4) 15deg, rgba(245,255,210,0) 19deg 30deg);
       -webkit-mask-image: radial-gradient(circle, transparent 32%, #000 48%, transparent 74%);
       mask-image: radial-gradient(circle, transparent 32%, #000 48%, transparent 74%);
       opacity: var(--flare, 0); animation: orbSpin 18s linear infinite; }
@keyframes orbSpin { to { transform: rotate(360deg); } }
@keyframes orbBreathe {
  0%, 100% { box-shadow: 0 0 14px 4px rgba(200,235,140,.45), 0 0 42px 12px rgba(200,235,140,.10); }
  50%      { box-shadow: 0 0 24px 8px rgba(225,250,175,.80), 0 0 64px 20px rgba(225,250,175,.22); } }
/* pop replaces breathe for one flash (an animation always beats a class's
   static box-shadow, so the flash must itself be an animation) */
#orb.pop { animation: orbPop .32s ease-out; }
@keyframes orbPop {
  0%   { transform: translateX(-50%) scale(1.45);
         box-shadow: 0 0 40px 14px rgba(235,255,190,.95), 0 0 110px 34px rgba(235,255,190,.40); }
  100% { transform: translateX(-50%) scale(1);
         box-shadow: 0 0 14px 4px rgba(200,235,140,.45), 0 0 42px 12px rgba(200,235,140,.10); } }

/* alive sun candidate (?orb=alive, under review): canvas particle swarm —
   the container keeps all transform choreography, the canvas only paints */
#orb.alive { background: none; box-shadow: none; animation: none; }
#orb.alive::before, #orb.alive::after { display: none; }
/* 280px matches CANVAS_PX in orb-alive.js — the atmospheric bloom needs the
   headroom or it clips at the canvas edge into a visible square.
   The radial mask kills the layer-boundary artifact class entirely: on iOS,
   WebKit composites the WebGL layer's region of the background gradient
   through a different path than the surrounding CSS, so the layer's BOUNDS
   showed as a faint square even where our pixels were fully transparent
   (user-caught on a real iPhone, 2026-08-20 — invisible on any Mac). With
   the mask, the layer itself fades out radially; there is no square edge
   left to reveal. */
.orbCanvas { position: absolute; left: 50%; top: 50%; width: 280px; height: 280px;
  transform: translate(-50%, -50%); pointer-events: none;
  -webkit-mask-image: radial-gradient(circle closest-side, #000 55%, transparent 97%);
  mask-image: radial-gradient(circle closest-side, #000 55%, transparent 97%); }
/* In alive mode the spirit keeps only the glide: spiritBreath's box-shadow
   ring wraps the old 51px body and reads as a hard-edged halo against the
   canvas swarm (user, 2026-08-18) — the swarm's own breathing carries the
   centered moment instead. More specific than #orb.spiritCenter, so it wins;
   the later .spiritDissolve rule still takes over on tap. */
#orb.alive.spiritCenter {
  animation: spiritGlide 1.1s cubic-bezier(0.3, 0, 0.15, 1) forwards; }

/* rich sun candidate (?orb=rich, under review): limb-darkened layered core,
   living granulation grain, soft two-lobe corona instead of hard conic rays.
   Authored in the same green→gold family — the §9 hue-rotate arc and growth
   mechanics are untouched. If ruled in, §9 gets the amendment. */
.orbRich #orb {
  background:
    radial-gradient(circle at 36% 30%, rgba(255,255,248,.95), rgba(255,255,248,0) 30%),
    radial-gradient(circle at 50% 46%,
      #fdffee 0%, #f2fbc8 20%, #dcee9e 40%, #b8d472 62%,
      #8fae4e 80%, #647d33 93%, rgba(58,74,30,.92) 100%);
  animation: orbBreatheRich 3.6s ease-in-out infinite;
}
@keyframes orbBreatheRich {
  0%, 100% { box-shadow: 0 0 8px 2px rgba(250,255,225,.6),
             0 0 22px 6px rgba(216,238,150,.35), 0 0 54px 18px rgba(190,220,120,.12); }
  50%      { box-shadow: 0 0 12px 3px rgba(252,255,235,.85),
             0 0 34px 10px rgba(224,244,165,.55), 0 0 80px 26px rgba(200,228,135,.22); } }
.orbRich #orb::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%; overflow: hidden;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="120" height="120"><filter id="n"><feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2"/></filter><rect width="120" height="120" filter="url(%23n)" opacity="0.85"/></svg>');
  background-size: 220% 220%;
  mix-blend-mode: overlay; opacity: .55;
  animation: grainDrift 16s ease-in-out infinite alternate;
}
@keyframes grainDrift {
  from { transform: rotate(0deg) scale(1); }
  to   { transform: rotate(150deg) scale(1.22); } }
.orbRich #orb::after {
  inset: -80%;
  background:
    radial-gradient(ellipse 58% 100% at 50% 50%, rgba(238,250,195,.32), rgba(238,250,195,0) 62%),
    radial-gradient(ellipse 100% 54% at 50% 50%, rgba(238,250,195,.28), rgba(238,250,195,0) 62%);
  -webkit-mask-image: none; mask-image: none;
  opacity: var(--flare, 0);
  animation: coronaTurn 26s linear infinite;
}
@keyframes coronaTurn { to { transform: rotate(360deg); } }
.orbRich #orb.pop { animation: orbPopRich .32s ease-out; }
@keyframes orbPopRich {
  0%   { transform: translateX(-50%) scale(1.45);
         box-shadow: 0 0 26px 8px rgba(252,255,235,.95), 0 0 70px 24px rgba(224,244,165,.5); }
  100% { transform: translateX(-50%) scale(1);
         box-shadow: 0 0 8px 2px rgba(250,255,225,.6), 0 0 54px 18px rgba(190,220,120,.12); } }

@media (prefers-reduced-motion: reduce) {
  #orb, #orb::before, #orb::after, .fly, .circle.armed i, .cell.hot.settle { animation: none; }
  .axisSheet { transition: none; }
  .navrow button, .wide { transition: none; }
  .navrow button:active, .wide:active { transform: none; }
}
.noanim #orb, .noanim #orb::before, .noanim #orb::after, .noanim .fly,
.noanim .circle.armed i, .noanim .cell.hot.settle { animation: none; }

.navrow { display: flex; justify-content: space-between; align-items: center;
  margin-top: auto; padding-top: 12px; gap: 10px; }
/* Buttons, meadow register (user direction 2026-08-19): quiet glass for the
   sideways steps (Back, Start over, Nothing right now), a firefly-lit
   .primary for the forward action (Start, Continue, Finish). Single-action
   buttons, not measurement surfaces — but hit height still ≥44px. */
.navrow button, .wide { font-size: 15px; padding: 11px 18px; min-height: 44px;
      background: rgba(13,20,34,.55); color: #c2ccdb; cursor: pointer;
      border: 1px solid rgba(255,255,255,.16); border-radius: 11px;
      -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
      transition: border-color .25s ease, color .25s ease, box-shadow .25s ease,
                  transform .12s ease; }
.navrow button:active, .wide:active { transform: scale(.97); }
.navrow button:disabled { opacity: .4; cursor: default; }
.navrow button:focus-visible, .wide:focus-visible {
      outline: 1.5px solid rgba(214,235,170,.8); outline-offset: 2px; }
button.primary {
      background: linear-gradient(180deg, rgba(158,196,108,.20), rgba(158,196,108,.06)),
                  rgba(13,20,34,.55);
      border-color: rgba(214,235,170,.5); color: #edf5da;
      box-shadow: 0 0 14px rgba(205,240,150,.14), inset 0 0 8px rgba(205,240,150,.06); }
button.primary:active {
      box-shadow: 0 0 22px rgba(205,240,150,.3), inset 0 0 10px rgba(205,240,150,.1); }
@media (hover: hover) {
  .navrow button:hover:not(:disabled), .wide:hover { border-color: rgba(255,255,255,.3); color: #e2e9f3; }
  button.primary:hover:not(:disabled) { border-color: rgba(214,235,170,.7); color: #f4f9e8;
      box-shadow: 0 0 20px rgba(205,240,150,.24), inset 0 0 9px rgba(205,240,150,.08); }
}
.noanim .navrow button, .noanim .wide { transition: none; }
.noanim .navrow button:active, .noanim .wide:active { transform: none; }
.wide { width: 100%; margin-top: 12px; text-align: left; font-size: 16px; padding: 13px 16px; }
input[type=text] { font-size: 17px; padding: 11px; border: 1px solid rgba(255,255,255,.3);
      background: rgba(13,20,34,.6); color: #e9edf5; width: 100%; border-radius: 8px; }
.err { color: #e8a0a0; font-size: 13px; min-height: 16px; }
.help { font-size: 13px; color: #93a0b5; line-height: 1.4; }
h2 { font-size: 17px; font-weight: 600; color: #e9edf5; }
.soft { color: #8a97ad; font-size: 13px; line-height: 1.45; }

/* ------------------------------------------------------------------ result
   Seven paged frames (docs/design/frame-placement.html), scroll-snap paging.
   Pages are transparent so the meadow and the full-grown sun stay visible. */
/* The pager is a standing stage (DECISIONS §17, the user's sketch intent):
   the viewport never scrolls — frames stack in place, one visible; a scroll
   gesture EVENTS the swap: exiting content leaves, entering content arrives,
   in the same beat. `safe center` + per-frame overflow still guard font
   scaling and zoom: an overflowing frame scrolls internally and pages only
   from its boundary. */
#screen.paged { position: absolute; inset: 0; z-index: 2; display: block;
  overflow: hidden; overscroll-behavior: contain; }
.rframe { position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 14px;
  justify-content: center; justify-content: safe center; overflow-y: auto;
  opacity: 0; visibility: hidden; pointer-events: none;
  padding: calc(22px + env(safe-area-inset-top)) 20px
           calc(64px + env(safe-area-inset-bottom)); }
.rframe.active { opacity: 1; visibility: visible; pointer-events: auto; }
/* exit and enter run CONCURRENTLY (both frames hold .active for the turn's
   duration) — the crossfade is the whole point, a gap of bare background
   between frames is a defect (user, 2026-08-18). Enter paints above exit. */
.rframe.active.exitUp { animation: frameExitUp .38s cubic-bezier(0.4, 0, 0.7, 1) forwards; }
.rframe.active.exitDown { animation: frameExitDown .38s cubic-bezier(0.4, 0, 0.7, 1) forwards; }
@keyframes frameExitUp { to { opacity: 0; transform: translateY(-18px); } }
@keyframes frameExitDown { to { opacity: 0; transform: translateY(18px); } }
.rframe.active.enterFromBelow { animation: frameEnterBelow .5s cubic-bezier(0.2, 0, 0.2, 1) both; }
.rframe.active.enterFromAbove { animation: frameEnterAbove .5s cubic-bezier(0.2, 0, 0.2, 1) both; }
.rframe.enterFromBelow, .rframe.enterFromAbove { z-index: 1; }
@keyframes frameEnterBelow { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }
@keyframes frameEnterAbove { from { opacity: 0; transform: translateY(-22px); } to { opacity: 1; transform: none; } }
.noanim .rframe.exitUp, .noanim .rframe.exitDown,
.noanim .rframe.enterFromBelow, .noanim .rframe.enterFromAbove { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .rframe.exitUp, .rframe.exitDown,
  .rframe.enterFromBelow, .rframe.enterFromAbove { animation: none; }
}
#rf1 { justify-content: flex-start; }
#rf1 .reveal { margin: auto 0; }
.wordmark { font-size: 11px; letter-spacing: .18em; color: #6d7a92; }

/* The display voice: Gloock (user ruling 2026-08-20, from the /type review;
   OFL, self-hosted latin subset — never a font CDN, per the privacy posture).
   Display moments ONLY: the reveal's THE and coordinate box here, the landing
   line in landing.css. Prose, UI strings, and every MEASURED surface stay on
   the system stack, so font loading can never shift the quiz's measured
   geometry (§8). font-display swap: the fallback shows instantly, the face
   arrives on the reveal like a page being set. */
@font-face {
  font-family: 'Gloock';
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url(/app/gloock-400.woff2) format('woff2');
}

/* reveal per sketch p12: bubbled THE, coordinate boxed on a contrasting
   color base ("box is part of design"), preposition line aligned under */
.revYou { font-size: 16px; color: #9aa8bf; }
.revThe { font-family: 'Gloock', Georgia, serif; font-size: 32px; font-weight: 400;
  letter-spacing: .06em; margin-top: 10px;
  color: transparent; -webkit-text-stroke: 1.5px #e9edf5; }
@supports not (-webkit-text-stroke: 1px #fff) { .revThe { color: #e9edf5; } }
.coordBox { display: inline-block; margin-top: 8px; padding: 10px 16px;
  background: #cde39a; color: #0a1322; border-radius: 12px;
  font-family: 'Gloock', Georgia, serif;
  font-size: 28px; font-weight: 400; letter-spacing: .02em;
  box-shadow: 0 0 24px rgba(205,227,154,.25); }
.revState { font-size: 18px; color: #cfd6e4; margin-top: 12px; }
.revState b { color: #cde39a; font-weight: 600; }
.reveal.small .revThe { font-size: 20px; -webkit-text-stroke-width: 1px; }
.reveal.small .coordBox { font-size: 19px; padding: 7px 12px; border-radius: 9px; }
.reveal.small .revState { font-size: 14px; margin-top: 8px; }
.swipeCue { text-align: center; color: #4a566c; font-size: 17px; }

/* recap header on the frames after the breakdowns (sketch p13) */
.recap { position: absolute; top: calc(18px + env(safe-area-inset-top)); right: 20px;
  text-align: right; font-size: 12px; line-height: 1.5; color: #9aa8bf; }
.rlabel { font-size: 11px; letter-spacing: .14em; color: #6d7a92; margin-bottom: 4px; }

.axisRow { display: block; width: 100%; background: none; border: none; padding: 8px 0;
  cursor: pointer; text-align: left; color: inherit; font: inherit; }
.lbl { display: flex; justify-content: space-between; align-items: center;
  font-size: 13px; color: #9aa8bf; }
/* sketch p12: the user's pole boxed, the unselected one faded */
.winChip { border: 1.5px solid rgba(205,227,154,.8); background: rgba(205,227,154,.12);
  border-radius: 6px; padding: 3px 8px; color: #e6f3c0; }
.loseLbl { opacity: .45; }
.bar { display: block; height: 10px; background: rgba(255,255,255,.1); border-radius: 5px;
  margin-top: 7px; overflow: hidden; }
.bar span { display: block; height: 10px; border-radius: 5px;
  background: linear-gradient(90deg, #9fbf6a, #cde39a); }

.diamond { width: 150px; height: 150px; margin: 34px auto; transform: rotate(45deg);
  display: grid; grid-template: 1fr 1fr / 1fr 1fr; gap: 5px; }
.cell { border: 1px solid rgba(255,255,255,.22); border-radius: 5px; }
.cell.hot { border: 3px solid #cde39a; box-shadow: 0 0 12px rgba(205,240,150,.4); }
/* slot-machine-like landing when the diamond scrolls into view (sketch p13) */
.cell.hot.settle { animation: cellSettle .9s cubic-bezier(.2, 1.4, .4, 1); }
@keyframes cellSettle {
  0%   { transform: scale(.55); box-shadow: 0 0 34px rgba(205,240,150,.95); }
  55%  { transform: scale(1.14); }
  100% { transform: scale(1); box-shadow: 0 0 12px rgba(205,240,150,.4); } }
.mini { font-size: 12px; color: #9aa8bf; text-align: center; }

.panel { background: rgba(13,20,34,.62); border: 1px solid rgba(255,255,255,.16);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px); border-radius: 10px; padding: 16px 15px; }
/* speech bubble (sketch p13); the silhouette + background scene arrive with
   the 22-asset set */
.voicePanel { position: relative; border-radius: 14px; }
.voicePanel::after { content: ''; position: absolute; left: 34px; bottom: -11px;
  width: 0; height: 0; border-left: 11px solid transparent;
  border-right: 5px solid transparent;
  border-top: 12px solid rgba(255,255,255,.16); }
.voicePanel::before { content: ''; position: absolute; left: 35px; bottom: -9px;
  width: 0; height: 0; border-left: 10px solid transparent;
  border-right: 4px solid transparent;
  border-top: 11px solid rgba(13,20,34,.95); z-index: 1; }
.voice { font-size: 15px; line-height: 1.6; color: #dbe2ee; font-style: italic; }
.voice p + p { margin-top: 10px; }
.rbody { font-size: 15.5px; line-height: 1.6; color: #e6ebf4; }
.contrast { border-style: dashed; border-color: rgba(255,255,255,.28); }
.x1 { font-size: 15px; color: #d8e6a9; line-height: 1.5; }
.contrastLine { font-size: 13.5px; color: #9aa8bf; line-height: 1.5; margin-top: 10px; }

.shareFrame { text-align: center; }
.shareRow { display: flex; justify-content: center; margin-top: 8px; }
.shareRow button { display: inline-flex; align-items: center; justify-content: center;
  padding: 12px 24px; background: rgba(13,20,34,.6); border: 1px solid rgba(255,255,255,.3);
  color: #dfe5f0; border-radius: 8px; cursor: pointer; }
.shareNote { min-height: 16px; font-size: 12px; color: #93a55f; }
.methodLink { margin-top: auto; margin-bottom: 16px; align-self: center; font-size: 12px;
  color: #7787a0; text-decoration: none; border-bottom: 1px solid rgba(119,135,160,.4);
  padding-bottom: 1px; }

/* axis detail: a separate full page sliding in from the right (sketch p12's
   right-swipe transition; user 2026-08-10: "not pop-up, separate pages") */
.axisSheet { position: absolute; inset: 0; z-index: 6; overflow-y: auto;
  padding: calc(22px + env(safe-area-inset-top)) 20px
           calc(40px + env(safe-area-inset-bottom));
  background:
    radial-gradient(ellipse 120% 45% at 50% 108%, rgba(24,48,34,.9), rgba(24,48,34,0) 70%),
    linear-gradient(#070c16 0%, #0a1322 55%, #0d1a27 100%);
  transform: translateX(102%); transition: transform .3s ease-out; }
.axisSheet.open { transform: none; }
.noanim .axisSheet { transition: none; }
.sheetBack { background: none; border: none; color: #9aa8bf; font: inherit;
  font-size: 14px; cursor: pointer; padding: 0 0 14px; text-align: left; display: block; }
.axisIntro { font-size: 14px; color: #c3ccdb; margin: 6px 0 12px; line-height: 1.5; }
.bandLine { font-size: 13.5px; color: #d8e6a9; line-height: 1.5; margin: 12px 0; }
.polePara { font-size: 14.5px; color: #c3ccdb; line-height: 1.55; margin-top: 12px; }
.polePara b { color: #e6ebf4; }
.polePara.faded { opacity: .5; }

/* ------------------------------------------------- question→result transition
   Review candidates behind ?transition=arrival|quiet (task #2). Compositor
   properties only. All of it dead when .noanim or reduced motion. */
.trOut { opacity: 0; transition: opacity .4s ease-in; }
.trIn { animation: trFadeUp .7s cubic-bezier(0.2, 0, 0.2, 1) both; }
@keyframes trFadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; } }

/* arrival: the grown sun rises ~2.6x and the meadow briefly holds light */
#orb.trRise { animation: orbUp 1.5s cubic-bezier(0.3, 0, 0.2, 1) forwards; }
@keyframes orbUp {
  to { transform: translateX(-50%) translateY(-46vh) scale(2.6);
       filter: hue-rotate(-50deg) saturate(1.5) brightness(1.25); } }
#orb.trSet { animation: orbDown .9s ease-in-out both; }
@keyframes orbDown {
  from { transform: translateX(-50%) translateY(-46vh) scale(2.6); }
  to   { transform: translateX(-50%); } }
.lightWash { position: absolute; inset: 0; z-index: 3; pointer-events: none;
  opacity: 0; transition: opacity 1.2s ease-out;
  background: radial-gradient(ellipse 150% 90% at 50% 88%,
    rgba(240,250,200,.38), rgba(233,247,180,.14) 45%, rgba(233,247,180,0) 75%); }
.lightWash.on { opacity: 1; }

/* spirit: the sun glides to center and breathes until TAPPED; the tap
   gathers it, blooms it away, one mote rises, a mild flash, then the name.
   The breath doubles as the tap affordance — no copy without a ruling. */
/* while armed as a button (transition.js sets role/tabindex), keyboard
   focus must be visible — a soft ring offset outside the glow */
#orb.spiritCenter:focus-visible { outline: 1.5px solid rgba(214,235,170,.7);
  outline-offset: 14px; border-radius: 50%; }
#orb.spiritCenter { z-index: 6; cursor: pointer; pointer-events: auto;
  animation: spiritGlide 1.1s cubic-bezier(0.3, 0, 0.15, 1) forwards,
             spiritBreath 1.9s ease-in-out 1.15s infinite; }
@keyframes spiritGlide {
  to { transform: translateX(-50%) translateY(-46dvh) scale(1.9); } }
@keyframes spiritBreath {
  0%, 100% { box-shadow: 0 0 18px 5px rgba(240,252,205,.55),
             0 0 48px 16px rgba(215,240,160,.22); }
  50%      { box-shadow: 0 0 30px 9px rgba(248,255,225,.9),
             0 0 84px 30px rgba(225,246,175,.4); } }
#orb.spiritCenter.spiritDissolve { pointer-events: none;
  animation: spiritBloom .8s cubic-bezier(0.45, 0, 0.85, 0.6) forwards; }
@keyframes spiritBloom {
  0%   { transform: translateX(-50%) translateY(-46dvh) scale(1.9);
         opacity: 1; filter: brightness(1); }
  32%  { transform: translateX(-50%) translateY(-46dvh) scale(1.5);
         opacity: 1; filter: brightness(1.7); }   /* the gather: an inhale */
  100% { transform: translateX(-50%) translateY(-46dvh) scale(3.6);
         opacity: 0; filter: brightness(2.4); } }
.spiritMote { position: absolute; left: 50%; top: calc(100% - 46dvh - 40px);
  width: 8px; height: 8px; border-radius: 50%; background: #fdffee;
  box-shadow: 0 0 14px 5px rgba(240,255,210,.9); opacity: 0; z-index: 6;
  pointer-events: none; transform: translateX(-50%);
  animation: moteRise 1.5s cubic-bezier(0.3, 0, 0.4, 1) .3s forwards; }
@keyframes moteRise {
  0%   { opacity: 0; transform: translateX(-50%) translateY(0) scale(.6); }
  18%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(calc(-50% + 12px)) translateY(-24dvh) scale(1.1); } }
.spiritFlash { position: absolute; inset: 0; z-index: 5; pointer-events: none;
  opacity: 0; transition: opacity .5s ease-out;
  background: radial-gradient(ellipse 120% 90% at 50% 52%,
    rgba(250,255,235,.5), rgba(240,250,200,.18) 55%, transparent 80%); }
.spiritFlash.on { opacity: .8; transition: opacity .25s ease-in; }

/* quiet: everything settles, one dark beat, the name arrives in stages */
.trDim .fly { opacity: 0 !important; transition: opacity .8s ease-in; }
.trDim #orb { transition: filter .8s ease-in, width .3s, height .3s;
  filter: brightness(.45) saturate(.6) !important; }
.trDim { transition: none; }
.quietIn { opacity: 1 !important; }
.quietIn #rf1 > * { opacity: 0; animation: trFadeUp .5s cubic-bezier(0.2, 0, 0.2, 1) forwards; }
.quietIn #rf1 .wordmark { animation-delay: 1.5s; }
.quietIn #rf1 .reveal .revYou { opacity: 0; animation: trFadeUp .45s cubic-bezier(0.2, 0, 0.2, 1) .15s forwards; }
.quietIn #rf1 .reveal .revThe { opacity: 0; animation: trFadeUp .45s cubic-bezier(0.2, 0, 0.2, 1) .45s forwards; }
.quietIn #rf1 .reveal > div:nth-child(3) { opacity: 0; animation: trFadeUp .5s cubic-bezier(0.2, 0, 0.2, 1) .8s forwards; }
.quietIn #rf1 .reveal .revState { opacity: 0; animation: trFadeUp .45s cubic-bezier(0.2, 0, 0.2, 1) 1.2s forwards; }
.quietIn #rf1 .reveal { opacity: 1; animation: none; }
.quietIn #rf1 .swipeCue { animation-delay: 1.7s; }
.noanim .trOut, .noanim .trIn, .noanim .lightWash { transition: none; animation: none; opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .trOut, .trIn, .lightWash, #orb.trRise, #orb.trSet,
  #orb.spiritCenter, #orb.spiritDissolve, .spiritMote, .spiritFlash,
  .quietIn #rf1 > *, .quietIn #rf1 .reveal > * { transition: none; animation: none; opacity: 1; }
}

/* answer-absorption mote (mote-flight.js, DECISIONS §18): rises from the
   confirmed circle into the orb. Fixed overlay, zero layout, zero hit area —
   decorative by measurement-guard rule. Driven entirely by WAAPI; no CSS
   animation to guard for reduced motion (the JS gates on config.anim). */
.flyMote { position: fixed; left: 0; top: 0; width: 16px; height: 16px;
  margin: -8px 0 0 -8px; border-radius: 50%; pointer-events: none;
  z-index: 7; will-change: transform, opacity; }

/* letter-scatter (scatter.js). Timing vars --outT/--inT are set from the
   runtime speed option; the speed itself is undecided (DECISIONS §8). */
.ch { display: inline-block; }
.word { display: inline-block; }
.anim-out .ch { animation: chOut var(--outT, .18s) forwards; }
.anim-in  .ch { opacity: 0; animation: chIn var(--inT, .22s) forwards; }
@keyframes chOut { to { opacity: 0; transform: translateY(-12px); } }
@keyframes chIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.noanim .ch, .noanim .anim-out .ch, .noanim .anim-in .ch { animation: none; opacity: 1; transform: none; }

/* Confirm exit / entry for the screen CHROME (user, 2026-08-18): the option
   boxes, circles, nav, hint, and the blank's underline fade in the same
   window the letters scatter, so the armed glow decays away instead of
   popping at the re-render. Purely opacity — geometry, hit areas, and timing
   of the advance are untouched (measurement guard, DECISIONS §8).
   The blank: EXIT fades any .blank (it is filled by confirm time); ENTRY
   fades only .blank.empty — arming swaps in a filled .blank without .empty,
   which must keep appearing INSTANTLY (arm feedback is interaction, not
   decoration). */
#screen.exiting .opt, #screen.exiting .circles, #screen.exiting .navrow,
#screen.exiting #hint, #screen.exiting .blank {
  animation: chromeOut calc(var(--outT, .18s) * 1.5) ease forwards; }
#screen.entering .opt, #screen.entering .circles, #screen.entering .navrow,
#screen.entering #hint, #screen.entering .blank.empty {
  animation: chromeIn calc(var(--inT, .22s) * 1.3) ease both; }
@keyframes chromeOut { to { opacity: 0; } }
@keyframes chromeIn { from { opacity: 0; } }
.noanim #screen.exiting .opt, .noanim #screen.exiting .circles,
.noanim #screen.exiting .navrow, .noanim #screen.exiting #hint,
.noanim #screen.exiting .blank,
.noanim #screen.entering .opt, .noanim #screen.entering .circles,
.noanim #screen.entering .navrow, .noanim #screen.entering #hint,
.noanim #screen.entering .blank.empty { animation: none; }
@media (prefers-reduced-motion: reduce) {
  #screen.exiting .opt, #screen.exiting .circles, #screen.exiting .navrow,
  #screen.exiting #hint, #screen.exiting .blank,
  #screen.entering .opt, #screen.entering .circles,
  #screen.entering .navrow, #screen.entering #hint,
  #screen.entering .blank.empty { animation: none; }
}
