/* === styles/tokens.css === */
/* Yumi design tokens — v3 "UNISON" (Ben's pick, 2026-07-06).
   yumi = you + me: cobalt lens on porcelain, crisp white surfaces, heavyweight grotesk.
   Themes: default (unison light) · night (unison dark) · enclave (the switchable
   Concept-3 alternate Ben reserved: acid lime on graphite, mono voice, square edges).
   Density contract unchanged: [data-density="tight|cozy|roomy"]. */
:root{
  --bg:#F4F4F2; --bg-2:#EBEBE7; --surface:#FFFFFF; --surface-2:#F7F7F5;
  --ink:#0E1116; --ink-2:#2A2F36; --mute:#6B7076; --faint:#A2A6AB;
  --line:#E4E4DF; --line-soft:#EFEFEA; --accent:#B23A34; --accent-soft:#F5E0DE;
  /* 2026-07-20 (Ben): accent moved off cobalt-blue to a muted brick/terracotta-crimson red
     that reads with the login background video's red yarn motion graphic. #B23A34 keeps
     >=5.8:1 contrast on white (--bg/--surface), well past AA 4.5:1 for the text uses of
     this token (.err/.aerr/links). --accent-soft is the same ~15% mix onto white the old
     blue token used, recomputed for the new hue instead of hand-picked. */
  --teal:#B23A34; /* trust states = accent; green is banned outside the enclave theme */
  --trust-green:#178754; /* scoped exception (Ben, 2026-07-09): the model-info lock indicator ONLY —
    not a general trust-state color, the --teal ban above still stands for everything else */
  --shadow:0 1px 2px rgba(14,17,22,.05), 0 12px 40px rgba(14,17,22,.08);
  --shadow-sm:0 1px 2px rgba(14,17,22,.05), 0 3px 10px rgba(14,17,22,.05);
  --display:"Inter","Helvetica Neue",-apple-system,system-ui,sans-serif;
  --ui:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,monospace;
  /* bk-f4ce98e9: Ben's standing rule — AI-served body copy defaults to serif — was
     already implemented for the chat bubble (.row.yumi .bub, below) but as a
     hand-written font stack with no design-system token backing it (a central-DS-only
     violation: type belongs in tokens, not repeated literal stacks). Named here so any
     future AI-body surface (e.g. the FlowState vault memory body, which already uses
     the identical Georgia stack ad hoc — see .memory-space-body in
     app-extensions.css) can consume one token instead of copy-pasting the stack again.
     System-serif on purpose, not the DS's Fraunces display face: Fraunces is a display/
     headline face (used italic, at heavy weight, for greet/word/mcard h3) — wrong
     register for dense paragraph body copy at 14.5px, and it is not currently loaded by
     index.html's asset chain (styles.css's @import of fonts.css) for this app shell at
     all, so depending on it here would silently no-op back to this exact fallback stack
     anyway. Georgia/Times is a safe, universally-available system serif for body text. */
  --font-body-serif:Georgia,"Times New Roman",Times,serif;
  --r:18px; --r-sm:12px; --r-xs:8px; --r-pill:999px;
  --on-accent:#FFFFFF; --on-ink:#F4F4F2;
  /* admin (YumYum console) aliases */
  --paper:#FFFFFF; --paper-2:#F7F7F5; --ink-soft:#2A2F36;
}
/* unison dark */
[data-theme="night"]{
  --bg:#0D0F13; --bg-2:#13161B; --surface:#171A20; --surface-2:#1F232A;
  --ink:#F2F2F0; --ink-2:#D4D6DA; --mute:#969BA3; --faint:#666C74;
  --line:#272B32; --line-soft:#1F232A; --accent:#5D73FF; --accent-soft:#232A4E;
  --teal:#5D73FF; --on-ink:#0D0F13;
  --trust-green:#3ECF8E;
  --shadow:0 1px 2px rgba(0,0,0,.35),0 12px 40px rgba(0,0,0,.4);
  --shadow-sm:0 1px 2px rgba(0,0,0,.3),0 3px 10px rgba(0,0,0,.28);
}
/* the reserved alternate: ENCLAVE — acid lime on graphite, mono voice, hard edges */
[data-theme="enclave"]{
  --bg:#0B0D0F; --bg-2:#101316; --surface:#14171A; --surface-2:#1A1E22;
  --ink:#EDEFF0; --ink-2:#D7DBDE; --mute:#8B949B; --faint:#5C646B;
  --line:#242A2F; --line-soft:#1A1E22; --accent:#C6F32F; --accent-soft:#2A3313;
  --teal:#C6F32F; --on-accent:#0B0D0F; --on-ink:#0B0D0F;
  --trust-green:#3ECF8E; /* deliberately NOT the enclave lime accent — the lock must stay
    visually distinct from "current theme" and read as "verified", not as themed chrome */
  --shadow:0 0 0 rgba(0,0,0,0); --shadow-sm:0 0 0 rgba(0,0,0,0);
  --display:"JetBrains Mono",ui-monospace,monospace;
  --ui:"JetBrains Mono",ui-monospace,monospace;
  --r:2px; --r-sm:2px; --r-xs:2px; --r-pill:2px;
}

/* === styles/yumi.css === */
/* Yumi component CSS — v3 "UNISON" (2026-07-06). Class vocabulary and component APIs
   unchanged since v1 (extracted from apps/yumi-app); the skin is now design-forward:
   porcelain + white + cobalt, heavyweight grotesk display, pill geometry.
   All colors/radii route through tokens.css vars so [data-theme="night"|"enclave"]
   restyle every component without component changes. */

.yumi-app{
  background:
    radial-gradient(1100px 640px at 84% -14%, color-mix(in srgb, var(--surface) 65%, transparent) 0%, transparent 52%),
    radial-gradient(880px 560px at -6% 114%, color-mix(in srgb, var(--accent) 5%, transparent) 0%, transparent 48%),
    var(--bg);
  color:var(--ink-2);font-family:var(--ui);font-weight:450;-webkit-font-smoothing:antialiased;
  letter-spacing:-.005em;
}
.yumi-app *{box-sizing:border-box}
.yumi-shell{display:flex;flex-direction:column;height:100dvh}

.top{display:flex;align-items:center;gap:14px;padding:20px 28px 0;max-width:880px;margin:0 auto;width:100%}
.brand{display:flex;align-items:center;gap:11px}
.mark{width:34px;height:34px;flex:none;border-radius:9px}
.word{font-family:var(--display);font-weight:800;font-size:24px;color:var(--ink);letter-spacing:-.045em;line-height:1}
.word em{font-style:normal;color:var(--accent)}
.tag{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--faint);padding-left:12px;border-left:1px solid var(--line);margin-left:2px;white-space:nowrap}
.sp{flex:1}
.whoami{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:lowercase;color:var(--faint);white-space:nowrap}
.btn{appearance:none;border:1px solid var(--line);background:var(--surface);color:var(--ink-2);font-family:var(--ui);font-weight:600;font-size:12.5px;padding:8px 15px;border-radius:var(--r-pill);cursor:pointer;box-shadow:var(--shadow-sm);transition:all .15s;white-space:nowrap;line-height:1;min-width:max-content;flex-shrink:0}
.btn:hover{border-color:var(--accent);color:var(--accent);transform:translateY(-1px)}
.btn.active{background:var(--surface-2);border-color:var(--ink-2);color:var(--ink);box-shadow:none}
.btn.solid{background:var(--ink);color:var(--on-ink);border-color:var(--ink)}
.btn.solid:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}

/* bk-8260f178 (2026-07-18): .yumi-main is the shared full-height content region for
   every primary screen routed through it (chat, Settings + every Settings sub-view,
   History, Connections, Usage — settings.js's shared SettingsShell renders them all
   into one <main class="yumi-main">, see settings.js ~line 2068). Its old rule (flex:1;
   overflow-y:auto only) stacked children at the top by default block flow — fine for
   content that fills or exceeds the viewport (Settings root, a long chat transcript,
   a big History list), but for short/empty content (a fresh chat, "No chats yet.", an
   unconfigured Connections list) it left everything glued under the top bar with a
   large dead gray gap (the untouched --bg page background) filling the rest of the
   viewport below — exactly the "content packed into the top ~250-300px, ~400px of dead
   gray space below" defect. `justify-content:safe center` is the fix: when the child
   content is SHORTER than the available height it centers it (using the space instead
   of abandoning it below); when content is TALLER than the available height (the safe
   fallback) it degrades to ordinary top-aligned, scrollable layout, so nothing about
   long-content screens changes. No new tokens, no fake/decorative content — same real
   content, distributed across the height it already owns. */
.yumi-main{flex:1;overflow-y:auto;padding:16px 0 6px;display:flex;flex-direction:column;justify-content:safe center}
/* Empty-chat state (chat.js applies this modifier ONLY when there are no messages/
   streaming reply). Previously flex:0 1 auto — shrinking the container off the
   available height entirely, which didn't remove the dead gray gap, it only moved it
   from "below the hero" to "below the composer" (same ~400px, still a bk-8260f178
   violation). .yumi-main's own justify-content:safe center above now does the right
   thing directly at flex:1 (hero+composer centered as a group in the real available
   height instead of pinned to the top with the composer trailing right under them), so
   this modifier no longer opts out of flex:1 — kept as an explicit no-op re-statement
   (not deleted) only so the className chat.js already applies never dangles unstyled. */
.yumi-main-compact{flex:1}
/* Density fix (QA defect): transcript column widened from 880px (~40% usable width once
   .col's own 76% cap is applied, at 1280) to 1040px (~81% at 1280) — target was 70-80%
   usable width. .compwrap below is widened to match so the composer stays aligned under
   the transcript, not narrower than it. */
.card{max-width:1040px;margin:0 auto;padding:0 28px}
.greet{font-family:var(--display);font-weight:800;font-size:40px;line-height:1.04;color:var(--ink);margin:8px 0 12px;letter-spacing:-.05em}
.greet em{font-style:normal;color:var(--accent)}
.sub{color:var(--mute);font-size:14.5px;line-height:1.6;margin-bottom:22px;max-width:58ch}
.sub b{color:var(--ink-2);font-weight:600}

.row{display:flex;margin:14px 0;gap:10px;align-items:flex-start}
.row.me{flex-direction:row-reverse}
.av{width:29px;height:29px;flex:none;margin-top:2px}
/* Density fix (QA defect): message column widened from 76% to 88% of the (now wider)
   .card — email lists/tables were the narrowest, most truncation-prone content at the
   old width; prose bubbles keep a readable measure via .bub's own font-size/line-height,
   not this cap, so widening it doesn't turn short replies into full-bleed walls of text. */
.col{max-width:88%;min-width:0}
.who{font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--faint);margin:2px 6px 5px}
.row.me .who{text-align:right}
.bub{padding:13px 16px;font-size:14.5px;line-height:1.6;white-space:pre-wrap;word-wrap:break-word}
.row.yumi .bub{background:var(--surface);border:1px solid var(--line);border-radius:var(--r) var(--r) var(--r) 5px;color:var(--ink-2);box-shadow:var(--shadow-sm);white-space:normal}
.row.yumi .bub p{margin:0 0 6px}.row.yumi .bub p:last-child{margin-bottom:0}
.row.yumi .bub pre{background:color-mix(in srgb,var(--surface) 70%,var(--ink) 5%);border:1px solid var(--line);border-radius:var(--r-xs);padding:10px 14px;overflow-x:auto;margin:6px 0;white-space:pre}
.row.yumi .bub code{font-family:var(--mono);font-size:12.5px;background:color-mix(in srgb,var(--surface) 70%,var(--ink) 5%);padding:2px 5px;border-radius:3px}
.row.yumi .bub pre code{background:none;padding:0}
.row.yumi .bub ul,.row.yumi .bub ol{margin:4px 0 4px 20px;padding:0}
.row.yumi .bub li{margin:2px 0}
.row.yumi .bub h1{font-size:1.15em;font-weight:700;margin:8px 0 4px}
.row.yumi .bub h2{font-size:1.08em;font-weight:700;margin:8px 0 4px}
.row.yumi .bub h3,.row.yumi .bub h4,.row.yumi .bub h5,.row.yumi .bub h6{font-size:1em;font-weight:700;margin:6px 0 3px}
.row.yumi .bub a{color:var(--accent);text-decoration:underline}
.row.yumi .bub hr{border:none;border-top:1px solid var(--line);margin:8px 0}
.row.yumi .bub strong{font-weight:700}.row.yumi .bub em{font-style:italic}
.row.me .bub{background:var(--ink);color:var(--on-ink);border-radius:var(--r) var(--r) 5px var(--r)}
.typing{color:var(--faint);font-style:italic}
.err{color:var(--accent);font-family:var(--mono);font-size:12px}
.step{color:var(--faint);font-style:italic;font-size:13.5px;animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.5}50%{opacity:1}}
.clip.mic-live{animation:pulse 1s ease-in-out infinite}

/* theme fine-tuning */
[data-theme="night"] .fld input{background:var(--surface-2)}
[data-theme="enclave"] .bub,[data-theme="enclave"] .box,[data-theme="enclave"] .btn{box-shadow:none}
[data-theme="enclave"] .step,[data-theme="enclave"] .typing{font-style:normal}

/* density + scale */
[data-density="tight"] .bub{padding:9px 12px;font-size:14px}
[data-density="tight"] .row{margin-bottom:8px}
[data-density="roomy"] .bub{padding:16px 20px}
[data-density="roomy"] .row{margin-bottom:20px}

/* sso + biometric */
.sso-row{display:flex;gap:10px;justify-content:center}
.sso-ic{width:46px;height:42px;display:flex;align-items:center;justify-content:center;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xs);cursor:pointer}
.sso-ic:hover{border-color:var(--ink-2)}
.sso-btn{width:100%;padding:11px;margin-top:8px;background:var(--ink);color:var(--on-ink);border:none;border-radius:var(--r-sm);font-size:13.5px;cursor:pointer}
.setrow{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:9px 0}
.setrow label{font-size:13px;color:var(--ink-2);font-weight:600}
.setrow select,.setrow input[type=range]{flex:0 0 auto}
.seth{font-size:12.5px;color:var(--mute);margin:16px 0 8px;font-weight:600}
.secbox{font-size:12.5px;line-height:1.7;background:var(--surface-2);border-radius:var(--r-sm);padding:12px;color:var(--ink-2)}
.secbox b{color:var(--ink)}
.toolrow{display:flex;align-items:center;justify-content:space-between;padding:6px 0;font-size:13px}
.mcard.wide{max-width:680px}
.clip{background:none;border:none;cursor:pointer;width:38px;height:38px;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%;color:var(--mute);flex:none}
.clip:hover{color:var(--ink);background:var(--surface-2)}
[data-theme="enclave"] .clip{border-radius:var(--r)}

/* composer */
.compwrap{max-width:1040px;margin:0 auto;padding:10px 28px 24px;width:100%}
.box{display:flex;gap:6px;align-items:center;background:var(--surface);border:2px solid var(--ink);border-radius:var(--r-pill);padding:7px 7px 7px 18px;box-shadow:var(--shadow-sm);transition:border-color .15s,box-shadow .15s}
.box:focus-within{border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 12%,transparent),var(--shadow-sm)}
.box textarea{flex:1;border:0;background:transparent;resize:none;font-family:var(--ui);font-size:15px;color:var(--ink);outline:none;max-height:160px;line-height:1.55;padding:7px 0;font-weight:450}
.box textarea::placeholder{color:var(--faint)}
.send{appearance:none;border:0;background:var(--accent);color:var(--on-accent);font-family:var(--ui);font-weight:700;font-size:13.5px;padding:10px 20px;border-radius:var(--r-pill);cursor:pointer;flex:none;transition:background .15s,transform .1s}
.send:hover{background:var(--ink);color:var(--on-ink)} .send:active{transform:scale(.97)} .send:disabled{background:var(--faint);color:var(--surface)}
.hint{text-align:center;font-family:var(--mono);font-size:9px;letter-spacing:.13em;color:var(--faint);text-transform:uppercase;margin-top:10px}

/* icon-only round button (settings gear, new chat, back) */
.icbtn{width:36px;height:36px;border-radius:50%;border:1px solid var(--line);background:var(--surface);display:flex;align-items:center;justify-content:center;color:var(--ink-2);cursor:pointer;flex:none;box-shadow:var(--shadow-sm)}
.icbtn:hover{border-color:var(--accent);color:var(--accent)}
.icbtn.active{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
[data-theme="enclave"] .icbtn{border-radius:var(--r)}

/* grouped settings (Settings is the container: memory, connections, appearance…) */
.setgh{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);margin:18px 2px 8px}
.setgroup{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden;box-shadow:var(--shadow-sm)}
.setlink{display:flex;align-items:center;gap:12px;padding:12px 14px;border-bottom:1px solid var(--line-soft);cursor:pointer}
.setlink:last-child{border-bottom:0}
.setlink:hover{background:var(--surface-2)}
.setlink .sl-ic{width:30px;height:30px;border-radius:var(--r-xs);background:var(--surface-2);display:flex;align-items:center;justify-content:center;color:var(--ink-2);flex:none}
.setlink .sl-b{flex:1;min-width:0}
.setlink .sl-l{font-size:14px;font-weight:600;color:var(--ink);line-height:1.3}
.setlink .sl-v{font-size:12px;color:var(--mute);margin-top:1px}
.setlink .sl-ch{color:var(--faint);display:flex}
.setlink.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}

/* phone sub-page header */
.mhead{display:flex;align-items:center;gap:8px;padding:14px 16px 10px}
.mhead .mh-t{font-family:var(--display);font-weight:800;font-size:18px;letter-spacing:-.03em;color:var(--ink);flex:1;text-align:center}
.mhead .mh-sp{width:36px;flex:none}

/* page title — left-aligned surface header, same rail as content */
.ptitle{display:flex;align-items:center;gap:14px;margin:10px 0 14px;padding-bottom:12px;border-bottom:1px solid var(--line)}
.ptitle h2{font-family:var(--display);font-weight:800;font-size:22px;letter-spacing:-.04em;color:var(--ink);margin:0}
.ptitle .pt-sub{font-size:12.5px;color:var(--mute)}
.ptitle .sp{flex:1}

/* auth + modal */
.authc{width:100%;max-width:380px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);padding:30px 26px;position:relative;overflow:hidden}
.authc::before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:var(--accent)}
.authc .mark{display:block;margin:0 auto 12px;width:42px;height:42px}
.authc .word{display:block;text-align:center;font-size:26px;margin-bottom:22px}
.asub{text-align:center;color:var(--mute);font-size:13px;margin:0 0 18px}
.atabs{display:flex;gap:6px;margin:0 0 14px;background:var(--surface-2);padding:4px;border-radius:var(--r-pill)}
.atab{flex:1;text-align:center;font-size:12.5px;font-weight:600;color:var(--mute);padding:7px;border-radius:var(--r-pill);cursor:pointer}
.atab.on{background:var(--surface);color:var(--ink);box-shadow:var(--shadow-sm)}
.atab.disabled{opacity:.45;cursor:not-allowed;pointer-events:none}
.fld{margin-bottom:11px}
.fld label{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.13em;text-transform:uppercase;color:var(--mute);margin:0 0 5px 3px}
.fld input{width:100%;border:1px solid var(--line);background:var(--surface);border-radius:var(--r-sm);padding:11px 13px;font-family:var(--ui);font-size:14.5px;color:var(--ink);outline:none;box-shadow:inset 0 1px 2px rgba(14,17,22,.03)}
.fld input:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 12%,transparent)}
.submit{width:100%;border:0;background:var(--ink);color:var(--on-ink);font-family:var(--ui);font-weight:700;font-size:14px;padding:12px;border-radius:var(--r-pill);cursor:pointer;margin-top:3px}
.submit:hover{background:var(--accent);color:var(--on-accent)}
.gbtn{width:100%;border:1px solid var(--line);background:var(--surface);color:var(--ink);font-weight:600;font-size:13.5px;padding:11px;border-radius:var(--r-pill);cursor:pointer;margin-top:10px;display:flex;align-items:center;justify-content:center;gap:9px}
.gbtn:hover{border-color:var(--ink-2)}
.or{display:flex;align-items:center;gap:10px;color:var(--faint);font-size:11px;margin:14px 0 4px;text-transform:uppercase;letter-spacing:.06em}
.or::before,.or::after{content:"";flex:1;height:1px;background:var(--line)}
.aerr{color:var(--accent);font-family:var(--mono);font-size:11px;margin-top:10px;min-height:14px;text-align:center}
.modal{position:fixed;inset:0;background:rgba(8,10,14,.55);display:none;align-items:center;justify-content:center;padding:20px;z-index:50}
.modal.on{display:flex}
.mcard{width:100%;max-width:480px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);padding:24px;max-height:86vh;overflow-y:auto}
.mcard h3{font-family:var(--display);font-weight:800;letter-spacing:-.03em;font-size:21px;color:var(--ink);margin:0 0 4px}
.mcard p.s{color:var(--mute);font-size:13px;margin:0 0 16px}
.conn{border:1px solid var(--line-soft);border-radius:var(--r-sm);padding:12px 13px;margin-bottom:10px}
.conn .cn{font-weight:600;color:var(--ink);font-size:13.5px}
.conn .cd{color:var(--mute);font-size:12px;margin-top:2px}
.srv{display:flex;align-items:center;justify-content:space-between;border:1px solid var(--line-soft);border-radius:var(--r-sm);padding:9px 12px;margin-bottom:8px;font-size:13px}
.srv .x{color:var(--accent);cursor:pointer;font-family:var(--mono);font-size:11px}
.mclose{margin-top:8px}
.hidden{display:none!important}

@media(max-width:600px){
  .top,.card,.compwrap{padding-left:14px;padding-right:14px}
  /* Mobile-viewport fix (2026-07-13): the topbar previously stayed nowrap+overflow-x:auto
     with a hidden scrollbar — brand+model-badge+memory+History+Projects+2 icon buttons
     total ~480px of content in a ~360px available row, so History/Projects and the
     settings icon scrolled off-screen with zero visual affordance that a scroll existed.
     Fix: wrap the row onto two clean lines instead (brand alone on row 1, the action
     buttons on row 2 via the .sp spacer forced to its own full-width line) so every
     control is fully visible with no horizontal scroll, no clipped/off-screen buttons. */
  .top{gap:8px 6px;flex-wrap:wrap;overflow-x:visible;padding-top:16px;padding-bottom:10px}
  .yumi-app .top .sp{flex-basis:100%;height:0}
  .brand,.btn{flex:none}
  .greet{font-size:28px}.tag{display:none}.col{max-width:90%}
  .whoami{display:none}
  .btn{font-size:12px;padding:7px 11px}
  .word{font-size:21px}.mark{width:30px;height:30px}
  .authc{padding:24px 18px}
  .mcard{padding:18px;max-height:90vh}
  .bub{font-size:14px;padding:12px 14px}
  .box textarea{font-size:16px}
}
@media(max-width:380px){.btn{padding:6px 9px;font-size:11px}.greet{font-size:25px}}

/* ============ product components (VoiceBar / TrustBadge / MemoryChip / ConnectorTile) ============ */
.voicebar{display:inline-flex;align-items:center;gap:11px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-pill);padding:8px 16px 8px 9px;box-shadow:var(--shadow-sm);font-family:var(--ui);font-size:13px;color:var(--ink-2)}
.voicebar .orb{width:30px;height:30px;border-radius:50%;background:var(--ink);display:flex;align-items:center;justify-content:center;color:var(--on-ink);font-size:14px;flex:none}
[data-theme="enclave"] .voicebar .orb{border-radius:var(--r)}
.voicebar[data-state="listening"] .orb{background:var(--accent);color:var(--on-accent);animation:pulse 1.1s ease-in-out infinite}
.voicebar[data-state="thinking"] .orb{background:var(--teal);color:var(--on-accent)}
.voicebar[data-state="speaking"] .orb{background:var(--accent);color:var(--on-accent)}
.voicebar .vstate{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);white-space:nowrap}
.voicebar .wave{display:inline-flex;gap:2.5px;align-items:center;height:14px}
.voicebar .wave i{width:2.5px;border-radius:2px;background:var(--faint);height:5px}
.voicebar[data-state="listening"] .wave i,.voicebar[data-state="speaking"] .wave i{background:var(--accent)}
.voicebar .wave i:nth-child(2){height:10px}.voicebar .wave i:nth-child(3){height:14px}.voicebar .wave i:nth-child(4){height:8px}.voicebar .wave i:nth-child(5){height:12px}
.trust{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--teal);border:1px solid color-mix(in srgb,var(--teal) 40%,transparent);background:color-mix(in srgb,var(--teal) 7%,transparent);border-radius:var(--r-xs);padding:4px 9px;white-space:nowrap}
.trust .tk{width:6px;height:6px;border-radius:50%;background:var(--teal);flex:none}
.trust.inkline{color:var(--mute);border-color:var(--line);background:var(--surface-2)}
.trust.inkline .tk{background:var(--faint)}
.memchip{display:inline-flex;align-items:center;gap:7px;background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 30%,transparent);color:var(--ink-2);border-radius:var(--r-pill);padding:5px 11px;font-size:12.5px;max-width:100%}
.memchip .mk{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}
.memchip .mx{font-family:var(--mono);font-size:10px;color:var(--mute);cursor:pointer;margin-left:2px}
.memchip .mx:hover{color:var(--accent)}
.conntile{display:flex;align-items:center;gap:12px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);padding:11px 13px;box-shadow:var(--shadow-sm);flex-wrap:wrap}
.conntile .ci{width:34px;height:34px;border-radius:var(--r-xs);background:var(--surface-2);border:1px solid var(--line-soft);display:flex;align-items:center;justify-content:center;flex:none}
.conntile .cb{flex:1;min-width:0}
.conntile .cn{font-weight:600;color:var(--ink);font-size:13.5px;line-height:1.25}
.conntile .cd{color:var(--mute);font-size:12px;margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.conntile .cs{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);flex:none}
.conntile .cs.on{color:var(--teal)}
/* bk-f4ce98e9: ConnectorTile (Settings > Connections > "Channels") renders its status
   explanation as a trailing `children` node — the generic Hint component (.hint), whose
   rule is styled for a totally different context (composer's tiny centered mono caption)
   — as an UNWRAPPED flex-row sibling of the icon/name/status. .hint's own
   `margin-top:10px` does nothing to start a new line inside a flex row, and long invite-
   channel copy ("Graph not configured (YUMI_MAIL_*). Invites still mint a copyable
   link.") has no room left in that row once icon+name+status claim their space, so its
   text visually overlapped the name/description column instead of wrapping cleanly
   below it. Fix: .conntile now wraps (added flex-wrap:wrap above); this rule forces its
   .hint child onto its own full-width line beneath the icon/name/status row (flex-basis
   100%) and restyles it to read as an explanatory sentence — left-aligned, sentence
   case, UI font — instead of the tiny centered uppercase mono caption it inherited from
   an unrelated context. */
.conntile > .hint{flex:1 1 100%;margin-top:6px;padding-left:46px;text-align:left;text-transform:none;letter-spacing:normal;font-family:var(--ui);font-size:11.5px;color:var(--mute)}

/* === styles/admin.css === */
/* YumYum admin console CSS — extracted verbatim from apps/yumi-app/public/admin.html <style>,
   scoped under .yumyum-admin because the admin surface redefines .top/.btn/.brand/.tag/.sp/.who
   with different values than the consumer app. Token names map to the shared tokens.css
   (--paper/--paper-2/--ink-soft aliases). body{} paint → .yumyum-admin. */
.yumyum-admin{background:var(--bg);color:var(--ink-soft);font-family:var(--ui);font-size:13.5px;line-height:1.5;-webkit-font-smoothing:antialiased}
.yumyum-admin *{box-sizing:border-box}
.yumyum-admin .top{height:54px;background:#0E0E0C;color:#FAFAF6;display:flex;align-items:center;gap:14px;padding:0 20px;position:sticky;top:0;z-index:20;max-width:none;margin:0}
.yumyum-admin .brand{display:flex;align-items:center;gap:10px;text-decoration:none}
.yumyum-admin .brand img{height:28px;width:28px;border-radius:7px;background:#fff;display:block}
.yumyum-admin .brand .word{font-family:var(--display);font-style:italic;font-weight:600;font-size:18px;color:#FAFAF6;letter-spacing:-.01em}
.yumyum-admin .tag{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:#A6A39A;border-left:none;padding-left:0}
.yumyum-admin .sp{flex:1}
.yumyum-admin .who{font-family:var(--mono);font-size:10px;letter-spacing:.08em;color:#CFCcC2;opacity:.85;margin:0}
.yumyum-admin .btn{border:1px solid #FAFAF6;background:transparent;color:#FAFAF6;font-family:var(--ui);font-weight:600;font-size:12px;padding:6px 12px;border-radius:5px;cursor:pointer;box-shadow:none}
.yumyum-admin .btn:hover{border-color:var(--accent);color:var(--accent);transform:none}
.yumyum-admin .layout{display:grid;grid-template-columns:196px 1fr;min-height:calc(100vh - 54px)}
.yumyum-admin nav{background:var(--paper);border-right:1px solid var(--line);padding:12px 8px}
.yumyum-admin nav a{display:block;padding:8px 12px;border-radius:5px;color:var(--ink-soft);font-size:13px;margin-bottom:2px;cursor:pointer;text-decoration:none}
.yumyum-admin nav a:hover{background:var(--paper-2);color:var(--ink)}
.yumyum-admin nav a.act{background:var(--paper-2);color:var(--ink);font-weight:600;border-left:2px solid var(--accent)}
.yumyum-admin main{padding:20px 26px;max-width:1180px}
.yumyum-admin h1{font-family:var(--display);font-style:italic;font-weight:600;font-size:24px;color:var(--ink);margin:0 0 2px}
.yumyum-admin .bar{display:flex;gap:22px;flex-wrap:wrap;align-items:baseline;margin:2px 0 18px;font-size:12.5px;color:var(--mute)}
.yumyum-admin .bar b{font-family:var(--display);font-style:italic;font-size:19px;color:var(--ink);margin-right:5px}
.yumyum-admin .panel{background:var(--paper);border:1px solid var(--line);border-radius:6px;overflow:hidden;margin-bottom:18px}
.yumyum-admin .panel .hd{display:flex;align-items:center;justify-content:space-between;padding:11px 15px;border-bottom:1px solid var(--line);font-weight:600;color:var(--ink);font-size:13px}
.yumyum-admin table{width:100%;border-collapse:collapse}
.yumyum-admin th,.yumyum-admin td{text-align:left;padding:9px 15px;border-bottom:1px solid var(--line);font-size:12.5px;vertical-align:top}
.yumyum-admin thead th{font-family:var(--mono);font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--mute);font-weight:500;background:var(--paper-2)}
.yumyum-admin tbody tr:last-child td{border-bottom:0}
.yumyum-admin tbody tr.dim{opacity:.55}
.yumyum-admin .m{font-family:var(--mono);font-size:11.5px;color:var(--ink)}
.yumyum-admin .pill{font-family:var(--mono);font-size:10px;padding:2px 7px;border-radius:3px;border:1px solid var(--line);color:var(--mute);white-space:nowrap}
.yumyum-admin .pill.on{color:var(--teal);border-color:var(--teal)} .yumyum-admin .pill.admin{color:#FAFAF6;background:var(--ink);border-color:var(--ink)}
.yumyum-admin .pill.off{color:#a04;border-color:#e6c9b8}
.yumyum-admin .muted{color:var(--mute)} .yumyum-admin .r{text-align:right}
.yumyum-admin .msg{padding:40px 26px;color:var(--mute)} .yumyum-admin .msg a{color:var(--accent)}
.yumyum-admin .warn{margin:0 0 14px;font-family:var(--mono);font-size:11px;color:#a04; background:#fbeee6;border:1px solid #e6c9b8;border-radius:5px;padding:8px 12px}
.yumyum-admin .note{margin:0 0 14px;font-family:var(--mono);font-size:11px;color:var(--mute);background:var(--paper-2);border:1px solid var(--line);border-radius:5px;padding:8px 12px}
.yumyum-admin .mini{font-family:var(--ui);font-size:11px;font-weight:600;border:1px solid var(--line);background:var(--paper);color:var(--ink-soft);padding:3px 9px;border-radius:4px;cursor:pointer;margin-right:5px}
.yumyum-admin .mini:hover{border-color:var(--accent);color:var(--accent)}
.yumyum-admin .mini.danger:hover{border-color:#a04;color:#a04}
.yumyum-admin input.seat{width:56px;font-family:var(--mono);font-size:12px;border:1px solid var(--line);border-radius:4px;padding:3px 6px;background:var(--paper)}
.yumyum-admin select.plan{font-family:var(--ui);font-size:12px;border:1px solid var(--line);border-radius:4px;padding:3px 6px;background:var(--paper)}
.yumyum-admin .ssobtn{display:inline-flex;align-items:center;gap:8px;background:var(--ink);color:#FAFAF6;border:none;padding:9px 16px;border-radius:5px;font-weight:600;font-size:13px;text-decoration:none;margin-top:10px}
.yumyum-admin .ssobtn:hover{background:var(--accent)}
@media(max-width:760px){.yumyum-admin .layout{grid-template-columns:1fr}.yumyum-admin nav{display:none}}

/* === YB-04 security-path (live TEE verification) — allowlisted classes ===
   Verified/trust states use --accent (the DS trust colour). Per the token note above
   ("green is banned outside the enclave theme") there is deliberately NO red/green
   status token, so a FAILED hop reads through weight (--ink) + the established mono
   .err idiom, never an invented colour. All motion honours prefers-reduced-motion. */
.secpath{display:flex;flex-direction:column;gap:0;margin:2px 0}
.secnode{display:flex;flex-direction:column;position:relative}
.secnode-hd{display:flex;align-items:flex-start;gap:12px;padding:8px 0;cursor:pointer;text-align:left}
.secnode-mark{width:26px;height:26px;flex:none;border-radius:50%;border:2px solid var(--line);background:var(--surface);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:13px;font-weight:700;color:var(--faint);transition:border-color .3s,color .3s,background .3s}
[data-theme="enclave"] .secnode-mark{border-radius:var(--r)}
.secnode-body{flex:1;min-width:0}
.secnode-t{font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.3}
.secnode-s{font-family:var(--mono);font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--faint)}
.secnode-chev{color:var(--faint);font-family:var(--mono);font-size:12px;flex:none;align-self:center}
.secnode.pending .secnode-mark{animation:pulse 1.2s ease-in-out infinite}
.secnode.pending .secnode-s{animation:pulse 1.4s ease-in-out infinite}
.secnode.ok .secnode-mark{border-color:var(--accent);background:var(--accent);color:var(--on-accent);animation:secpop .35s ease}
.secnode.ok .secnode-s{color:var(--accent)}
.secnode.fail .secnode-mark{border-color:var(--ink);color:var(--ink);background:var(--surface);animation:secpop .35s ease}
.secnode.fail .secnode-s{color:var(--ink)}
.secnode-err{font-family:var(--mono);font-size:11px;color:var(--accent);margin-top:3px;line-height:1.5}
.secedge{width:2px;height:16px;margin-left:12px;background:var(--line);position:relative;overflow:hidden;flex:none}
.secedge::after{content:"";position:absolute;inset:0;background:var(--accent);transform:scaleY(0);transform-origin:top;transition:transform .4s ease}
.secedge.filled::after{transform:scaleY(1)}
.secev{font-family:var(--mono);font-size:11.5px;line-height:1.6;background:var(--surface-2);border-radius:var(--r-xs);padding:10px 12px;margin:0 0 6px 38px;color:var(--ink-2);overflow-x:auto}
.secev b{color:var(--ink);font-family:var(--ui)}
.secev pre{white-space:pre;font-family:var(--mono);font-size:10.5px;color:var(--ink-2);margin:6px 0 0;max-height:280px;overflow:auto;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xs);padding:8px}
.secev-disc{font-family:var(--ui);font-size:11.5px;font-weight:600;color:var(--accent);cursor:pointer;margin-top:8px;display:inline-block}
@keyframes secpop{0%{transform:scale(.4);opacity:0}60%{transform:scale(1.15)}100%{transform:scale(1);opacity:1}}
@media(prefers-reduced-motion:reduce){
  .secnode .secnode-mark,.secnode.pending .secnode-mark,.secnode.pending .secnode-s{animation:none}
  .secedge::after{transition:none}
}

/* === YB-01 "What Yumi did" per-task audit trail — allowlisted classes ===
   Compact, collapsed-by-default trail of the REAL tool calls a turn made. Trust/ok
   uses --accent; a failed step reads via weight (--ink) + mono, no invented red/green
   (same DS token rule as the security-path block above). Reduced-motion honoured. */
.ywd{margin:2px 0 14px 0}
.ywd-toggle{display:inline-flex;align-items:center;gap:7px;background:none;border:0;padding:2px 0;cursor:pointer;font-family:var(--mono);font-size:11px;letter-spacing:.03em;text-transform:uppercase;color:var(--mute)}
.ywd-toggle:hover{color:var(--ink)}
.ywd-toggle .ywd-tick{color:var(--accent);font-weight:700}
.ywd-toggle .ywd-chev{font-size:10px;transition:transform .2s ease}
.ywd-toggle[aria-expanded="true"] .ywd-chev{transform:rotate(90deg)}
.ywd-list{list-style:none;margin:8px 0 0;padding:8px 0 4px 4px;border-left:2px solid var(--line-soft);display:flex;flex-direction:column;gap:6px}
.ywd-step{display:flex;align-items:flex-start;gap:8px;font-size:12.5px;line-height:1.35;color:var(--ink-2)}
.ywd-mark{width:15px;flex:none;text-align:center;font-family:var(--mono);font-size:12px;font-weight:700;color:var(--accent);margin-top:1px}
.ywd-step.bad .ywd-mark{color:var(--ink)}
.ywd-step.bad{color:var(--mute)}
.ywd-tool{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint);margin-left:auto;padding-left:10px;flex:none}
@media(prefers-reduced-motion:reduce){.ywd-toggle .ywd-chev{transition:none}}

/* === YB-05 live task checklist — real-time per-tool-call progress rendered WHILE a turn
   streams (public/app/chat.js LiveStepChecklist, fed by SSE 'step'/'delta'/'done' events —
   never fabricated steps). Same visual language + tokens as the .ywd-* trail above it
   becomes once the turn ends (mono mark column, --accent for the live/success signal,
   no invented red/green) — this is that same trail's live, in-progress twin. Reduced-
   motion honoured (no new hex; reuses the existing @keyframes pulse also used by .step). */
.yls{list-style:none;margin:2px 0 14px;padding:0;display:flex;flex-direction:column;gap:5px}
.yls-row{display:flex;align-items:center;gap:8px;font-size:13px;line-height:1.3}
.yls-mark{width:14px;flex:none;text-align:center;font-family:var(--mono);font-size:12px;font-weight:700;color:var(--accent)}
.yls-row.yls-doing .yls-mark{animation:pulse 1.4s ease-in-out infinite}
.yls-row.yls-doing .yls-label{color:var(--ink-2)}
.yls-row.yls-done .yls-mark{color:var(--accent)}
.yls-row.yls-done .yls-label{color:var(--mute)}
.yls-row.yls-failed .yls-mark{color:var(--ink)}
.yls-row.yls-failed .yls-label{color:var(--mute)}
@media(prefers-reduced-motion:reduce){.yls-row.yls-doing .yls-mark{animation:none}}

/* === admin DataTable / RecordModal — YUMI-R-031..035 (existing tokens only, no new hex) === */
.yumyum-admin .dt-toolbar{display:flex;gap:8px;align-items:center;margin:0 0 12px;flex-wrap:wrap}
.yumyum-admin .dt-search{font-family:var(--ui);font-size:12.5px;border:1px solid var(--line);border-radius:4px;padding:5px 10px;background:var(--paper);color:var(--ink-soft);width:220px}
.yumyum-admin .dt-search:focus{outline:none;border-color:var(--accent)}
.yumyum-admin .dt-search::placeholder{color:var(--mute)}
.yumyum-admin .dt-sp{flex:1}
.yumyum-admin th.sortable{cursor:pointer;user-select:none}
.yumyum-admin th.sortable:hover{color:var(--ink)}
.yumyum-admin th .arrow{margin-left:5px;color:var(--faint);font-size:9px}
.yumyum-admin tbody tr.clickable{cursor:pointer}
.yumyum-admin tbody tr.clickable:hover{background:var(--paper-2)}
.yumyum-admin .dt-pager{display:flex;gap:8px;align-items:center;margin:10px 0 18px}
.mcard{position:relative}
.mclosebtn{position:absolute;top:12px;right:12px;width:28px;height:28px;border-radius:50%;border:1px solid var(--line);background:var(--surface);color:var(--mute);cursor:pointer;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;padding:0}
.mclosebtn:hover{border-color:var(--accent);color:var(--accent)}

/* === email results UX — allowlisted classes ===
   Dense, clickable inbox/search-results list rendered from server.js steps[n].emails
   (replaces the old raw-pipe-table LLM output). Each row expands in place (accordion) to
   show the full message fetched from GET /api/mail/message/:id — no modal, no new tab, no
   scroll jump. Same visual language as the .ywd trail above (mono labels/dates, --accent
   for the live/unread signal, no invented red/green). */
.email-list{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden;margin:0 0 10px}
.email-row{border-bottom:1px solid var(--line-soft)}
.email-row:last-child{border-bottom:0}
.email-row-head{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:var(--surface);border:0;padding:9px 12px;cursor:pointer;font-family:var(--ui);color:var(--ink-2)}
.email-row-head:hover{background:var(--surface-2)}
.email-row.unread .email-row-head{background:color-mix(in srgb,var(--accent-soft) 55%,var(--surface) 45%)}
.email-row.unread .email-row-head:hover{background:var(--accent-soft)}
.email-unread-dot{width:14px;flex:none;text-align:center;color:var(--accent);font-size:8px;line-height:1}
.email-from{flex:0 0 auto;max-width:32%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;color:var(--ink)}
.email-row.unread .email-from{font-weight:700}
.email-subject{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.email-date{flex:none;font-family:var(--mono);font-size:10.5px;text-transform:uppercase;letter-spacing:.03em;color:var(--faint)}
.email-detail{background:var(--surface-2);border-top:1px solid var(--line-soft);padding:12px 14px 14px}
.email-detail-loading,.email-detail-error{font-size:12.5px;color:var(--mute)}
.email-detail-error{color:var(--ink)}
.email-detail-meta{display:flex;flex-direction:column;gap:2px;margin:0 0 10px;font-size:12px;color:var(--ink-2)}
.email-detail-label{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint);margin-right:6px}
.email-detail-body{max-height:280px;overflow-y:auto;white-space:pre-wrap;font-size:13px;line-height:1.5;color:var(--ink-2);background:var(--surface);border:1px solid var(--line-soft);border-radius:var(--r-xs);padding:10px 12px}
.email-detail-attach{margin-top:8px;font-size:11.5px;color:var(--mute)}
.email-ask-yumi{margin-top:10px;background:none;border:1px solid var(--line);border-radius:var(--r-pill);padding:5px 12px;font-family:var(--ui);font-size:12px;font-weight:600;color:var(--accent);cursor:pointer}
.email-ask-yumi:hover{background:var(--accent-soft);border-color:var(--accent)}

/* === md() table renderer — allowlisted classes ===
   Fallback for any markdown pipe-table an LLM reply emits (not just email results). */
.md-table-wrap{overflow-x:auto;margin:6px 0}
table.md-table{border-collapse:collapse;font-size:12.5px;min-width:100%}
table.md-table th,table.md-table td{border:1px solid var(--line);padding:5px 10px;text-align:left;white-space:nowrap}
table.md-table thead th{background:var(--surface-2);font-weight:700;color:var(--ink)}
table.md-table tbody tr:nth-child(even){background:color-mix(in srgb,var(--surface) 92%,var(--ink) 3%)}
/* Mobile overflow affordance (YUMI item 2, 2026-07-14): the wrap already scrolled
   horizontally, but on a 390px screen a 5-col table (~808px) inside a ~296px box gave the
   user zero visual signal that content was cut off. Fix, CSS-only (no JS class toggling
   needed — this repo's hard rule keeps this PR to *.css only), no new hex, existing tokens
   only:
   1) always-visible thin scrollbar track on touch/webkit + Firefox, so the track itself is
      the "there is more here" signal instead of the platform's hidden native scrollbar;
   2) -webkit-overflow-scrolling:touch for native momentum scroll on iOS;
   3) a right-edge fade that shows ONLY while there is unscrolled content to the right and
      hides itself once the user has scrolled to the true end — the classic dual-layer
      background-attachment technique: an opaque "cover" gradient painted with
      attachment:local (scrolls WITH the table content, so it slides out of view once you
      reach the real right edge) sits on top of a darker "shadow" gradient painted with
      attachment:scroll (fixed to the viewport of the box, always at its right edge). When
      content exactly fits the box the two coincide and the shadow never shows; when content
      overflows the cover starts already past the visible edge, so the shadow reads through
      until you scroll all the way to the end — automatic, no scroll-event JS required. */
.md-table-wrap,.row.yumi .bub pre,.secev,.secev pre{
  -webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--faint) transparent;
  background-repeat:no-repeat;background-position:100% 0,100% 0;background-size:24px 100%,24px 100%;
  background-attachment:local,scroll;
}
.md-table-wrap::-webkit-scrollbar,.row.yumi .bub pre::-webkit-scrollbar,.secev::-webkit-scrollbar,.secev pre::-webkit-scrollbar{height:6px}
.md-table-wrap::-webkit-scrollbar-track,.row.yumi .bub pre::-webkit-scrollbar-track,.secev::-webkit-scrollbar-track,.secev pre::-webkit-scrollbar-track{background:transparent}
.md-table-wrap::-webkit-scrollbar-thumb,.row.yumi .bub pre::-webkit-scrollbar-thumb,.secev::-webkit-scrollbar-thumb,.secev pre::-webkit-scrollbar-thumb{background:var(--faint);border-radius:var(--r-pill)}
/* per-surface cover/shadow gradient pairs — cover color matches each surface's own
   background exactly (so the fade reads as "this surface, ending" not a visible seam),
   shadow uses that surface's own ink token at low opacity via color-mix (no new hex). */
.md-table-wrap{background-image:
    linear-gradient(to left,var(--surface),color-mix(in srgb,var(--surface) 0%,transparent)),
    linear-gradient(to left,color-mix(in srgb,var(--ink) 16%,transparent),transparent)}
.row.yumi .bub pre{background-image:
    linear-gradient(to left,color-mix(in srgb,var(--surface) 70%,var(--ink) 5%),color-mix(in srgb,var(--surface) 0%,transparent)),
    linear-gradient(to left,color-mix(in srgb,var(--ink) 16%,transparent),transparent)}
.secev{background-image:
    linear-gradient(to left,var(--surface-2),color-mix(in srgb,var(--surface-2) 0%,transparent)),
    linear-gradient(to left,color-mix(in srgb,var(--ink) 16%,transparent),transparent)}
.secev pre{background-image:
    linear-gradient(to left,var(--surface),color-mix(in srgb,var(--surface) 0%,transparent)),
    linear-gradient(to left,color-mix(in srgb,var(--ink) 16%,transparent),transparent)}

/* === model-info trust badge (YB-05, 2026-07-09) ===
   Compact top-bar indicator: live model name + TEE label, plus a lock/shield icon whose
   color is the ONLY visual cue for encryption status. Text and icon both come from
   GET /api/model-info at runtime — nothing here is a color for "always trust", it is a
   color for "this call told us so, right now". Green (--trust-green, defined above,
   scoped exception to the --teal-only trust-state rule) fires ONLY when the caller
   passes the .lock-secure modifier; the unmodified state uses --faint (neutral ink),
   never red — a failed/unverified state is silence or neutral, not an alarm color. */
.model-badge{display:flex;align-items:center;gap:4px;flex:none;font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;color:var(--faint);white-space:nowrap}
.model-badge-label{text-transform:none}
.model-badge-lock{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;padding:0;margin:0;border:none;background:none;color:var(--faint);cursor:pointer;border-radius:50%;transition:color .2s ease,background-color .2s ease}
.model-badge-lock:hover,.model-badge-lock:focus-visible{background:var(--surface-2);color:var(--ink-2)}
.model-badge-lock:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.model-badge-lock.lock-secure{color:var(--trust-green)}
.model-badge-lock.lock-secure:hover,.model-badge-lock.lock-secure:focus-visible{background:var(--surface-2);color:var(--trust-green)}
@media (max-width:600px){
  .model-badge-label{display:none} /* mobile .top is an icon-only horizontal-scroll row (see .brand,.btn{flex:none} above) — keep only the lock, same as the other icon buttons */
}

/* === .sec-verify — animated security-check wait indicator (item 11, 2026-07-14) ===
   A small ring spinner settings.js's SecurityView (initial "Loading…" state before
   GET /api/security resolves, and the "TEE — checking…" state before /api/security/verify
   resolves) and main.js's lock popup (model-badge-lock while its live check is in flight)
   can drop next to their existing text/labels and toggle with .is-verifying — motion only,
   no invented color: the ring uses --line (track) and --accent (the same color the lock
   icon and every other "live, in-progress" affordance in this file already uses), and sits
   static/hidden (no spin, no unnecessary paint) until .is-verifying is applied. A --lg
   modifier matches the 22px .model-badge-lock icon size for direct drop-in there; the base
   16px size matches inline use next to body text (e.g. the SecurityView loading line). */
.sec-verify{display:inline-block;width:16px;height:16px;border-radius:50%;border:2px solid var(--line);border-top-color:var(--accent);flex:none;vertical-align:middle}
.sec-verify--lg{width:22px;height:22px;border-width:2.5px}
.sec-verify.is-verifying{animation:sec-verify-spin .8s linear infinite}
@keyframes sec-verify-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.sec-verify.is-verifying{animation:none;opacity:.6}}

/* === composer "Think" toggle (2026-07-09) — existing tokens only, no new hex ===
   Per-message deep-reasoning toggle, sticky until turned off (state lives in chat.js's
   chat state, default OFF). Sized to match the composer's round .clip icon buttons
   (38px tall) so it sits in the same row with no layout shift; base state reserves a
   1px transparent border so toggling .on never changes box size (box-sizing:border-box
   is already global via .yumi-app *). ON state reuses the same accent-border + accent-ink
   language as .icbtn:hover/.box:focus-within/.fld input:focus elsewhere in this file —
   no new color, just the existing "active/focused" token pairing held persistently. */
.think-toggle{display:flex;align-items:center;justify-content:center;gap:5px;height:38px;padding:0 13px;border:1px solid transparent;border-radius:var(--r-pill);background:none;color:var(--mute);font-family:var(--ui);font-size:12.5px;font-weight:600;cursor:pointer;flex:none;line-height:1;white-space:nowrap;transition:border-color .15s,color .15s,background-color .15s}
.think-toggle:hover{color:var(--ink);background:var(--surface-2)}
.think-toggle.on{border-color:var(--accent);color:var(--accent);background:var(--accent-soft)}
.think-toggle.on:hover{background:var(--accent-soft)}
[data-theme="enclave"] .think-toggle{border-radius:var(--r)}
.collab-shell{flex:1;min-height:0;overflow:auto;padding:24px 28px 40px;background:var(--bg);color:var(--ink-2)}
.collab-tabs button{flex:0 0 auto}
.collab-header{max-width:1320px;margin:0 auto 20px;display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.collab-header h1{font:800 clamp(32px,5vw,56px)/1 var(--display);letter-spacing:-.05em;color:var(--ink);margin:2px 0 8px}.collab-kicker,.collab-version{font:600 10px/1.4 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--accent);margin:0}.collab-disclosure{color:var(--mute);margin:0;max-width:72ch;line-height:1.6}.collab-layout{max-width:1320px;margin:auto;display:grid;grid-template-columns:minmax(240px,300px) minmax(0,1fr);gap:18px}.collab-sidebar,.collab-content{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow-sm)}.collab-sidebar{padding:16px;align-self:start}.collab-create label{display:block;font-weight:700;color:var(--ink);margin-bottom:8px}.collab-create-row{display:flex;gap:8px;margin-bottom:18px}.collab-create input{min-width:0;width:100%;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface-2);color:var(--ink);font:inherit;padding:11px 12px}.collab-project{width:100%;min-height:52px;border:1px solid transparent;border-radius:var(--r-sm);background:transparent;color:var(--ink-2);display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;text-align:left;cursor:pointer}.collab-project:hover,.collab-project:focus-visible{border-color:var(--accent)}.collab-project.active{background:var(--accent-soft);color:var(--ink)}.collab-project span{font:10px var(--mono);color:var(--mute)}.collab-content{padding:20px;min-height:520px}.collab-title{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.collab-title h2{margin:0;color:var(--ink);font:800 28px/1.1 var(--display);letter-spacing:-.035em}.collab-title p{margin:5px 0;color:var(--mute)}.collab-tabs{display:flex;gap:4px;overflow-x:auto;padding:18px 0 12px;border-bottom:1px solid var(--line);scrollbar-width:thin}.collab-tabs button{min-height:44px;border:0;border-radius:var(--r-pill);background:transparent;color:var(--mute);font:650 12px var(--ui);padding:0 14px;cursor:pointer;white-space:nowrap}.collab-tabs button.active{background:var(--ink);color:var(--on-ink)}.collab-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;padding-top:16px}.collab-card{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface-2);padding:16px}.collab-card.wide{grid-column:1/-1}.collab-card h3{margin:0 0 8px;color:var(--ink)}.collab-card p{margin:0;color:var(--mute);line-height:1.6}.collab-card.metric span{display:block;color:var(--mute);font-size:12px}.collab-card.metric strong{display:block;color:var(--ink);font:800 34px var(--display);margin-top:8px}.collab-list{display:grid;gap:10px;padding-top:16px}.collab-card-line{display:flex;justify-content:space-between;gap:12px}.collab-status{font:600 10px var(--mono);text-transform:uppercase;color:var(--accent)}.collab-info{margin-top:16px}.collab-info .btn{margin-top:16px}.collab-empty,.collab-empty-state{color:var(--mute);line-height:1.6}.collab-empty-state{display:grid;place-content:center;min-height:380px;text-align:center}.collab-error{max-width:1320px;margin:0 auto 14px;border:1px solid var(--accent);border-radius:var(--r-sm);padding:12px 14px;background:var(--accent-soft);color:var(--ink)}
@media(max-width:760px){.collab-shell{padding:16px 14px 32px}.collab-header{align-items:center}.collab-layout{grid-template-columns:1fr}.collab-sidebar{position:static}.collab-content{padding:14px;min-height:420px}.collab-grid{grid-template-columns:1fr 1fr}.collab-card.wide{grid-column:1/-1}.collab-create-row{flex-direction:column}.collab-create-row .btn{min-height:44px}.collab-tabs button{padding:0 12px}}
@media(prefers-reduced-motion:reduce){.collab-shell *{scroll-behavior:auto!important;transition:none!important}}
