/* Agent figures: art per role, provider ring, state layers and motion. Markup comes from figure() in app.js. */
.figure{--fig-accent:var(--claude);--ring:166 81 43;position:relative;display:block;flex:none}
.figure.provider-codex{--fig-accent:var(--codex);--ring:79 111 143}
.fig-art{position:absolute;inset:0;display:block;transform-origin:50% 97%}
.fig-art>svg,.fig-art>img{position:absolute;inset:0;width:100%;height:100%;display:block;object-fit:contain;-webkit-user-drag:none;user-select:none}
.figure.has-art .fig-fallback{display:none}
.fig-layer{opacity:0}

/* full figure (map) */
.fig-full{width:78px;height:104px}
.fig-ring{position:absolute;left:50%;bottom:-5px;width:62px;height:20px;transform:translateX(-50%);border-radius:50%;
 background:radial-gradient(closest-side,rgb(var(--ring)/.22),rgb(var(--ring)/.10) 70%,transparent);box-shadow:0 0 0 1.5px rgb(var(--ring)/.45);transition:box-shadow var(--t-fast),background var(--t-fast)}
.fig-aura{position:absolute;left:50%;top:6%;width:96%;height:70%;transform:translateX(-50%);border-radius:50%;opacity:0;
 background:radial-gradient(closest-side,rgb(var(--p-light-rgb)/.75),rgb(var(--p-light-rgb)/0));pointer-events:none}
.fig-portrait .fig-ring,.fig-portrait .fig-aura,.fig-portrait .model-badge{display:none}

/* portrait (inspector, detail): same art, cropped to head and shoulders */
/* sized from the width only (aspect-ratio), so the crop stays on the face whatever height the container resolves to */
.fig-portrait{width:100%;height:auto;aspect-ratio:1/1;overflow:hidden;border-radius:50%}
/* crop window on the art: x 85..315, y 125..355 of 384x512, i.e. the head and shoulders of every figure */
.fig-portrait .fig-art{inset:auto;left:-37%;top:-54.3%;width:167%;height:auto;aspect-ratio:3/4}
.fig-portrait .fig-art>img{object-fit:fill}

/* state badges above the head */
.fig-fx i{position:absolute;display:none;font:800 12px/1 var(--font-latin);font-style:normal;pointer-events:none}
.fx-wait,.fx-error{top:-2px;right:2px;width:20px;height:20px;border-radius:50%;place-items:center;background:#fff;box-shadow:0 4px 10px -4px rgb(var(--p-shadow)/.5)}
.fx-wait{color:var(--p);border:1.5px solid rgb(var(--p-rgb)/.45)}
.fx-error{color:var(--st-error);border:1.5px solid rgb(168 38 28/.45);background:var(--st-error-bg)}
.fx-idle{top:2px;right:6px;color:var(--p-mid);font-size:14px;opacity:.8}
.fx-done{top:-4px;left:50%;width:34px;height:16px;margin-left:-17px;background:#7f9a6a;
 -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 16'%3E%3Cg fill='black'%3E%3Cellipse cx='6' cy='6' rx='5' ry='2.4' transform='rotate(35 6 6)'/%3E%3Cellipse cx='10' cy='11' rx='5' ry='2.4' transform='rotate(15 10 11)'/%3E%3Cellipse cx='28' cy='6' rx='5' ry='2.4' transform='rotate(-35 28 6)'/%3E%3Cellipse cx='24' cy='11' rx='5' ry='2.4' transform='rotate(-15 24 11)'/%3E%3Ccircle cx='17' cy='13' r='2.2'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat;
 mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 16'%3E%3Cg fill='black'%3E%3Cellipse cx='6' cy='6' rx='5' ry='2.4' transform='rotate(35 6 6)'/%3E%3Cellipse cx='10' cy='11' rx='5' ry='2.4' transform='rotate(15 10 11)'/%3E%3Cellipse cx='28' cy='6' rx='5' ry='2.4' transform='rotate(-35 28 6)'/%3E%3Cellipse cx='24' cy='11' rx='5' ry='2.4' transform='rotate(-15 24 11)'/%3E%3Ccircle cx='17' cy='13' r='2.2'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat}
.status-awaiting_user .fx-wait,.status-error .fx-error{display:grid}
.status-idle .fx-idle,.status-completed .fx-done{display:block}

/* model badge O/S/H */
.model-badge{position:absolute;left:0;bottom:8px;display:grid;place-items:center;width:17px;height:17px;border-radius:50%;background:#fff;font:800 9px/1 var(--font-latin);border:1.5px solid currentColor;box-shadow:0 2px 6px -2px rgb(var(--p-shadow)/.4)}
.model-opus{color:#6d3fc0}.model-sonnet{color:#1f6aa5}.model-haiku{color:#2f7a5c}.model-fable{color:#a5582a}

/* states */
.status-running .fig-aura{opacity:.9;animation:fig-aura 1.8s ease-in-out infinite}
.status-running .fig-art{animation:fig-breathe 2.4s ease-in-out infinite}
/* work pose: one clock on .fig-art drives both images, so the base pose and the work pose can never drift apart */
@property --pose{syntax:'<number>';inherits:true;initial-value:0}
.status-running .fig-art:has(.fig-work.ready){animation:fig-breathe 2.4s ease-in-out infinite,fig-pose 1.6s steps(1,end) infinite}
.status-running .fig-art:has(.fig-work.ready) .fig-work{opacity:var(--pose)}
.status-running .fig-art:has(.fig-work.ready) .fig-img{opacity:calc(1 - var(--pose))}
.status-awaiting_user .fig-art{animation:fig-sway 3.6s ease-in-out infinite}
.status-awaiting_user .fx-wait{animation:fig-pop 2.4s ease-in-out infinite}
.status-idle .fig-art{opacity:.88}
.status-idle .fig-blink.ready{opacity:1}
.status-idle .fx-idle{animation:fig-doze 3.6s ease-in-out infinite}
.status-completed .fx-done{animation:fig-shine 3.2s ease-in-out infinite}
.status-error .fig-art{animation:fig-shake .5s ease-in-out 1}
.status-error .fig-ring{box-shadow:0 0 0 1.5px rgb(168 38 28/.6);background:radial-gradient(closest-side,rgb(208 69 58/.2),transparent)}
.status-unknown .fig-art{filter:grayscale(.7);opacity:.65}
/* blink now and then, staggered so a room never blinks in unison (not while asleep or working) */
.figure:not(.status-idle):not(.status-running) .fig-blink.ready{animation:fig-blink 5.2s steps(1,end) infinite}
.beat-1 .fig-blink.ready,.beat-1 .fig-art{animation-delay:-1.3s}
.beat-2 .fig-blink.ready,.beat-2 .fig-art{animation-delay:-2.6s}
.beat-3 .fig-blink.ready,.beat-3 .fig-art{animation-delay:-3.9s}

/* on the map */
.map-agent .fig-full{margin-top:-9px;filter:drop-shadow(0 8px 6px rgb(var(--p-shadow)/.16))}
.map-agent .agent-halo{display:none}
.map-agent .agent-identity{margin-top:3px}
.map-agent:hover .fig-ring{box-shadow:0 0 0 2px rgb(var(--ring)/.7)}
.map-agent.is-selected .fig-ring{box-shadow:0 0 0 2.5px var(--p),0 0 0 7px rgb(var(--p-rgb)/.14);background:radial-gradient(closest-side,rgb(var(--p-light-rgb)/.5),transparent)}
.map-agent.is-swimming{z-index:25}
.map-agent.is-swimming .fig-art{animation:fig-walk .42s ease-in-out infinite!important}
.map-agent.is-swimming .fig-fx,.map-agent.is-swimming .fig-aura{display:none}
.map-agent.is-swimming .fig-work{opacity:0!important}
.map-agent.is-swimming .fig-img{opacity:1!important}

/* inspector and detail avatars */
.inspector-avatar{width:116px;height:116px;margin:4px auto 10px;padding:0;border-radius:50%;background:radial-gradient(closest-side,rgb(var(--p-light-rgb)/.45),rgb(var(--p-light-rgb)/.12));box-shadow:inset 0 0 0 1px rgb(255 255 255/.8),var(--shadow-soft)}
.detail-avatar .figure{width:58px;height:auto}

@keyframes fig-breathe{0%,100%{transform:scale(1,1)}50%{transform:scale(1.012,1.028)}}
@keyframes fig-aura{0%,100%{opacity:.45}50%{opacity:.95}}
@keyframes fig-pose{0%{--pose:0}50%{--pose:1}}
@keyframes fig-sway{0%,100%{transform:rotate(0)}30%{transform:rotate(-2.5deg)}70%{transform:rotate(2deg)}}
@keyframes fig-pop{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
@keyframes fig-doze{0%{opacity:0;transform:translate(0,4px)}40%,60%{opacity:.85}100%{opacity:0;transform:translate(5px,-8px)}}
@keyframes fig-shine{0%,100%{opacity:.7}50%{opacity:1}}
@keyframes fig-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-2px)}50%{transform:translateX(2px)}75%{transform:translateX(-1px)}}
@keyframes fig-blink{0%{opacity:0}94%{opacity:1}97%{opacity:0}}
@keyframes fig-walk{0%,100%{transform:translateY(0) rotate(-1.5deg)}50%{transform:translateY(-4px) rotate(1.5deg)}}
@media(prefers-reduced-motion:reduce){.figure *{animation:none!important}.figure .fig-img{opacity:1!important}.figure .fig-work{opacity:0!important}.status-running .fig-aura{opacity:.8}}
