:root{
  --bg:#F3F2F6; --surface:#FFFFFF; --text:#1B1626; --muted:#6A6577; --line:#E2DFE8;
  --accent:#00A870;
  --skin-ink:#1B1626; --skin-eye:#00A870;
  --wall:#E8E6EE; --dot:#CFCBD9; --shadow:rgba(27,22,38,.12);
  --blush:#FF8FA8; --tear:#5AAEF0; --anger:#E5484D; --heart:#F0567A; --dust:#A39DB0;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    color-scheme:dark;
    --bg:#0D1117; --surface:#151A22; --text:#E9EDF2; --muted:#8C95A3; --line:#252C37;
    --accent:#2FD59B;
    --skin-ink:#FFFFFF; --skin-eye:#2FD59B;
    --wall:#10151C; --dot:#232B37; --shadow:rgba(0,0,0,.32);
    --blush:#FF7F9E; --tear:#6BBDF7; --anger:#FF6369; --heart:#FF6F93; --dust:#5B6472;
  }
}
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0D1117; --surface:#151A22; --text:#E9EDF2; --muted:#8C95A3; --line:#252C37;
  --accent:#2FD59B;
  --skin-ink:#FFFFFF; --skin-eye:#2FD59B;
  --wall:#10151C; --dot:#232B37; --shadow:rgba(0,0,0,.32);
  --blush:#FF7F9E; --tear:#6BBDF7; --anger:#FF6369; --heart:#FF6F93; --dust:#5B6472;
}
*{box-sizing:border-box}
html,body{margin:0; height:100%; overflow:hidden}
body{
  font-family:system-ui,-apple-system,"Segoe UI","Noto Sans",sans-serif;
  font-size:15px; line-height:1.55; color:var(--text);
  user-select:none; -webkit-user-select:none;
}
/* line icons (ui.js): one line weight at every size, the same as the settings window's */
svg[viewBox="0 0 24 24"][stroke="currentColor"]{stroke-width:1.6px}
svg[viewBox="0 0 24 24"][stroke="currentColor"] *{vector-effect:non-scaling-stroke}
/* the app language is on <html lang> (web/i18n.js): each CJK script gets its own fonts, Latin and Cyrillic the system's */
:lang(zh) body{font-family:"Noto Sans SC","PingFang SC","Microsoft YaHei",system-ui,sans-serif}
:lang(zh-Hant) body{font-family:"Noto Sans TC","PingFang TC","Microsoft JhengHei",system-ui,sans-serif}
:lang(ja) body{font-family:"Noto Sans JP","Hiragino Sans","Hiragino Kaku Gothic ProN","Yu Gothic UI",Meiryo,system-ui,sans-serif}
:lang(ko) body{font-family:"Noto Sans KR","Apple SD Gothic Neo","Malgun Gothic",system-ui,sans-serif}
/* in a browser tab the page draws its own wall and floor; in the pet window it is transparent */
body.tab{
  background-color:var(--wall);
  background-image:radial-gradient(var(--dot) 1.2px, transparent 1.3px);
  background-size:22px 22px;
}
body.tab .floor{position:fixed; left:0; right:0; bottom:0; height:48px; background:var(--surface); border-top:1px solid var(--line)}
/* the wall (stage.js lightWall): a soft light and a lens of bigger, eye-colored dots follow the pointer; both are
   composited layers moved by transform, under everything else on the wall */
.wall{isolation:isolate}
.wall-glow, .wall-lens{position:absolute; left:0; top:0; z-index:-1; pointer-events:none; opacity:0; transition:opacity .45s ease; will-change:transform, opacity}
.wall-lit > .wall-glow, .wall-lit > .wall-lens{opacity:1}
/* --glow: the body's color (stage.js setGlow); without one, the settings window's theme color, else the page's */
.wall-glow{width:560px; height:560px; border-radius:50%; background:radial-gradient(circle closest-side, color-mix(in srgb, var(--glow, var(--host-accent, var(--accent))) 16%, transparent), transparent)}
.wall-lens{
  width:300px; height:300px; overflow:hidden; border-radius:50%;
  -webkit-mask-image:radial-gradient(circle closest-side, #000 0, rgba(0,0,0,.4) 50%, transparent 100%);
  mask-image:radial-gradient(circle closest-side, #000 0, rgba(0,0,0,.4) 50%, transparent 100%);
}
.wall-lens-grid{
  position:absolute; left:0; top:0; width:4000px; height:3000px; will-change:transform;
  background-image:radial-gradient(color-mix(in srgb, var(--glow, var(--host-accent, var(--accent))) 70%, var(--dot)) 2.3px, transparent 2.6px); background-size:22px 22px;
}
/* the floor's row of taskbar icons, decoration only */
.floor-icons{position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:26px; color:var(--muted); opacity:.75; pointer-events:none}
.floor-icons svg{width:18px; height:18px; display:block}
/* the night/day button at the stage's top left */
.stage-mode{
  position:absolute; top:12px; left:12px; z-index:2; display:grid; place-items:center; width:32px; height:32px; padding:0;
  border-radius:50%; border:1px solid var(--line); background:var(--surface); color:var(--text); cursor:pointer;
  box-shadow:0 4px 12px var(--shadow); transition:color .15s, border-color .15s, transform .15s;
}
body.tab .stage-mode{position:fixed}
.stage-mode:hover{color:var(--skin-eye); border-color:var(--skin-eye); transform:scale(1.06)}
.stage-mode svg{width:17px; height:17px; display:block}
body.desk{background:transparent}
body.desk .floor{display:none}
.stage{position:fixed; inset:0; touch-action:none}
/* the body's sandboxed frame: transparent (a colour scheme unlike the frame's would give it a backdrop) and never under the pointer */
.figure-layer{position:absolute; inset:0; pointer-events:none}
/* the frame's window onto the stage: body-host cuts it down to the body's surroundings while the halo is on */
.figure-layer .figure-clip{position:absolute; inset:0; pointer-events:none}
.figure-layer iframe{position:absolute; inset:0; width:100%; height:100%; border:0; background:transparent; color-scheme:normal; pointer-events:none}


/* activity borrows the speech bubble, but never takes the pointer or competes with dialogue */
.bubble.status{
  display:flex; align-items:center; gap:6px;
  max-width:min(220px, calc(100vw - 20px)); padding:6px 10px;
  font-size:12.5px; line-height:1.4; pointer-events:none; user-select:none; transition:opacity .2s;
}
.status[hidden]{display:none}
.status.fading{opacity:0}
.bubble.status.pop{animation:status-in .24s cubic-bezier(.3,1.4,.5,1)}
.status-text{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.status-icon{display:flex; flex:none; color:color-mix(in srgb, var(--skin-eye) 78%, var(--skin-ink))}
.status-icon svg{width:14px; height:14px; overflow:visible}
.status[data-kind="think"]{justify-content:center}
.status[data-kind="think"] .status-text{display:none}
.status[data-kind="think"] .status-icon svg{width:24px}
.status-icon svg, .status-icon svg *{transform-box:fill-box; transform-origin:center}
.status[data-kind="think"] circle{animation:status-think 1.3s ease-in-out infinite}
.status[data-kind="think"] circle:nth-child(2){animation-delay:.16s}
.status[data-kind="think"] circle:nth-child(3){animation-delay:.32s}
.status .scan{animation:status-read 1.8s ease-in-out infinite}
.status .flap{transform-origin:center bottom; animation:status-browse 1.6s ease-in-out infinite}
.status[data-kind="search"] svg{animation:status-search 2s linear infinite}
.status[data-kind="write"] svg{animation:status-write 1.2s ease-in-out infinite}
.status .lid{transform-origin:left bottom; animation:status-delete 1.5s ease-in-out infinite}
.status .arrow{animation:status-save 1.5s ease-in-out infinite}
.status .pupil{animation:status-look 2.2s ease-in-out infinite}
.status .ripple{animation:status-click 1.2s ease-out infinite}
.status .wheel{animation:status-scroll 1.1s ease-in-out infinite}
.status .keycap{animation:status-type .9s ease-in-out infinite}
.status[data-kind="wait"] svg{animation:status-wait 2.8s ease-in-out infinite}
.status[data-kind="alarm"] svg{animation:status-alarm 1.8s ease-in-out infinite}
.status[data-kind="work"] svg{animation:status-work 4s linear infinite}
@keyframes status-in{from{transform:translateY(3px) scale(.92); opacity:0}}
@keyframes status-think{0%,60%,100%{transform:none; opacity:.45} 30%{transform:translateY(-3px); opacity:1}}
@keyframes status-read{0%,100%{transform:translateY(0); opacity:.5} 70%{transform:translateY(6px); opacity:1}}
@keyframes status-browse{50%{transform:scaleY(.72) skewX(-8deg)}}
@keyframes status-search{0%,100%{transform:translate(-1px,0)} 25%{transform:translate(0,-1px)} 50%{transform:translate(1px,0)} 75%{transform:translate(0,1px)}}
@keyframes status-write{0%,100%{transform:translate(-1px,1px) rotate(-5deg)} 50%{transform:translate(1px,-1px) rotate(5deg)}}
@keyframes status-delete{20%,60%{transform:rotate(-12deg)} 40%,80%{transform:none}}
@keyframes status-save{0%{transform:translateY(-3px); opacity:.3} 70%,100%{transform:translateY(2px); opacity:1}}
@keyframes status-look{25%{transform:translateX(-2px)} 75%{transform:translateX(2px)}}
@keyframes status-click{0%{transform:scale(.7); opacity:0} 35%{opacity:1} 100%{transform:scale(1.4); opacity:0}}
@keyframes status-scroll{0%{transform:translateY(-1px) scaleY(1); opacity:.4} 50%{transform:translateY(2px) scaleY(.5); opacity:1} 100%{transform:translateY(-1px) scaleY(1); opacity:.4}}
@keyframes status-type{40%,65%{transform:translateY(3px)}}
@keyframes status-wait{0%,30%{transform:rotate(0)} 60%,100%{transform:rotate(180deg)}}
@keyframes status-alarm{10%,30%{transform:rotate(-10deg)} 20%,40%{transform:rotate(10deg)} 50%,100%{transform:none}}
@keyframes status-work{to{transform:rotate(360deg)}}

/* bubbles; the min-width keeps an empty one (its line not typed yet) wide enough for the tail to sit on its bottom edge */
.bubble{
  position:fixed; left:0; top:0; z-index:3; width:max-content; min-width:46px; max-width:min(300px, calc(100vw - 20px));
  padding:10px 14px; border-radius:18px; background:var(--surface); color:var(--text);
  border:2.5px solid var(--skin-ink); box-shadow:0 8px 22px var(--shadow);
  font-size:14.5px; line-height:1.55;
  transform-origin:var(--tail, 50%) calc(100% + 10px);
}
/* tail: an outline triangle whose base lies inside the border, so its sides join the border, and a
   surface triangle one line width inside it that opens the border between the sides. Neither is
   rotated. y=0 is the padding edge, the border spans 0..2.5, the tip sits 8.5px past the border, at
   --tail from the outer left edge (the same point transform-origin scales from). The outline's base
   sits .75px into the border: the border is drawn on whole device pixels and the triangle is not, so a
   base on the border's inner edge showed as a nub above the line at each corner of the tail. */
.bubble::before, .bubble::after{
  content:""; position:absolute; left:calc(var(--tail, 50%) - 13.5px); bottom:-11px; width:22px; height:11.5px;
}
.bubble::before{background:var(--skin-ink); clip-path:path('M0.75 1.25 L8.9 9.4 Q11 11.5 13.1 9.4 L21.25 1.25 Z')}
.bubble::after{background:var(--surface); clip-path:path('M3.04 0 L10.53 7.49 Q11 7.96 11.47 7.49 L18.96 0 Z')}
.bubble.heard{border-style:dashed; box-shadow:none; max-width:min(260px, calc(100vw - 20px))}
.bubble.heard::before, .bubble.heard::after{display:none}
.bubble.ask{min-width:min(236px, calc(100vw - 20px)); padding-right:32px}
.bubble.pop{animation:bubble-in .26s cubic-bezier(.3,1.5,.5,1)}
@keyframes bubble-in{from{transform:scale(.5); opacity:0}}
.b-text{margin:0; min-height:1.55em; white-space:pre-wrap; text-wrap:pretty}
.b-text .interim{color:var(--muted)}
.caret{display:inline-block; width:2px; height:1.05em; margin-left:2px; vertical-align:-2px; background:var(--skin-eye); animation:caret 1s steps(1) infinite}
@keyframes caret{50%{opacity:0}}
.b-hint{display:block; margin-top:2px; font-size:12px; color:var(--muted)}
.b-close{position:absolute; top:5px; right:6px; width:24px; height:24px; padding:0; border:0; border-radius:50%; background:none; color:var(--muted); font-size:18px; line-height:1; cursor:pointer}
.b-close:hover{color:var(--text)}
.b-opts{display:flex; flex-direction:column; gap:6px; margin:10px -18px 2px 0}
.b-opt, .b-own{animation:opt-in .24s cubic-bezier(.3,1.4,.5,1) both; transition:border-color .15s, opacity .2s}
@keyframes opt-in{from{transform:translateY(6px) scale(.92); opacity:0}}
.b-opt{
  display:flex; align-items:center; gap:8px; width:100%; text-align:left; font:inherit; font-size:14px;
  padding:6px 10px; border-radius:11px; border:1.5px solid var(--line); background:var(--bg); color:var(--text); cursor:pointer;
}
.b-opt:hover, .b-opt.chosen{border-color:var(--skin-eye)}
.b-opt kbd{
  flex:none; display:grid; place-items:center; width:20px; height:20px; border-radius:50%;
  border:2px solid var(--skin-eye); font:500 11px/1 ui-monospace,Consolas,monospace; color:var(--text);
}
.b-own{display:flex; align-items:center; gap:6px; padding:3px 3px 3px 10px; border-radius:11px; border:1.5px dashed var(--line); background:var(--bg)}
.b-own:focus-within, .b-own.chosen{border-style:solid; border-color:var(--skin-eye)}
.b-own input{flex:1; min-width:0; border:0; background:transparent; font:inherit; font-size:14px; color:var(--text); outline:none; padding:4px 0}
.b-own button[type="submit"]{flex:none; font:inherit; font-size:12.5px; padding:4px 10px; border-radius:8px; border:0; background:var(--text); color:var(--surface); cursor:pointer}
.b-expand{flex:none; display:grid; place-items:center; width:26px; height:26px; padding:0; border:0; border-radius:50%; background:none; color:var(--muted); cursor:pointer}
.b-expand:hover{color:var(--text)}
.b-expand svg{width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.6px; stroke-linecap:round; stroke-linejoin:round}
.b-expand svg *{vector-effect:non-scaling-stroke}
.b-opt.dim, .b-own.dim{opacity:.35}
/* an app's conversation: one step per bubble, with the answer's controls under Coo's line */
.d-mark{color:var(--skin-eye); font-weight:700}
.bubble.talk{width:min(318px, calc(100vw - 20px)); max-width:none; padding:11px 14px 12px}
.d-top{display:flex; align-items:center; min-height:14px; margin:-2px 22px 5px 0}
.bubble.talk .b-close{top:4px; right:5px}
.d-dots{display:flex; gap:4px}
.d-dots i{width:6px; height:6px; border-radius:3px; background:var(--line); transition:width .25s, background .25s}
.d-dots i.past{background:color-mix(in srgb, var(--skin-eye) 45%, var(--line))}
.d-dots i.on{width:16px; background:var(--skin-eye)}
.d-body{display:flex; flex-direction:column; gap:8px; margin-top:10px}
.d-body > *{animation:opt-in .24s cubic-bezier(.3,1.4,.5,1) both}
.d-body button, .d-body input{font:inherit}
.d-row{display:flex; flex-wrap:wrap; justify-content:flex-end; gap:6px}
.d-pill{
  padding:5px 14px; border-radius:999px; border:1.5px solid var(--line); background:var(--bg); color:var(--text);
  font-size:13.5px; cursor:pointer; transition:border-color .15s, background .15s, transform .15s;
}
.d-pill:hover{border-color:var(--skin-ink)}
.d-pill.primary{background:var(--skin-ink); border-color:var(--skin-ink); color:var(--surface); font-weight:600}
.d-pill.primary:hover{background:var(--skin-eye); border-color:var(--skin-eye)}
.d-pill.chosen{animation:pill-pick .26s cubic-bezier(.3,1.5,.5,1)}
@keyframes pill-pick{45%{transform:scale(1.1)}}
.d-body button:disabled{cursor:default}
/* the talk key as a key cap that keeps being pressed */
.d-keys{display:flex; justify-content:center; padding:4px 0 2px}
.d-key{
  display:inline-block; padding:5px 16px 4px; border-radius:10px; border:2px solid var(--skin-ink); border-bottom-width:5px;
  background:var(--surface); color:var(--text); font:600 14px/1.3 ui-monospace,Consolas,monospace;
  animation:key-press 1.8s ease-in-out infinite;
}
@keyframes key-press{0%,35%,100%{transform:none; border-bottom-width:5px} 45%,80%{transform:translateY(3px); border-bottom-width:2px; border-color:var(--skin-eye); color:var(--skin-eye)}}
/* tapped, then held: a quick press, a quick release, and a long press lit in the eye color */
.d-key.taps{animation:key-taphold 2.2s ease-in-out infinite}
@keyframes key-taphold{
  0%,20%,100%{transform:none; border-bottom-width:5px}
  24%,28%{transform:translateY(3px); border-bottom-width:2px}
  32%,36%{transform:none; border-bottom-width:5px}
  40%,82%{transform:translateY(3px); border-bottom-width:2px; border-color:var(--skin-eye); color:var(--skin-eye)}
  86%{transform:none; border-bottom-width:5px}
}
.d-keys{align-items:center; gap:6px}
.d-taps{font:700 12px/1 ui-monospace,Consolas,monospace; color:var(--muted)}
/* choice cards: the picked one lit in the eye color */
.d-cards{display:grid; grid-template-columns:repeat(auto-fit, minmax(80px, 1fr)); gap:6px}
/* while the cards grow to the rows the 「more」 card unfolded, the new rows stay inside them; the margin keeps level tags whole */
.d-cards.unfolding{overflow:clip; overflow-clip-margin:8px}
.d-card{
  position:relative; display:flex; flex-direction:column; align-items:center; gap:4px; padding:10px 4px 8px; border-radius:14px;
  border:1.5px solid var(--line); background:var(--bg); color:var(--text); cursor:pointer;
  animation:opt-in .24s cubic-bezier(.3,1.4,.5,1) both; transition:border-color .15s, background .15s, transform .15s, color .15s;
}
.d-card:hover{transform:translateY(-2px); border-color:var(--skin-ink)}
.d-card.on{border-color:var(--skin-eye); background:color-mix(in srgb, var(--skin-eye) 14%, var(--bg)); color:var(--skin-eye)}
.d-cardic svg{width:24px; height:24px; display:block}
.d-cardimg{width:28px; height:28px; display:block; padding:3px; border-radius:7px; background:#fff; box-sizing:border-box}
.d-card.on .d-cardimg{animation:card-bob .5s cubic-bezier(.3,1.5,.5,1)}
.d-cardlbl{font-size:13px; color:var(--text)}
.d-cardnote{font-size:11px; line-height:1.35; color:var(--muted); text-align:center}
.d-level{
  position:absolute; top:-7px; right:-5px; min-width:18px; padding:0 4px; border-radius:7px; border:1.5px solid var(--surface);
  background:var(--muted); color:var(--surface); font:700 10px/15px system-ui,sans-serif;
}
.d-card.on .d-level{background:var(--skin-eye)}
.d-card.on .d-cardic{animation:card-bob .5s cubic-bezier(.3,1.5,.5,1)}
@keyframes card-bob{40%{transform:translateY(-4px) rotate(-8deg)}}
/* a text box with its send button; a secret one can be peeked at */
.d-field{display:flex; align-items:center; gap:4px; padding:3px 3px 3px 11px; border-radius:12px; border:1.5px solid var(--line); background:var(--bg)}
.d-field:focus-within{border-color:var(--skin-eye)}
.d-field input{flex:1; min-width:0; border:0; background:transparent; font-size:14px; color:var(--text); outline:none; padding:5px 0; user-select:text; -webkit-user-select:text}
.d-field .d-peek{flex:none; display:grid; place-items:center; width:26px; height:26px; padding:0; border:0; border-radius:50%; background:none; color:var(--muted); cursor:pointer}
.d-field .d-peek:hover{color:var(--text)}
.d-field .d-peek svg{width:16px; height:16px}
.d-send{flex:none; padding:5px 12px; border-radius:9px; border:0; background:var(--skin-ink); color:var(--surface); font-size:13px; font-weight:600; cursor:pointer}
.d-send:hover{background:var(--skin-eye)}
.d-field.shake{animation:field-shake .32s}
@keyframes field-shake{20%,60%{transform:translateX(-4px)} 40%,80%{transform:translateX(4px)}}
.d-links{display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:12.5px}
.d-link{display:inline-flex; align-items:center; gap:3px; color:var(--skin-eye); text-decoration:none}
.d-link:hover{text-decoration:underline}
.d-link svg{width:12px; height:12px}
.d-alt{margin-left:auto; padding:2px 4px; border:0; background:none; color:var(--muted); font-size:12.5px; cursor:pointer}
.d-alt:hover{color:var(--text); text-decoration:underline}
/* a progress bar; without a fraction a band slides along it */
.d-bar{position:relative; height:8px; border-radius:4px; background:var(--line); overflow:hidden}
.d-bar i{position:absolute; left:0; top:0; bottom:0; width:0; border-radius:4px; background:linear-gradient(90deg, var(--skin-eye), color-mix(in srgb, var(--skin-eye) 55%, #4CC9F0)); transition:width .4s ease}
.d-bar.wait i{width:35%; animation:bar-slide 1.2s ease-in-out infinite}
@keyframes bar-slide{from{left:-35%} to{left:100%}}
.d-barlbl{display:flex; justify-content:space-between; gap:8px; font-size:12px; color:var(--muted)}
.d-barlbl b{font-weight:600; font-variant-numeric:tabular-nums; color:var(--text)}
.trail{position:fixed; inset:0; pointer-events:none; z-index:3}
.trail i{position:absolute; border-radius:50%; border:2.5px solid var(--skin-ink); background:var(--surface); animation:trail-bob 1.2s ease-in-out infinite}
.trail i:nth-child(2){animation-delay:.15s}
.trail i:nth-child(3){animation-delay:.3s}
@keyframes trail-bob{50%{transform:translateY(-3px)}}

/* context menu: the bot and its run controls on top, the actions as icon tiles below */
.menu{
  position:fixed; z-index:5; width:max-content; padding:6px; border-radius:16px;
  background:var(--surface); border:2px solid var(--skin-ink); box-shadow:0 10px 26px var(--shadow);
  font-size:14px; animation:bubble-in .18s cubic-bezier(.3,1.5,.5,1);
}
.menu button{font:inherit; cursor:pointer}
.menu .m-head{display:flex; align-items:center; gap:8px; min-height:40px; padding:3px 2px 7px 4px; margin-bottom:4px; border-bottom:1px solid var(--line)}
.m-avatar{flex:none; width:30px; height:30px; border-radius:50%; overflow:hidden; background:var(--bg); border:1.5px solid var(--line)}
.m-avatar img, .m-avatar svg{width:100%; height:100%; display:block; object-fit:cover}
/* the name takes what room the buttons leave and does not widen the menu: a long one ends in … (its title has it all) */
.m-name{flex:1 1 0; width:0; min-width:4em; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.m-acts{flex:none; display:flex; gap:2px}
/* asking to quit: the prompt takes the avatar's room, so the fixed-width menu keeps it readable */
.m-head.confirm .m-avatar{display:none}
/* the question wraps rather than ending in …: the menu keeps its opening width (pet-app openMenu) */
.m-head.confirm .m-name{white-space:normal; overflow-wrap:anywhere; line-height:1.3}
.menu .m-act{display:grid; place-items:center; width:30px; height:30px; padding:0; border:0; border-radius:50%; background:none; color:var(--muted)}
.menu .m-act:hover{background:var(--bg); color:var(--text)}
.menu .m-act svg{width:17px; height:17px; display:block}
/* running: the pause button in the accent color, as the console's rail shows the live run */
.menu .m-act.run:not(.paused){color:var(--skin-eye)}
.menu .m-act.power:hover, .menu .m-act.danger{color:var(--anger)}
.menu .m-act.text{width:auto; padding:0 10px; border-radius:15px; font-size:12.5px; white-space:nowrap}
/* six actions in three columns spread over the menu's width (the header no longer widens it: see .m-name) */
.m-grid{display:grid; grid-template-columns:repeat(3, 1fr); justify-items:center; gap:8px 10px; padding:4px 2px 2px}
/* every entry is a round icon button; a switch that is on is lit in the eye color, one that is off keeps its crossed-out icon on a dashed ring */
.m-tile{
  position:relative; display:grid; place-items:center; width:46px; height:46px; padding:0; border-radius:50%;
  border:1.5px solid var(--line); background:none; color:var(--text); transition:background .15s, border-color .15s, color .15s;
}
.m-tile:hover, .m-tile:focus-visible{background:var(--bg); border-color:var(--skin-ink); outline:none}
.m-tile .ic{position:relative; display:grid; place-items:center}
.m-tile .ic svg{width:22px; height:22px; display:block}
.m-tile.on{background:color-mix(in srgb, var(--skin-eye) 16%, transparent); border-color:var(--skin-eye); color:var(--skin-eye)}
.m-tile.off{color:var(--muted); border-style:dashed}
.badge{
  position:absolute; right:-9px; bottom:-8px; padding:0 3px; border-radius:6px; border:1.5px solid var(--surface);
  background:var(--skin-eye); color:var(--surface); font:700 8.5px/12px ui-monospace,Consolas,monospace; letter-spacing:.02em; text-transform:uppercase;
}
/* dressing up: on hover the shirt wiggles through the palettes and three dots of color pop out */
.m-tile.dress:hover, .tool[data-action="dress"]:hover{animation:dress-hue 1.6s linear infinite}
.m-tile.dress:hover .ic, .tool[data-action="dress"]:hover .ic{animation:dress-wiggle .5s ease-in-out}
.m-tile.dress::before, .m-tile.dress::after, .m-tile.dress .ic::before{
  content:""; position:absolute; width:6px; height:6px; border-radius:50%; opacity:0; pointer-events:none;
}
.m-tile.dress::before{left:-2px; top:4px; background:#FF6B8B}
.m-tile.dress::after{right:-3px; top:0; background:#FFC43D}
.m-tile.dress .ic::before{left:7px; top:-19px; background:#4CC9F0}
.m-tile.dress:hover::before{animation:dress-pop .7s ease-out infinite}
.m-tile.dress:hover::after{animation:dress-pop .7s .23s ease-out infinite}
.m-tile.dress:hover .ic::before{animation:dress-pop .7s .46s ease-out infinite}
@keyframes dress-hue{
  0%{color:#FF6B8B; border-color:#FF6B8B} 20%{color:#FF9F43; border-color:#FF9F43} 40%{color:#FFC43D; border-color:#FFC43D}
  60%{color:#2FD59B; border-color:#2FD59B} 80%{color:#4CC9F0; border-color:#4CC9F0} 100%{color:#B388FF; border-color:#B388FF}
}
@keyframes dress-wiggle{25%{transform:rotate(-12deg)} 75%{transform:rotate(12deg)}}
@keyframes dress-pop{0%{opacity:0; transform:scale(.3) translate(0, 0)} 30%{opacity:1} 100%{opacity:0; transform:scale(1.1) translate(0, -8px)}}
/* hover buttons: the actions chosen in settings, in columns of up to three beside the pet */
.tools{position:fixed; left:0; top:0; z-index:4; display:grid; grid-auto-flow:column; gap:8px; animation:bubble-in .18s cubic-bezier(.3,1.5,.5,1)}
.tools[hidden]{display:none}
.tool{
  position:relative; display:grid; place-items:center; width:34px; height:34px; padding:0; border-radius:50%; cursor:pointer;
  background:var(--surface); color:var(--text); border:2px solid var(--skin-ink); box-shadow:0 6px 16px var(--shadow);
}
.tool .ic{position:relative; display:grid; place-items:center}
.tool:hover{color:var(--skin-eye); border-color:var(--skin-eye)}
.tool svg{width:20px; height:20px; display:block}
/* the key badge sits off the button's lower right, clear of the icon */
.tool .badge{right:-14px; bottom:-9px}
/* the voice switch: struck through when off, muted while the recognizer is not ready, lit while hearing */
.tool.off{color:var(--muted)}
/* not ready yet: muted, at the same line weight (a faded icon reads as a thinner one) */
.tool.waiting{color:var(--muted)}
.tool.live{color:var(--skin-eye); border-color:var(--skin-eye)}
/* held down: a ring closes in; when it is full the sentence is sent */
.tool.holding::after{
  content:""; position:absolute; inset:-7px; border-radius:50%; border:2.5px solid var(--skin-eye); pointer-events:none;
  animation:hold-ring var(--hold, .5s) linear forwards;
}
@keyframes hold-ring{from{transform:scale(.72); opacity:0} to{transform:scale(1); opacity:1}}
.tool.sent{animation:tool-sent .36s cubic-bezier(.3,1.5,.5,1)}
@keyframes tool-sent{45%{transform:scale(1.2)}}
@media (prefers-reduced-motion: reduce){.wall-glow, .wall-lens{transition:none}}
@media (prefers-reduced-motion: reduce){.bubble.status.pop, .status .status-icon svg, .status .status-icon svg *, .bubble.pop, .b-opt, .b-own, .d-body > *, .d-card, .d-key, .d-key.taps, .d-bar.wait i, .d-card.on .d-cardic, .d-field.shake, .d-pill.chosen, .trail i, .caret, .menu, .tools, .tool.holding::after, .tool.sent, .m-tile, .m-tile::before, .m-tile::after, .m-tile .ic, .m-tile .ic::before{animation:none}}
