*{box-sizing:border-box}body{margin:var(--space-0);background:var(--color-room);color:var(--color-ink);font-family:var(--font-body);font-size:var(--text-base);line-height:var(--rhythm-body-leading)}
#exploration{margin:var(--space-6) 0;padding:var(--space-4);background:var(--color-paper);border:var(--stroke-thin) solid var(--color-line);border-radius:var(--radius-card);overflow-wrap:anywhere}
#exploration h2{font-size:var(--text-base);line-height:var(--leading-heading);margin:0 0 var(--space-3)}
#exploration p{font-size:var(--text-sm);line-height:var(--leading-body);margin:var(--space-3) 0}
#exploration a{color:var(--color-accent)}
#exploration details a{display:block;margin-top:var(--space-2)}
.exploration-actions{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-3);margin-top:var(--space-4);font-size:var(--text-sm)}
button,textarea{font:inherit}button{min-height:var(--button-height);font-size:var(--button-font-size);font-weight:var(--button-weight);cursor:pointer;color:inherit;border:var(--stroke-thin) solid transparent;background:transparent;padding:var(--button-padding-y) var(--button-padding-x);border-radius:var(--button-radius)}button:hover{background:var(--color-accent-soft)}button:disabled{opacity:var(--button-disabled-opacity);cursor:default}button:focus-visible,a:focus-visible,textarea:focus-visible{outline:var(--outline) solid var(--color-accent);outline-offset:var(--offset)}[hidden]{display:none!important}
.room{position:relative;max-width:var(--room-width);min-height:100svh;margin:auto;display:grid;grid-template-columns:var(--scene-width) var(--talk-width);grid-template-rows:var(--size-site-header) auto;align-content:start;isolation:isolate}
.topbar{grid-column:1/-1;display:flex;align-items:center;gap:var(--space-6);padding:var(--space-4) var(--space-8);z-index:var(--z-header)}.brand{font-family:var(--font-brand);font-size:var(--text-brand);font-weight:var(--sally-weight-brand);color:var(--color-ink);text-decoration:none;letter-spacing:calc(var(--tracking)*-1)}.brand span{color:var(--color-accent);font-size:var(--sally-text-title);margin-left:var(--space-1)}.eyebrow,.small-title{text-transform:uppercase;letter-spacing:var(--tracking);font-size:var(--text-xs);color:var(--color-muted)}nav{margin-left:auto;display:flex;align-items:center;gap:var(--space-1)}.topbar nav button:not(.utility-switch){background:transparent;border-color:transparent;font-size:var(--button-font-size)}
.scene{position:sticky;top:var(--space-0);height:clamp(var(--room-min),calc(100svh - var(--size-market-ticker) - var(--size-site-header) - var(--space-6)),var(--scene-max));overflow:hidden;background:var(--scene-gradient);border-radius:var(--radius-card);margin:var(--space-0) var(--space-6) var(--space-6);z-index:var(--z-scene)}.scene:after{content:'';position:absolute;inset:0;background:var(--scene-fade);pointer-events:none}.window-glow{position:absolute;inset:0;background:var(--light-gradient)}.portrait{position:absolute;top:var(--portrait-top);left:50%;transform:translateX(-50%);width:var(--portrait-width);max-width:var(--portrait-max);margin:0}.portrait img{width:100%;display:block;border-radius:var(--radius-card);animation:breathe var(--motion-slow) var(--motion-ease) infinite alternate;transform-origin:bottom center}.scene-caption{position:absolute;top:var(--space-8);left:var(--space-8);display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm)}.scene-dot{width:var(--space-2);height:var(--space-2);border-radius:var(--radius-pill);background:var(--color-sage)}
.conversation{align-self:start;min-width:0;padding:var(--welcome-top) var(--space-12) var(--space-12) var(--space-4);z-index:var(--z-content)}h1{font-weight:var(--weight-medium);font-size:var(--text-heading);line-height:var(--leading-title);margin:var(--space-4) 0}h2{font-size:var(--sally-text-title);margin:var(--space-2) 0}p{margin:var(--space-3) 0}.room-heading p,.consent,small{color:var(--color-muted)}.consent{font-size:var(--text-sm);margin:var(--space-8) 0}.primary,.send{background:var(--button-primary-bg);color:var(--button-primary-fg);font-weight:var(--button-weight)}.primary:hover,.send:hover{background:var(--button-primary-hover-bg)}#welcome small{display:block;font-size:var(--text-xs);margin-top:var(--space-4)}
#bubbles{display:flex;flex-direction:column;gap:var(--space-4);margin:var(--space-8) 0;overflow-wrap:anywhere}.bubble{padding:var(--space-4) var(--space-6);border-radius:var(--radius-card);max-width:var(--bubble-width);white-space:pre-wrap;box-shadow:var(--shadow-bubble);background:var(--color-paper);font-size:var(--sally-text-bubble)}.bubble.me{align-self:flex-end;background:var(--color-accent-soft);font-size:var(--text-base)}.bubble .speaker{display:block;font-size:var(--text-xs);color:var(--color-muted);margin-bottom:var(--space-1)}
.candidate,.memory-card{background:var(--color-paper);border:var(--stroke-thin) solid var(--color-line);border-radius:var(--radius-card);padding:var(--space-6);margin-bottom:var(--space-4)}.candidate h3{font-size:var(--text-sm);margin:0;color:var(--color-accent)}.actions{display:flex;gap:var(--space-2);flex-wrap:wrap;margin-top:var(--space-3)}.actions button{border-color:transparent;background:var(--color-control);font-size:var(--button-font-size)}details{font-size:var(--text-sm);color:var(--color-muted)}summary{cursor:pointer;min-height:var(--control-height);padding-top:var(--space-2)}blockquote{margin:var(--space-2) 0;padding-left:var(--space-4);border-left:var(--outline) solid var(--color-accent-soft);white-space:pre-wrap;overflow-wrap:anywhere}
#feedback{font-size:var(--text-sm);color:var(--color-warning);margin:var(--space-3) 0;white-space:pre-wrap}#recovery{display:flex;gap:var(--space-2)}#recovery button{border-color:var(--color-control-line)}#composer{display:flex;flex-direction:column;gap:var(--space-2);background:var(--color-paper);border:var(--stroke-thin) solid var(--color-control-line);border-radius:var(--radius-card);padding:var(--space-4);margin-top:var(--space-6)}textarea{display:block;width:100%;min-height:var(--input-min);max-height:var(--input-max);border:0;background:transparent;color:inherit;resize:vertical;padding:var(--space-2);border-radius:var(--radius-control)}#composer:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 var(--stroke-thin) var(--color-accent)}#composer textarea{resize:none}#composer textarea:focus-visible{outline:none}.compose-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2)}.compose-footer button{flex-shrink:0}#presence{min-width:0;font-size:var(--text-xs);color:var(--color-muted);margin-right:auto}
dialog{width:calc(100% - var(--space-8));max-width:var(--album-width);max-height:var(--album-height);padding:var(--space-8);border:var(--stroke-thin) solid var(--color-line);border-radius:var(--dialog-radius);background:var(--color-room);color:var(--color-ink);box-shadow:var(--sally-shadow-dialog)}dialog::backdrop{background:var(--backdrop)}dialog>header{display:flex;justify-content:space-between;align-items:center;gap:var(--space-4);margin-bottom:var(--space-6)}#album-body{overflow-wrap:anywhere}.memory-card time{font-size:var(--text-xs);color:var(--color-muted)}.memory-card p{white-space:pre-wrap}.memory-card textarea{background:var(--color-light);border:var(--stroke-thin) solid var(--color-control-line)}.sr-only{position:absolute;width:var(--hidden-size);height:var(--hidden-size);overflow:hidden;clip:var(--clip-hidden)}
h1,p{white-space:pre-line}
/* The market indices strip and the header stay at the top together, as on Mandarin and Wagle (control-contract.css). */
.market-ticker{position:sticky;top:0;z-index:var(--z-header)}
.topbar{position:sticky;top:var(--size-market-ticker);align-self:start;background:var(--color-room)}
@media(min-width:701px){.topbar{height:var(--size-site-header)}.topbar .brand{line-height:var(--leading-solid)}.scene{top:calc(var(--size-market-ticker) + var(--size-site-header))}}
#album{overflow:hidden}#album[open]{display:flex;flex-direction:column}#album>header{flex-shrink:0;align-items:flex-start}#album-body{min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:var(--space-1);scrollbar-gutter:stable}#album-close{display:grid;place-items:center;flex-shrink:0;width:var(--button-target-height);height:var(--button-target-height);padding:0;border-color:var(--color-control-line);background:var(--color-paper);box-shadow:var(--shadow-bubble);color:var(--color-accent)}#album-close svg{transition:transform calc(var(--motion-fast)*3) var(--motion-ease)}#album-close:hover{background:var(--color-accent-soft)}@media(hover:hover){#album-close:hover svg{transform:rotate(180deg)}}
.chat-photo{display:block;width:100%;max-width:var(--album-width);max-height:50svh;object-fit:contain;border-radius:var(--radius-control);margin-top:var(--space-2)}#photo-preview .chat-photo{width:auto;max-width:100%;max-height:24svh}.photo-note{white-space:pre-line;font-size:var(--text-xs)}#photo-pick{padding-inline:var(--button-padding-x);border-color:transparent;background:var(--color-control)}#photo-pick:hover{background:var(--color-accent-soft)}#photo-status{color:var(--color-warning)}.compose-footer{flex-wrap:wrap}
#legacy-choice{display:flex;align-items:flex-start;gap:var(--space-2);font-size:var(--text-sm);margin-bottom:var(--space-4);color:var(--color-muted)}#legacy-choice input{accent-color:var(--color-accent);margin-top:var(--space-1)}
@media(max-width:700px){.topbar{flex-wrap:wrap}.topbar nav{max-width:100%;flex-wrap:wrap;justify-content:flex-end}}
@keyframes breathe{from{scale:1}to{scale:var(--breath-scale)}}
.photo-loading{align-self:flex-start}.photo-loading-dots{display:flex;align-items:center;gap:var(--space-1);height:var(--space-4)}.photo-loading-dots i{width:var(--space-2);height:var(--space-2);border-radius:var(--radius-pill);background:currentColor;animation:photo-hop var(--motion-photo) var(--motion-ease) infinite}.photo-loading-dots i:nth-child(2){animation-delay:var(--motion-fast)}.photo-loading-dots i:nth-child(3){animation-delay:calc(var(--motion-fast)*2)}
@keyframes photo-hop{0%,60%,100%{transform:translateY(0) scale(.85);opacity:var(--opacity-dim)}30%{transform:translateY(calc(var(--space-1)*-1)) scale(1);opacity:1}}
@media(prefers-reduced-motion:reduce){.portrait img,.photo-loading-dots i{animation:none}#album-close svg{transition:none;transform:none!important}}
.connected .conversation{padding-top:var(--space-8)}.connected .room-heading h1{font-size:var(--sally-text-title)}.connected .room-heading p{display:none}.album-status{color:var(--color-warning)}
@media(max-width:700px){.room{display:block}.topbar{height:auto;min-height:var(--size-site-header);padding:var(--space-3) var(--space-4);gap:var(--space-2)}.eyebrow{display:none}nav{gap:0}.topbar nav button:not(.utility-switch){padding:var(--button-padding-y) var(--button-padding-x);font-size:var(--button-font-size-small);white-space:nowrap}.brand{font-size:var(--text-brand-mobile)}.scene{position:relative;height:var(--scene-mobile);min-height:0;margin:0 var(--space-4);border-radius:var(--radius-card)}.portrait{width:var(--portrait-mobile-width);top:var(--space-12);max-width:var(--portrait-max)}.scene-caption{top:var(--space-4);left:var(--space-4)}.conversation{padding:var(--space-6) var(--space-6) max(var(--space-8),env(safe-area-inset-bottom))}.room-heading h1{font-size:var(--sally-text-title);margin:var(--space-2) 0}.room-heading p{font-size:var(--text-sm)}#bubbles{margin:var(--space-4) 0}.bubble{font-size:var(--text-base)}#composer{position:relative}dialog{padding:var(--space-6)}}

@media(max-width:700px),(any-pointer:coarse){button{min-width:var(--button-min-width)}}

/* Ways back to Mandarin: same quiet look as the other top-bar items. */
.topbar nav a.button{display:inline-flex;align-items:center;background:transparent;border-color:transparent;color:var(--color-ink);font-size:var(--button-font-size);text-decoration:none}
.topbar nav a.button:hover{background:var(--button-hover-bg)}
/* Continue in Wagle: an action, so the shared .button shape in a soft accent, not a raw link. [hidden] keeps working because display is set only when shown. */
#wagle-continue:not([hidden]){display:inline-flex;align-items:center;gap:var(--space-2);margin-block:var(--gap-tight);padding-inline:var(--space-5);background:var(--color-accent-soft);border-color:var(--color-accent);color:var(--color-ink);text-decoration:none}
#wagle-continue:not([hidden])::after{content:"→";color:var(--color-accent)}
#wagle-continue:hover{background:var(--color-paper)}
@media(max-width:700px){.topbar nav a.button{padding:var(--button-padding-y) var(--button-padding-x);font-size:var(--button-font-size-small);white-space:nowrap}}

/* Messenger bubbles: round profile, name, bubble with a tail. Sally left, member right. */
#bubbles .message{display:flex;align-items:flex-start;gap:var(--space-2);max-width:100%}
#bubbles .message.me{flex-direction:row-reverse}
.message-body{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-1);min-width:0;max-width:80%}
.message.me .message-body{align-items:flex-end}
.message .speaker{font-size:var(--text-xs);color:var(--color-muted);margin:0}
.message .bubble{position:relative;max-width:100%;margin:0;padding:var(--space-3) var(--space-4);border-radius:var(--radius-card);background:var(--color-paper);box-shadow:var(--shadow-bubble);white-space:pre-wrap;font-size:var(--sally-text-bubble);line-height:var(--leading-body)}
.message:not(.me) .bubble{border-start-start-radius:var(--radius-tail)}
.message.me .bubble{background:var(--color-accent-soft);border-start-end-radius:var(--radius-tail);font-size:var(--text-base)}
.message:not(.me) .bubble::before,.message.me .bubble::before{content:"";position:absolute;top:0;border-top:var(--space-2) solid var(--color-paper)}
.message:not(.me) .bubble::before{left:calc(var(--space-2) * -1);border-left:var(--space-2) solid transparent}
.message.me .bubble::before{right:calc(var(--space-2) * -1);border-right:var(--space-2) solid transparent;border-top-color:var(--color-accent-soft)}
@media(max-width:700px){.message-body{max-width:85%}.message .bubble{font-size:var(--text-base)}}
/* Header right side (shared control contract): language, theme, account. On a phone the room's own links take the
   second row so the right side stays on the first, as in Mandarin and Wagle. */
.topbar .account-controls{margin-left:0}
@media(max-width:700px){.topbar .header-utilities{margin-left:auto}.topbar nav{order:1;flex-basis:100%;margin-left:0}}

/* Wagle alerts in the header (wagle-bell.js): Wagle's notification API drawn by Sally with the room's tokens. */
.wagle-alerts[open]{display:flex;flex-direction:column}
.wagle-alerts-close{display:grid;place-items:center;flex-shrink:0;width:var(--button-target-height);height:var(--button-target-height);padding:0}
.wagle-alerts-status{margin:0 0 var(--space-4);color:var(--color-muted)}
.wagle-alerts-status:empty{display:none}
.wagle-alerts-list{display:grid;gap:var(--space-2);min-height:0;overflow-y:auto;overscroll-behavior:contain}
.wagle-alerts-list .wagle-alert{justify-content:flex-start;text-align:left;white-space:normal}

/* Sally is thinking (2026-10-30): three hearts pulse one after another beside the thinking line. */
.sally-thinking{display:inline-flex;align-items:center;gap:var(--space-2)}
.sally-hearts{display:inline-flex;gap:var(--space-1);color:var(--sally-heart)}
.sally-heart{display:inline-block;animation:sally-heart var(--motion-heart) var(--motion-ease) infinite both}
.sally-heart:nth-child(2){animation-delay:var(--motion-heart-step)}
.sally-heart:nth-child(3){animation-delay:calc(var(--motion-heart-step) * 2)}
@keyframes sally-heart{0%,100%{transform:scale(.7);opacity:var(--opacity-dim)}40%{transform:scale(1.15);opacity:1}}
@media (prefers-reduced-motion:reduce){.sally-heart{animation:none;opacity:1}}
/* Voice (voice.js): the microphone sits beside 보내기 as a round icon button; while listening it fills like 보내기. */
.voice-mic,.voice-read{display:inline-flex;align-items:center;justify-content:center;min-width:var(--button-target-height);min-height:var(--button-target-height);padding:0;border-radius:var(--radius-round)}
.voice-mic{border-color:transparent;background:var(--color-control)}
.voice-mic:hover{background:var(--color-accent-soft)}
.voice-mic[aria-pressed="true"]{background:var(--button-primary-bg);color:var(--button-primary-fg)}
.voice-status{font-size:var(--text-xs);color:var(--color-muted)}
/* Read aloud: a quiet speaker under Sally's bubble, accent while it speaks. */
.voice-read{border-color:transparent;background:transparent;color:var(--color-muted)}
.voice-read:hover,.voice-read[aria-pressed="true"]{color:var(--color-accent);background:var(--color-accent-soft)}
/* Sally's server voice on its way (aria-busy): the speaker breathes until the sound arrives. */
.voice-read[aria-busy="true"] .ui-icon{animation:sally-heart var(--motion-heart) var(--motion-ease) infinite both}
@media (prefers-reduced-motion:reduce){.voice-read[aria-busy="true"] .ui-icon{animation:none;opacity:var(--opacity-dim)}}
