/* ELLA — app frame component layer (navbar · left toolbar · sidebar views).
 *
 * Companion to copilot-tokens.css (shipped in design_handoff_dark_theme/).
 * Append this file to assets/copilot.css, or add it as assets/ella-frame.css —
 * Dash serves every .css in assets/ automatically, in alphabetical order, so
 * ella-frame.css loads AFTER copilot.css. Either works.
 *
 * ── The one rule that matters ──────────────────────────────────────────────
 * These classes only take effect if the matching inline `style={...}` dict is
 * DELETED from the .py file. An inline style beats any class. Every selector
 * below names the .py file and symbol it replaces so the deletion is
 * mechanical. Structural sizing (widths, flex ratios) may stay inline as
 * var() strings per project convention; COLOUR must not.
 *
 * Reused selectors (already in the codebase, restyled here):
 *   .copilot-navbar  .nav-icon-btn  .user-chip  .badge-version
 *   #left-toolbar  .toolbar-icon-btn  .toolbar-icon-btn--active  .toolbar-divider
 *   #copilot-sidebar  #conversation-list  .fsv-*  .custom-checklist
 * New selectors are prefixed .sbv- (sidebar view), .cv- (conversation),
 * .tl- (tools), .ss- (session), .ac- (account), .cmp- (composer).
 */

/* ═════════════════════════════════════════════════════════════════════════
   NAVBAR — clients/dash/navbar.py :: render_nav_bar()
   Delete: the `color="#A6DBA440"` kwarg, the `style={...}` on dbc.Navbar,
   the `style={...}` on dbc.Container, and every inline style on the three
   slot Divs. Delete html.Button("Sign out") entirely — it moves into the
   account menu.
   ═════════════════════════════════════════════════════════════════════════ */
.copilot-navbar{margin:0;padding:0;background:var(--bg-soft);border-bottom:1px solid var(--border)}
.copilot-navbar>.container-fluid{display:flex;align-items:center;position:relative;min-height:56px;padding:6px 12px;margin:0}

.nav-brand{display:flex;align-items:center;z-index:2}
.nav-brand img{height:34px;display:block}

/* Centre title. `white-space:nowrap` is NOT optional — navbar.py sets it
   inline today and the badge + subtitle both wrap without it. */
.nav-center{position:absolute;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;text-align:center;white-space:nowrap;z-index:1}
.navbar-title{display:flex;align-items:center;justify-content:center;gap:7px;font-size:clamp(14px,1.15vw,20px);font-weight:800;line-height:1.1;letter-spacing:.01em;color:var(--ink)}
.navbar-title img{width:24px;height:24px;border-radius:50%;object-fit:cover;display:block;margin:0}
.navbar-subtitle{font-size:clamp(10px,.85vw,14px);color:var(--muted);margin:0;line-height:1.1;margin-top:2px}
/* navbar.py currently sets className="text-dark" on the title and
   className="text-muted" on the subtitle. Both are Bootstrap utilities that
   hardcode a hex and will win against --ink in dark mode. Remove them. */

.badge-version{font-size:10px;font-weight:700;color:var(--accent-ink);background:var(--accent-bg);border:1px solid var(--accent-border);border-radius:5px;padding:2px 7px;letter-spacing:.02em;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;vertical-align:baseline}

.nav-right{margin-left:auto;display:flex;align-items:center;gap:6px;z-index:2}

.nav-icon-btn{width:30px;height:30px;border-radius:7px;border:1px solid transparent;background:none;color:var(--ink-soft);display:grid;place-items:center;cursor:pointer;padding:0;position:relative}
.nav-icon-btn:hover{background:var(--card-bg);border-color:var(--border)}
.nav-unread-badge{position:absolute;top:5px;right:5px;width:7px;height:7px;border-radius:50%;background:var(--orange);border:1.5px solid var(--bg-soft)}

.user-chip{display:flex;align-items:center;gap:7px;padding:4px 8px 4px 5px;border-radius:8px;border:1px solid var(--border);background:var(--card-bg);cursor:pointer;color:inherit}
.user-chip:hover{border-color:var(--border-strong)}
.user-chip .avatar{width:22px;height:22px;border-radius:50%;background:var(--btn-accent-bg);color:var(--btn-accent-ink);display:grid;place-items:center;font-size:10px;font-weight:800}
.user-chip-name{font-size:12.5px;font-weight:600;color:var(--ink);white-space:nowrap}

/* Account menu — new. Replaces the standalone gear button and Sign out
   button. A dbc.Popover(trigger="legacy", target="navbar-user-chip") with
   className="nav-acct-menu" gets this styling; put the items in the body. */
.nav-acct-menu .popover-body{background:var(--overlay-bg);border-radius:10px;padding:5px}
.nav-acct-menu.popover{background:var(--overlay-bg);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md)}
.nav-acct-menu .popover-arrow::after,.nav-acct-menu .popover-arrow::before{border-bottom-color:var(--border)}
.nav-acct-item{display:flex;align-items:center;gap:9px;width:100%;padding:8px 9px;border-radius:7px;border:none;background:none;color:var(--ink);font-size:12.5px;font-weight:600;cursor:pointer;text-align:left;font-family:inherit}
.nav-acct-item:hover{background:var(--accent-bg);color:var(--accent-ink-strong)}
.nav-acct-sep{height:1px;background:var(--border);margin:4px 6px}

/* ═════════════════════════════════════════════════════════════════════════
   LEFT TOOLBAR — clients/dash/components/left_toolbar.py :: LeftToolbar()
   Delete: the `style={...}` on the outer Div and both inner group Divs
   (replaced by #left-toolbar and .toolbar-group).
   ═════════════════════════════════════════════════════════════════════════ */
#left-toolbar{width:48px;flex-shrink:0;height:100%;background:var(--card-bg-soft);border-right:1px solid var(--border);display:flex;flex-direction:column;align-items:center;gap:4px;padding:8px 0;z-index:6}
.toolbar-group{display:flex;flex-direction:column;gap:4px}
.toolbar-spacer{flex:1}
.toolbar-divider{width:24px;height:1px;background:var(--border);margin:4px 0;flex-shrink:0}

.toolbar-icon-btn{width:34px;height:34px;border-radius:9px;border:1px solid transparent;background:none;color:var(--muted);display:grid;place-items:center;cursor:pointer;padding:0;position:relative;font-family:inherit}
.toolbar-icon-btn:hover{background:var(--card-bg);border-color:var(--border);color:var(--ink-soft)}
.toolbar-icon-btn--active{background:var(--accent-bg);border-color:var(--accent-border);color:var(--accent-ink-strong)}
/* Active marker bleeds into the toolbar's left edge. */
.toolbar-icon-btn--active::before{content:"";position:absolute;left:-8px;top:7px;bottom:7px;width:2px;border-radius:0 2px 2px 0;background:var(--accent)}

/* Hover label. The current `title=` attribute is a native tooltip with a
   ~1s delay; this shows immediately. Add a
   html.Span(tooltip, className="toolbar-tip") inside each button and KEEP
   title= for screen readers. */
.toolbar-tip{position:absolute;left:44px;top:50%;transform:translateY(-50%);background:var(--overlay-bg);border:1px solid var(--border);color:var(--ink);font-size:11.5px;font-weight:600;padding:4px 8px;border-radius:6px;box-shadow:var(--shadow-sm);pointer-events:none;opacity:0;transition:opacity .1s;z-index:20;white-space:nowrap}
.toolbar-icon-btn:hover .toolbar-tip{opacity:1}

/* ELLA note on --muted-2: copilot.css reserves it for graphical marks and
   text >=19px (it is 2.49:1 on --card-bg-soft in light mode). Small
   informational text in this file therefore uses --muted (4.59:1 light /
   6.48:1 dark). --muted-2 is kept only for actual marks — .fsv-file-dot,
   .cv-row-icon, .ac-row-gear, .tl-caret, the search glyph — and for the
   deliberately-recessive .fsv-file-row--disabled state. */

/* ═════════════════════════════════════════════════════════════════════════
   SIDEBAR SHELL — clients/dash/sidebar.py
   Delete: _SIDEBAR_STYLE's colour keys (background, borderRight). Keep its
   width/minWidth/maxWidth/flexShrink — those are structural. Delete
   #sidebar-divider-handle and both flexGrow:0.5 section wrappers entirely;
   the two-section split is replaced by five sibling views.
   ═════════════════════════════════════════════════════════════════════════ */
#copilot-sidebar{background:var(--card-bg-soft);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden;height:100%;position:relative;min-height:0}

/* One view per toolbar tab. Exactly one has no `hidden` attribute; the
   switch_sidebar_view callback toggles `hidden` rather than re-rendering. */
.sbv{flex:1;min-height:0;display:flex;flex-direction:column}
.sbv[hidden]{display:none}

/* View header — the .fsv-h pattern from file_system_viewer.py, generalised. */
.sbv-head{padding:12px 14px;border-bottom:1px solid var(--border);flex-shrink:0}
.sbv-label{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.sbv-sub{font-size:11px;color:var(--muted);margin-top:2px}
/* Inline variant for views whose header carries an action instead of a rule. */
.sbv-head--inline{display:flex;align-items:center;gap:8px;padding:12px 12px 0;border-bottom:none}
.sbv-head--inline .sbv-title{font-size:13px;font-weight:800;letter-spacing:-.01em;color:var(--ink);white-space:nowrap}
.sbv-tag{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--accent-ink);background:var(--accent-bg);border-radius:4px;padding:2px 6px;white-space:nowrap}
.sbv-action{margin-left:auto;font-size:10.5px;font-weight:700;color:var(--accent-ink);background:none;border:none;cursor:pointer;padding:2px 4px;border-radius:5px;font-family:inherit}
.sbv-action:hover{background:var(--accent-bg)}

.sbv-scroll{flex:1;min-height:0;overflow-y:auto}
.sbv-foot{flex-shrink:0;border-top:1px solid var(--border);padding:8px}
.sbv-foot--bar{display:flex;align-items:center;gap:8px;padding:10px 14px}
.sbv-note{flex-shrink:0;font-size:10.5px;color:var(--muted);padding:8px 14px;border-top:1px solid var(--border);text-align:center;text-wrap:pretty}

/* Right-edge resize handle — already #sidebar-resize-handle in sidebar.py.
   Keep its inline position/width; this adds the hover affordance. */
.resizable-handle-horizontal{cursor:col-resize}
.resizable-handle-horizontal:hover{background:var(--accent-border)}

/* ═════════════════════════════════════════════════════════════════════════
   CONVERSATIONS VIEW — sidebar.py top section, rebuilt search-led
   ═════════════════════════════════════════════════════════════════════════ */
.cv-head{padding:12px;flex-shrink:0;display:flex;flex-direction:column;gap:9px}

/* Search. Delete the inline style on dcc.Input#sidebar-search-input AND the
   absolutely-positioned "🔍" html.Span — the glyph becomes an inline SVG
   sibling styled by .sb-search>svg. */
.sb-search{position:relative;display:flex;align-items:center}
.sb-search>svg,.sb-search>.ella-ico{position:absolute;left:11px;color:var(--muted-2);pointer-events:none}
/* ELLA: icons are .ella-ico mask spans, not inline <svg> (dash.html has no
   SVG tags — see components/icons.py). Without the second selector the
   search icon fell out of the absolutely-positioned slot and rendered to
   the LEFT of the input box instead of inside it. */
.sb-search input{width:100%;padding:10px 44px 10px 34px;border:1px solid var(--border-strong);border-radius:8px;background:var(--card-bg);font-size:13px;font-family:inherit;color:var(--ink);outline:none}
.sb-search input:focus{border-color:var(--accent-border);box-shadow:0 0 0 3px var(--focus-ring)}
.sb-search-kbd{position:absolute;right:9px;font-size:9.5px;color:var(--muted);border:1px solid var(--border);border-radius:4px;padding:1px 4px;background:var(--bg-soft);pointer-events:none;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

/* Project filter chips. nowrap + flex-shrink:0 are load-bearing: without
   them "SOX-A" hyphen-breaks inside its own pill. */
.cv-filters{display:flex;flex-wrap:wrap;gap:5px}
/* inline-flex + gap so a chip with a glyph (Pinned, Shared) does not butt the
   icon against its own label — the default inline layout gives them 0px. */
.cv-chip{font-size:11px;font-weight:600;color:var(--chip-ink);border:1px solid var(--chip-border);background:var(--chip-bg);border-radius:20px;padding:3px 9px;cursor:pointer;flex-shrink:0;white-space:nowrap;font-family:inherit;display:inline-flex;align-items:center;gap:4px}
.cv-chip:hover{border-color:var(--border-strong);color:var(--ink)}
.cv-chip--on{background:var(--accent-bg);border-color:var(--accent-border);color:var(--accent-ink-strong)}

/* New conversation — delete the inline style on #btn-new-conversation.
   Note the surface change: --btn-accent-bg (#0b6623), not LIGHTGREEN.
   White on #4CB748 is 2.9:1 and fails even the 3:1 glyph floor. */
.btn-new-conversation{width:100%;display:flex;align-items:center;justify-content:center;gap:7px;padding:9px 12px;background:var(--btn-accent-bg);color:var(--btn-accent-ink);font-weight:700;font-size:13px;border:none;border-radius:8px;cursor:pointer;font-family:inherit}
.btn-new-conversation:hover{background:var(--btn-accent-bg-hover)}

#conversation-list{padding:2px 8px 8px}
.cv-group-head{display:flex;align-items:center;gap:6px;font-size:10px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.09em;padding:6px 6px 4px}
.cv-count{margin-left:auto;font-weight:600;letter-spacing:0;color:var(--muted);text-transform:none;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

.cv-row{display:flex;align-items:center;gap:8px;padding:8px;border-radius:7px;cursor:pointer;border:none;background:none;width:100%;text-align:left;font-family:inherit;color:inherit}
.cv-row:hover{background:var(--card-bg)}
.cv-row--active{background:var(--accent-bg);box-shadow:inset 2px 0 0 var(--accent)}
/* The pin is one glyph in two weights (icons.py: `pin` stroked, `pin-fill`
   solid). UNPINNED it is a control, so it stays out of the way until the row
   is hovered or the button itself is keyboard-focused — `visibility`, not
   `display`, so the row's flex layout does not shift by 14px on hover.
   PINNED it is state, so it is always visible: a pin you cannot see without
   hovering every row is a pin you cannot find again. */
.cv-row-icon{flex-shrink:0;color:var(--muted-2);display:grid;place-items:center;
  visibility:hidden;opacity:0;transition:opacity .15s;background:none;border:none;
  padding:0;cursor:pointer}
.cv-row:hover .cv-row-icon,.cv-row-icon:focus-visible,.cv-row--active .cv-row-icon{
  visibility:visible;opacity:1}
.cv-row-icon:hover{color:var(--ink)}
.cv-row-icon:focus-visible{outline:none;border-radius:4px;
  box-shadow:0 0 0 2px var(--accent-border)}
.cv-row--active .cv-row-icon{color:var(--accent-ink)}
.cv-row-icon--pinned{color:var(--orange);visibility:visible;opacity:1}
.cv-row:hover .cv-row-icon--pinned,.cv-row--active .cv-row-icon--pinned{
  visibility:visible;opacity:1}
/* min-width:0 + overflow on the column is what makes the ellipsis work.
   A block parent with inline children silently disables text-overflow. */
.cv-row-text{min-width:0;display:flex;flex-direction:column;gap:1px;overflow:hidden}
/* The title row is now a flex line (title + optional shared badge), so the
   ellipsis has to live on the text span: `text-overflow` needs a block-level
   box whose overflow it governs, and a flex CONTAINER is not that box. */
.cv-row-title{font-size:12.5px;font-weight:600;color:var(--ink);display:flex;
  align-items:center;gap:5px;min-width:0}
.cv-row-title-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cv-row--active .cv-row-title{color:var(--accent-ink-strong)}
/* Shared badge: state, not a control, so it never hides on hover. Muted so it
   reads as an annotation on the title rather than competing with it. */
.cv-row-shared{flex-shrink:0;color:var(--muted);display:grid;place-items:center}
.cv-row--shared:hover .cv-row-shared,.cv-row--active .cv-row-shared{color:var(--accent-ink)}
.cv-row-meta{font-size:10.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cv-row-when{margin-left:auto;flex-shrink:0;font-size:10px;color:var(--muted);white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.cv-empty{padding:26px 20px;text-align:center;font-size:12px;color:var(--muted);line-height:1.5;text-wrap:pretty}

/* Compact model + context strip — sidebar.py :: _conversations_meta().
   Outside .sbv-scroll (never scrolls away), between the list and the account
   row. The full-size versions of the same two controls live in the session
   view; both surfaces share ids via components/METER_SURFACES, so this only
   needs layout, not a second copy of .ella-model-select / .ss-meter. */
.cv-meta{flex-shrink:0;padding:8px 12px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:2px}
.cv-meta-row{display:flex;align-items:center;gap:8px}
.cv-meta-key{font-size:10.5px;color:var(--muted);white-space:nowrap;flex-shrink:0;width:44px}
.cv-meta-row .ella-model-select{flex:1;min-width:0}
.cv-meta-row [id*="token-count"]{flex:1;min-width:0}
.cv-meta-more{margin-left:auto;flex-shrink:0;font-size:10.5px;font-weight:600;color:var(--accent-ink);background:none;border:none;padding:0;cursor:pointer;font-family:inherit}
.cv-meta-more:hover{text-decoration:underline}
.cv-meta .ss-meter{margin:4px 0 0}
/* "more models…" / "fewer models" link under each model picker. */
.model-list-toggle{display:block;margin-top:3px;font-size:10.5px;font-weight:600;color:var(--accent-ink);background:none;border:none;padding:0;cursor:pointer;font-family:inherit}
.model-list-toggle:hover{text-decoration:underline}
/* In the compact strip, line the toggle up under the dropdown, not the 44px key column. */
.cv-meta .model-list-toggle{margin-left:52px}

/* Account row in the sidebar footer. */
.ac-row{display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:8px;cursor:pointer;width:100%;border:none;background:none;text-align:left;font-family:inherit;color:inherit}
.ac-row:hover{background:var(--card-bg)}
.ac-row-avatar{width:28px;height:28px;border-radius:50%;background:var(--btn-accent-bg);color:var(--btn-accent-ink);display:grid;place-items:center;font-size:11px;font-weight:800;flex-shrink:0}
.ac-row-text{min-width:0;display:flex;flex-direction:column;gap:1px;overflow:hidden}
.ac-row-name{font-size:12.5px;font-weight:700;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ac-row-email{font-size:10.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ac-row-gear{margin-left:auto;color:var(--muted-2);flex-shrink:0}

/* ═════════════════════════════════════════════════════════════════════════
   TOOLS VIEW — sidebar.py :: _tools_section()
   Delete every inline style in _tools_section() and _tool_checklist_option().
   The nested html.Details per category stays; it gains .tl-cat.
   ═════════════════════════════════════════════════════════════════════════ */
.tl-cat{margin:0 8px 4px;border:1px solid var(--border);border-radius:9px;background:var(--card-bg);overflow:hidden}
.tl-cat>summary{display:flex;align-items:center;gap:7px;padding:8px 10px;cursor:pointer;list-style:none;font-size:10px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;user-select:none}
.tl-cat>summary::-webkit-details-marker{display:none}
.tl-cat>summary .tl-caret{transition:transform .12s;color:var(--muted-2);display:grid;place-items:center}
.tl-cat[open]>summary .tl-caret{transform:rotate(90deg)}
.tl-cat>summary .cv-count{margin-left:auto}
.tl-items{padding:0 10px 8px;display:flex;flex-direction:column;gap:2px}

/* dbc.Checklist renders <label><input><span>. Drop inputStyle /
   labelStyle / label_checked_style and set className="tl-list"; the
   accent-color and the checked-state colour come from here so they follow
   the theme instead of pinning C["DARKGREEN"]. */
.tl-opt{display:flex;align-items:flex-start;gap:9px;padding:7px 4px;border-radius:6px;cursor:pointer;margin:0}
.tl-opt:hover{background:var(--accent-bg-soft)}
.tl-list input,.tl-opt input{margin:1px 0 0;accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}

/* ELLA: dbc.Checklist / dbc.RadioItems render Bootstrap `.form-check-input`,
   which sets `appearance: none` and paints the tick with its own
   background-color + background-image. `accent-color` above therefore never
   reaches it and every box came up Bootstrap blue (.claude/rules/dash-ui.md: no Bootstrap
   blue, ever). These are the same overrides `.custom-checklist` applies in
   copilot.css, re-pointed at tokens so they hold in both themes — the old
   kwargs pinned --darkgreen, which is ~1.3:1 on a dark surface. */
/* dbc renders `<div.form-check><input.form-check-input><label.form-check-label>`
   — the input is a SIBLING of the label, not a child. The `.tl-list label`
   rule above therefore lays out the label's own contents, and the row itself
   has to be the flex container, or the box stacks above its text. */
.tl-list .form-check{display:flex;align-items:flex-start;gap:9px;margin:0;padding:7px 4px;border-radius:6px}
.tl-list .form-check:hover{background:var(--accent-bg-soft)}
/* float:none + margin-left:0 undo Bootstrap's hanging indent (the input floats
   left with margin-left:-1.5em into .form-check's padding-left). In a flex row
   the float has nothing to hang into and the boxes rendered half outside the
   sidebar's left edge. */
.tl-list .form-check-input{accent-color:var(--accent);background-color:var(--bg);border:1.5px solid var(--border-strong);margin:2px 0 0;float:none;flex-shrink:0;cursor:pointer}
.tl-list .form-check-input:checked{background-color:var(--accent);border-color:var(--accent)}
.tl-list .form-check-input:focus{border-color:var(--accent-border);box-shadow:0 0 0 3px var(--focus-ring)}
.tl-list .form-check-label{cursor:pointer;min-width:0;padding:0}
.tl-name{font-size:12px;font-weight:600;color:var(--ink);display:block}
.tl-desc{font-size:10.5px;color:var(--muted);line-height:1.35;margin-top:1px;text-wrap:pretty;display:block}
/* Unchecked tools read one step back so the enabled set is scannable. */
.tl-list input:not(:checked)~* .tl-name,.tl-opt input:not(:checked)~div .tl-name{color:var(--ink-soft);font-weight:500}

/* ═════════════════════════════════════════════════════════════════════════
   SESSION VIEW — sidebar.py session-stats block
   Delete every inline style in the `id="session-stats"` subtree and on
   #btn-compress-session, #model-select, #token-meter-fill.
   ═════════════════════════════════════════════════════════════════════════ */
.ss-panel{margin:0 12px 10px;border:1px solid var(--border);border-radius:10px;background:var(--card-bg);padding:10px 12px}
.ss-panel-head{font-size:10px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.09em;display:flex;align-items:center;gap:6px;margin-bottom:8px}
.ss-stat{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:5px 0}
.ss-stat-key{font-size:11.5px;color:var(--muted);white-space:nowrap}
.ss-stat-val{font-size:11.5px;color:var(--ink);white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.ss-meter{height:4px;border-radius:4px;background:var(--bg-soft);overflow:hidden;margin:4px 0 2px}
/* The model picker + context meter render TWICE now (convos view + session
   view) via pattern-matching ids ({"type": "token-meter-fill"|"token-count",
   "index": "convos"|"session"}) — Dash serialises those into the DOM `id`
   attribute as a JSON string, so a plain #token-meter-fill selector stopped
   matching anything the moment this stopped being a single id. `[id*=...]`
   matches either instance without caring about key order. */
[id*="token-meter-fill"]{display:block;height:100%;background:var(--accent);border-radius:4px}
/* ELLA: the token-count span holds TWO children (cache + convo, written by
   update_token_display). Without a gap they render as "0 cache0 convo / 1M". */
[id*="token-count"]{display:inline-flex;gap:7px;align-items:baseline}
/* Past ~75% of context the meter turns amber. Set this class from the same
   callback that writes the width. Dead in practice today — the fill's own
   `background` is always set inline (the gradient in _token_meter_gradient),
   which outranks this rule — but kept in case that inline write is ever
   dropped. */
.ss-meter--warn>span{background:var(--orange)}
.ss-hint{font-size:10.5px;color:var(--muted);line-height:1.45;margin-top:7px;text-wrap:pretty}

/* Shared control shells. */
.ella-select{width:100%;padding:7px 9px;border-radius:7px;border:1px solid var(--border-strong);background:var(--bg);color:var(--ink);font-size:11.5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;outline:none;cursor:pointer}
.btn-ghost{width:100%;padding:7px;border-radius:7px;border:1px solid var(--accent-border);background:none;color:var(--accent-ink);font-size:11.5px;font-weight:700;cursor:pointer;margin-top:8px;font-family:inherit}
.btn-ghost:hover{background:var(--accent-bg)}
.btn-outline{background:none;border:1px solid var(--border-strong);border-radius:8px;color:var(--ink-soft);font-size:12px;font-weight:600;cursor:pointer;padding:6px 12px;font-family:inherit}
.btn-outline:hover{border-color:var(--accent-border);color:var(--accent-ink)}
.btn-primary-ella{background:var(--btn-accent-bg);border:none;border-radius:8px;color:var(--btn-accent-ink);font-size:12px;font-weight:700;cursor:pointer;padding:6px 16px;font-family:inherit}
.btn-primary-ella:hover{background:var(--btn-accent-bg-hover)}

/* ═════════════════════════════════════════════════════════════════════════
   FILES VIEW — components/file_system_viewer.py
   Structure is already right. Delete the inline styles in _file_row(),
   _folder_summary(), FileSystemViewer() and the truncation Div; keep the
   paddingLeft depth calculation inline (it is data, not theme).
   ═════════════════════════════════════════════════════════════════════════ */
.fsv-tree{padding:8px 10px 12px;min-width:0}
.fsv-details>summary,.fsv-summary{display:flex;align-items:center;gap:6px;padding:2px 0;cursor:pointer;list-style:none;min-width:0}
.fsv-details>summary::-webkit-details-marker,.fsv-summary::-webkit-details-marker{display:none}
.fsv-summary:hover{background:var(--accent-bg-soft)}
.fsv-caret{width:12px;flex-shrink:0;font-size:10px;color:var(--accent-ink);transition:transform .12s;display:inline-block;text-align:center}
.fsv-details[open]>summary .fsv-caret{transform:rotate(90deg)}
.fsv-folder-name{font-weight:700;font-size:12px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fsv-file-row{display:flex;align-items:center;gap:6px;padding:2px 4px;border-radius:5px;cursor:pointer;min-width:0}
.fsv-file-row:hover{background:var(--card-bg)}
.fsv-file-dot{width:12px;flex-shrink:0;color:var(--muted-2);text-align:center;font-size:12px}
.fsv-file-name{font-size:12px;color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fsv-file-row--disabled{cursor:default}
.fsv-file-row--disabled .fsv-file-name{color:var(--muted-2)}
.fsv-file-row--disabled:hover{background:none}
.fsv-truncated{font-size:11px;color:var(--muted);font-style:italic;padding:2px 0}
.fsv-root-dropdown{margin-top:6px}

/* File viewer modal — components/file_viewer_modal.py. --code-bg is dark in
   BOTH themes by design; the gutter/code pair does not invert. */
.fv-modal .modal-content{background:var(--overlay-bg);border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow-md);overflow:hidden}
.fv-head{display:flex;align-items:center;gap:10px;padding:11px 14px;border-bottom:1px solid var(--border);flex-shrink:0;min-width:0}
.fv-name{font-size:13.5px;font-weight:800;color:var(--ink);flex-shrink:0}
.fv-path{font-size:10.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.fv-body{flex:1;min-height:0;overflow:auto;background:var(--code-bg)}
.fv-code-wrap{display:flex;min-height:100%}
.fv-gutter{padding:12px 10px;text-align:right;color:var(--code-ink-soft);background:var(--code-bg-head);border-right:1px solid var(--code-border);user-select:none;margin:0;flex-shrink:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.6}
.fv-code{padding:12px 14px;color:var(--code-ink);margin:0;white-space:pre;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.6}
.fv-markdown{padding:16px 20px;color:var(--code-ink);font-size:13px;line-height:1.6}
.fv-truncated-note{font-size:11.5px;color:var(--warn-ink);background:var(--warn-bg);border:1px solid var(--warn-border);padding:6px 10px;border-radius:6px;margin:10px 14px 0}
/* Rendered / Raw toggle — class names match components/file_viewer_modal.py's
   actual markup (.fv-seg wrapper, .fv-seg-btn / .fv-seg-btn--active buttons),
   not the .fv-seg--on variant a prior pass here invented: that selector never
   matched anything Python emits, and the plain `.fv-seg button` catch-all it
   shipped alongside outranked .fv-seg-btn--active's specificity, silently
   erasing the active/inactive visual distinction. */
.fv-seg{display:flex;border:1px solid var(--border);border-radius:7px;overflow:hidden;flex-shrink:0;margin-left:auto}
.fv-seg-btn{border:none;background:none;padding:4px 10px;font-size:11px;font-weight:700;color:var(--muted);cursor:pointer;font-family:inherit}
.fv-seg-btn:hover{background:var(--accent-bg-soft);color:var(--accent-ink)}
.fv-seg-btn--active{background:var(--accent-bg);color:var(--accent-ink-strong)}

/* ═════════════════════════════════════════════════════════════════════════
   ACCOUNT VIEW — components/account_sidebar_view.py
   Delete _section_label()'s style dict and every inputStyle / labelStyle /
   label_checked_style kwarg (they pin C["DARKGREEN"], which is 1.3:1 on a
   dark surface). Set className="tl-list" on the RadioItems/Checklist.
   ═════════════════════════════════════════════════════════════════════════ */
.ac-group{margin-bottom:18px;padding:0 14px}
.ac-section-label{font-size:10.5px;font-weight:800;color:var(--accent-ink);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px}
.ac-opt-label{font-size:12.5px;font-weight:700;color:var(--ink);display:block}
.tl-list input:checked~* .ac-opt-label{color:var(--accent-ink)}
.ac-opt-desc{font-size:11px;color:var(--muted);line-height:1.35;margin-top:1px;text-wrap:pretty;display:block}
.ac-opts-inline{display:flex;gap:16px}
.ac-opts-inline label{align-items:center}
.ac-save-status{font-size:11px;color:var(--accent-ink);margin-right:auto}

/* dbc.Switch. Bootstrap's own .form-switch paints a blue thumb and a
   hardcoded grey track; this overrides both so the switch follows --accent.
   Drop the input_style={"accentColor": ...} kwarg. */
.ella-switch .form-check-input{appearance:none;width:34px;height:19px;border-radius:20px;background:var(--border-strong);border:none;position:relative;cursor:pointer;transition:background .15s;margin:0;flex-shrink:0;box-shadow:none}
.ella-switch .form-check-input:checked{background:var(--accent)}
.ella-switch .form-check-input::after{content:"";position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;background:#fff;transition:transform .15s}
.ella-switch .form-check-input:checked::after{transform:translateX(15px)}
.ella-switch .form-check-label{font-size:12.5px;color:var(--ink);font-weight:600;margin-left:9px;cursor:pointer}

/* ═════════════════════════════════════════════════════════════════════════
   COMPOSER META PILLS — clients/dash/chat.py
   Model and context usage left the sidebar, so the composer is now the only
   always-visible place they appear. These are BUTTONS: each one opens its
   sidebar view (model + usage → session, tools → tools), which is how the
   detail stays reachable without a permanent panel.
   ═════════════════════════════════════════════════════════════════════════ */
/* One row that scrolls sideways, never wraps: a long model id must not push
   the usage pill onto a second line (React mirrors this inline, EL-571). */
.cmp-bar{display:flex;align-items:center;gap:6px;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:thin}
.cmp-pill{font-size:10.5px;font-weight:600;color:var(--chip-ink);border:1px solid var(--chip-border);background:var(--chip-bg);border-radius:20px;padding:3px 9px;cursor:pointer;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.cmp-pill:hover,.cmp-pill:focus-visible{border-color:var(--border-strong);color:var(--ink)}
.cmp-pill:focus-visible{outline:2px solid var(--lightgreen);outline-offset:1px}
/* Amber past ~75% of the window — the only pill that changes colour. */
.cmp-pill--warn{color:var(--warn-ink);background:var(--warn-bg);border-color:var(--warn-border)}
.cmp-send{margin-left:auto;width:30px;height:30px;border-radius:50%;background:var(--btn-accent-bg);border:none;display:grid;place-items:center;color:var(--btn-accent-ink);cursor:pointer;flex-shrink:0}
.cmp-send:hover{background:var(--btn-accent-bg-hover)}

/* ═════════════════════════════════════════════════════════════════════════
   GUARDRAILS — do not delete these three rules
   ═════════════════════════════════════════════════════════════════════════ */
/* 1. Buttons default to the UA `buttontext` keyword, which is white in dark
      mode and black in light — it ignores --ink entirely. Every control in
      the frame is a <button>, so without this the theme leaks.
      `:where()` keeps it at element specificity (0,0,1). Written as
      `#app-shell button` it was (1,0,1) and beat EVERY class-level button
      colour — .btn-new-conversation, .btn-primary-ella, .cmp-send — so those
      rendered --ink on their --btn-accent-bg fill: #1f2d3d on #0b6623, ~1.9:1,
      in light mode (measured live, EL-551). */
:where(#app-shell) button{color:inherit}

/* 2. Bootstrap text utilities hardcode hexes and outrank the tokens.
      navbar.py uses text-dark and text-muted today. */
#app-shell[data-theme='dark'] .text-dark{color:var(--ink)!important}
#app-shell[data-theme='dark'] .text-muted{color:var(--muted)!important}

/* 3. Native scrollbars inside sidebar views. */
#app-shell[data-theme='dark'] .sbv-scroll::-webkit-scrollbar-thumb,
#app-shell[data-theme='dark'] .fsv-tree::-webkit-scrollbar-thumb{background:var(--border-strong)}

/* ── Icons — generated by clients/dash/components/icons.py ─────────────────
   Regenerate with: python -m clients.dash.components.icons
   A masked span, not an emoji and not an <svg>: dash.html has no SVG tags,
   and a mask filled with currentColor is how the repo already themes the
   feedback thumbs (.ella-thumb-glyph). Size comes from --ico, set inline. */
.ella-ico{display:inline-block;width:var(--ico,16px);height:var(--ico,16px);flex-shrink:0;background-color:currentColor;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;-webkit-mask-size:contain;mask-size:contain;pointer-events:none}
.ella-ico--bell{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M18%208A6%206%200%20006%208c0%207-3%209-3%209h18s-3-2-3-9%27%2F%3E%3Cpath%20d%3D%27M13.7%2021a2%202%200%2001-3.4%200%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M18%208A6%206%200%20006%208c0%207-3%209-3%209h18s-3-2-3-9%27%2F%3E%3Cpath%20d%3D%27M13.7%2021a2%202%200%2001-3.4%200%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--moon{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M21%2012.8A9%209%200%201111.2%203a7%207%200%20009.8%209.8z%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M21%2012.8A9%209%200%201111.2%203a7%207%200%20009.8%209.8z%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--sun{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%274%27%2F%3E%3Cpath%20d%3D%27M12%202v2M12%2020v2M4.9%204.9l1.4%201.4M17.7%2017.7l1.4%201.4M2%2012h2M20%2012h2M4.9%2019.1l1.4-1.4M17.7%206.3l1.4-1.4%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%274%27%2F%3E%3Cpath%20d%3D%27M12%202v2M12%2020v2M4.9%204.9l1.4%201.4M17.7%2017.7l1.4%201.4M2%2012h2M20%2012h2M4.9%2019.1l1.4-1.4M17.7%206.3l1.4-1.4%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--chevron-down{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M6%209l6%206%206-6%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M6%209l6%206%206-6%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--sign-out{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M9%2021H5a2%202%200%2001-2-2V5a2%202%200%20012-2h4M16%2017l5-5-5-5M21%2012H9%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M9%2021H5a2%202%200%2001-2-2V5a2%202%200%20012-2h4M16%2017l5-5-5-5M21%2012H9%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--chat{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M21%2011.5a8.4%208.4%200%2001-9%208.4%209%209%200%2001-4-.9L3%2021l1.9-4.6A8.4%208.4%200%20013%2011.5%208.4%208.4%200%200112%203a8.4%208.4%200%20019%208.5z%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M21%2011.5a8.4%208.4%200%2001-9%208.4%209%209%200%2001-4-.9L3%2021l1.9-4.6A8.4%208.4%200%20013%2011.5%208.4%208.4%200%200112%203a8.4%208.4%200%20019%208.5z%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--tools{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M14.7%206.3a4%204%200%20105.3%205.3L21%2021H3l9.4-1a4%204%200%20012.3-13.7z%27%2F%3E%3Cpath%20d%3D%27M15%209l-9%209%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M14.7%206.3a4%204%200%20105.3%205.3L21%2021H3l9.4-1a4%204%200%20012.3-13.7z%27%2F%3E%3Cpath%20d%3D%27M15%209l-9%209%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--gauge{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2019V9M10%2019V5M16%2019v-7M22%2019H2%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2019V9M10%2019V5M16%2019v-7M22%2019H2%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--sitemap{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%279%27%20y%3D%272%27%20width%3D%276%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Crect%20x%3D%272%27%20y%3D%2717%27%20width%3D%275.5%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Crect%20x%3D%279.25%27%20y%3D%2717%27%20width%3D%275.5%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Crect%20x%3D%2716.5%27%20y%3D%2717%27%20width%3D%275.5%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Cpath%20d%3D%27M12%207v5M4.75%2017v-2.5h14.5V17M12%2012v5%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%279%27%20y%3D%272%27%20width%3D%276%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Crect%20x%3D%272%27%20y%3D%2717%27%20width%3D%275.5%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Crect%20x%3D%279.25%27%20y%3D%2717%27%20width%3D%275.5%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Crect%20x%3D%2716.5%27%20y%3D%2717%27%20width%3D%275.5%27%20height%3D%275%27%20rx%3D%271%27%2F%3E%3Cpath%20d%3D%27M12%207v5M4.75%2017v-2.5h14.5V17M12%2012v5%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--folder{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M3%207a2%202%200%20012-2h4l2%202h8a2%202%200%20012%202v8a2%202%200%2001-2%202H5a2%202%200%2001-2-2z%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M3%207a2%202%200%20012-2h4l2%202h8a2%202%200%20012%202v8a2%202%200%2001-2%202H5a2%202%200%2001-2-2z%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--user{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%278%27%20r%3D%273.6%27%2F%3E%3Cpath%20d%3D%27M4.5%2020a7.5%207.5%200%200115%200%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%278%27%20r%3D%273.6%27%2F%3E%3Cpath%20d%3D%27M4.5%2020a7.5%207.5%200%200115%200%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--menu{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%206h16M4%2012h16M4%2018h16%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%206h16M4%2012h16M4%2018h16%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--plus{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%205v14M5%2012h14%27%20stroke-width%3D%272.4%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%205v14M5%2012h14%27%20stroke-width%3D%272.4%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--capabilities{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%279%27%2F%3E%3Cpath%20d%3D%27M12%203a9%209%200%20010%2018z%27%20fill%3D%27currentColor%27%20stroke%3D%27none%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%279%27%2F%3E%3Cpath%20d%3D%27M12%203a9%209%200%20010%2018z%27%20fill%3D%27currentColor%27%20stroke%3D%27none%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--grid{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%273%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%2713.5%27%20y%3D%273%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%273%27%20y%3D%2713.5%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%2713.5%27%20y%3D%2713.5%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%273%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%2713.5%27%20y%3D%273%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%273%27%20y%3D%2713.5%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%2713.5%27%20y%3D%2713.5%27%20width%3D%277.5%27%20height%3D%277.5%27%20rx%3D%271.5%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--download{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203v12M7%2011l5%205%205-5M4%2020h16%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203v12M7%2011l5%205%205-5M4%2020h16%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--search{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2711%27%20cy%3D%2711%27%20r%3D%277%27%2F%3E%3Cpath%20d%3D%27M20%2020l-4.3-4.3%27%20stroke-width%3D%272%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2711%27%20cy%3D%2711%27%20r%3D%277%27%2F%3E%3Cpath%20d%3D%27M20%2020l-4.3-4.3%27%20stroke-width%3D%272%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--gear{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%273%27%2F%3E%3Cpath%20d%3D%27M19.4%2015a1.7%201.7%200%2000.3%201.9l.1.1a2%202%200%2011-2.8%202.8l-.1-.1a1.7%201.7%200%2000-2.9%201.2%202%202%200%2011-4%200%201.7%201.7%200%2000-2.9-1.2l-.1.1a2%202%200%2011-2.8-2.8l.1-.1A1.7%201.7%200%20002.6%2015a2%202%200%20110-4%201.7%201.7%200%20001.2-2.9l-.1-.1a2%202%200%20112.8-2.8l.1.1A1.7%201.7%200%20009.5%204.1a2%202%200%20114%200%201.7%201.7%200%20002.9%201.2l.1-.1a2%202%200%20112.8%202.8l-.1.1a1.7%201.7%200%20001.2%202.9%202%202%200%20110%204z%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%273%27%2F%3E%3Cpath%20d%3D%27M19.4%2015a1.7%201.7%200%2000.3%201.9l.1.1a2%202%200%2011-2.8%202.8l-.1-.1a1.7%201.7%200%2000-2.9%201.2%202%202%200%2011-4%200%201.7%201.7%200%2000-2.9-1.2l-.1.1a2%202%200%2011-2.8-2.8l.1-.1A1.7%201.7%200%20002.6%2015a2%202%200%20110-4%201.7%201.7%200%20001.2-2.9l-.1-.1a2%202%200%20112.8-2.8l.1.1A1.7%201.7%200%20009.5%204.1a2%202%200%20114%200%201.7%201.7%200%20002.9%201.2l.1-.1a2%202%200%20112.8%202.8l-.1.1a1.7%201.7%200%20001.2%202.9%202%202%200%20110%204z%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--caret-right{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M9%205l7%207-7%207%27%20stroke-width%3D%272.2%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M9%205l7%207-7%207%27%20stroke-width%3D%272.2%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--star{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203.5l2.6%205.3%205.9.9-4.2%204.1%201%205.8-5.3-2.8-5.3%202.8%201-5.8L3.5%209.7l5.9-.9z%27%20fill%3D%27currentColor%27%20stroke%3D%27none%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203.5l2.6%205.3%205.9.9-4.2%204.1%201%205.8-5.3-2.8-5.3%202.8%201-5.8L3.5%209.7l5.9-.9z%27%20fill%3D%27currentColor%27%20stroke%3D%27none%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--pin{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2017v5%27%20stroke-width%3D%272%27%2F%3E%3Cpath%20d%3D%27M5%2017h14v-1.76a2%202%200%2000-1.11-1.79l-1.78-.9A2%202%200%200115%2010.76V6h1a2%202%200%20000-4H8a2%202%200%20000%204h1v4.76a2%202%200%2001-1.11%201.79l-1.78.9A2%202%200%20005%2015.24z%27%20stroke-width%3D%272%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2017v5%27%20stroke-width%3D%272%27%2F%3E%3Cpath%20d%3D%27M5%2017h14v-1.76a2%202%200%2000-1.11-1.79l-1.78-.9A2%202%200%200115%2010.76V6h1a2%202%200%20000-4H8a2%202%200%20000%204h1v4.76a2%202%200%2001-1.11%201.79l-1.78.9A2%202%200%20005%2015.24z%27%20stroke-width%3D%272%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--pin-fill{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2017v5%27%20stroke-width%3D%272%27%2F%3E%3Cpath%20d%3D%27M5%2017h14v-1.76a2%202%200%2000-1.11-1.79l-1.78-.9A2%202%200%200115%2010.76V6h1a2%202%200%20000-4H8a2%202%200%20000%204h1v4.76a2%202%200%2001-1.11%201.79l-1.78.9A2%202%200%20005%2015.24z%27%20fill%3D%27currentColor%27%20stroke%3D%27none%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2017v5%27%20stroke-width%3D%272%27%2F%3E%3Cpath%20d%3D%27M5%2017h14v-1.76a2%202%200%2000-1.11-1.79l-1.78-.9A2%202%200%200115%2010.76V6h1a2%202%200%20000-4H8a2%202%200%20000%204h1v4.76a2%202%200%2001-1.11%201.79l-1.78.9A2%202%200%20005%2015.24z%27%20fill%3D%27currentColor%27%20stroke%3D%27none%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--users{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%279%27%20cy%3D%278%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M3%2019a6%206%200%200112%200%27%2F%3E%3Cpath%20d%3D%27M16.5%205.6a3.2%203.2%200%20010%205.6M17.5%2013.2A5.6%205.6%200%200121%2019%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%279%27%20cy%3D%278%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M3%2019a6%206%200%200112%200%27%2F%3E%3Cpath%20d%3D%27M16.5%205.6a3.2%203.2%200%20010%205.6M17.5%2013.2A5.6%205.6%200%200121%2019%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--share{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2718%27%20cy%3D%275%27%20r%3D%272.6%27%2F%3E%3Ccircle%20cx%3D%276%27%20cy%3D%2712%27%20r%3D%272.6%27%2F%3E%3Ccircle%20cx%3D%2718%27%20cy%3D%2719%27%20r%3D%272.6%27%2F%3E%3Cpath%20d%3D%27M8.3%2010.8l7.4-4.3M8.3%2013.2l7.4%204.3%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2718%27%20cy%3D%275%27%20r%3D%272.6%27%2F%3E%3Ccircle%20cx%3D%276%27%20cy%3D%2712%27%20r%3D%272.6%27%2F%3E%3Ccircle%20cx%3D%2718%27%20cy%3D%2719%27%20r%3D%272.6%27%2F%3E%3Cpath%20d%3D%27M8.3%2010.8l7.4-4.3M8.3%2013.2l7.4%204.3%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--send{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2019V5M5%2012l7-7%207%207%27%20stroke-width%3D%272.4%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2019V5M5%2012l7-7%207%207%27%20stroke-width%3D%272.4%27%2F%3E%3C%2Fsvg%3E")}
.ella-ico--message{-webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%205h16a1%201%200%20011%201v10a1%201%200%2001-1%201H8l-4%204V6a1%201%200%20011-1z%27%2F%3E%3C%2Fsvg%3E");mask-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27currentColor%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%205h16a1%201%200%20011%201v10a1%201%200%2001-1%201H8l-4%204V6a1%201%200%20011-1z%27%2F%3E%3C%2Fsvg%3E")}

/* ── Architecture field guide (architecture_view.py) ──────────────────────
   Rendered from clients/server/architecture.py, the same spec the React shell
   fetches. Every colour is a theme token so the guide flips with the app;
   this view is the one place an internal scroll is correct — it is shell
   chrome, not a card body, so CORE RULE 1 does not apply to it.
   Accent TEXT uses --accent-ink, never --darkgreen: the latter is ~1.3:1
   on a dark surface (see the green-ramp note at copilot.css:119). */
.architecture-page{flex:1;min-height:0;overflow-y:auto;background:var(--bg)}
.arch-inner{max-width:1080px;margin:0 auto;padding:28px 32px 72px}
.arch-back-btn{background:none;border:1px solid var(--border);color:var(--ink-soft);border-radius:8px;padding:5px 12px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit;margin-bottom:20px}
.arch-back-btn:hover{border-color:var(--border-strong);color:var(--ink)}
.architecture-nav-btn{width:auto;gap:6px;padding:0 10px;display:inline-flex;align-items:center;font-family:inherit;font-size:12px;font-weight:600}
.arch-nav-label{white-space:nowrap}
@media (max-width:900px){.arch-nav-label{display:none}}

.arch-header{border-bottom:1px solid var(--border);padding-bottom:20px;margin-bottom:8px}
.arch-eyebrow{font-size:11.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--accent-ink);margin:0 0 6px}
.arch-h1{font-size:28px;font-weight:800;color:var(--ink);margin:0 0 6px;letter-spacing:.01em}
.arch-sub{font-size:14.5px;color:var(--ink-soft);margin:0 0 10px;max-width:70ch}
.arch-scope{font-size:12.5px;color:var(--muted);margin:0 0 12px;max-width:80ch}
.arch-meta{display:flex;flex-wrap:wrap;gap:8px}
.arch-meta-item{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--muted);background:var(--card-bg);border:1px solid var(--border);border-radius:20px;padding:3px 9px}

.arch-section{padding:24px 0;border-bottom:1px solid var(--border)}
.arch-section:last-child{border-bottom:0}
.arch-h2{font-size:18px;font-weight:800;color:var(--ink);margin:0 0 4px}
.arch-h3{font-size:13.5px;font-weight:700;color:var(--ink);margin:0 0 4px}
.arch-blurb{font-size:12.5px;color:var(--muted);margin:0 0 16px;max-width:75ch}
.arch-detail{font-size:12.5px;color:var(--ink-soft);margin:0 0 6px;line-height:1.55}
.arch-detail--muted{color:var(--muted)}
.arch-list{font-size:12.5px;color:var(--ink-soft);margin:6px 0 0;padding-left:18px;line-height:1.6}
.arch-steps{font-size:12.5px;color:var(--ink-soft);margin:6px 0 8px;padding-left:18px;line-height:1.6}
.arch-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--muted);background:var(--card-bg-soft);border:1px solid var(--border);border-radius:5px;padding:1px 6px;display:inline-block;margin:2px 0 6px;word-break:break-all}

.arch-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
.arch-card{background:var(--card-bg);border:1px solid var(--border);border-radius:11px;padding:14px 15px}
.arch-lane{margin-bottom:22px}
.arch-comp-name{font-size:13.5px;font-weight:700;color:var(--ink)}
.arch-comp-caption{font-size:11.5px;color:var(--muted);margin-bottom:6px}

.arch-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:14px}
.arch-fact{background:var(--card-bg);border:1px solid var(--border);border-radius:11px;padding:12px 14px}
.arch-fact-value{font-size:17px;font-weight:800;color:var(--ink)}
.arch-fact-label{font-size:11px;color:var(--muted);margin-top:2px}
.arch-method{font-size:12px;color:var(--muted);margin:0;font-style:italic}

.arch-chip{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.03em;border-radius:20px;padding:2px 9px;margin-bottom:7px;border:1px solid var(--border)}
.arch-chip--live{color:var(--accent-ink);background:var(--accent-bg);border-color:var(--accent-border)}
.arch-chip--repo{color:var(--ink-soft);background:var(--card-bg-soft)}
.arch-chip--unverified{color:var(--warn-ink);background:var(--warn-bg);border-color:var(--warn-border)}

.arch-ba-row{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:8px 0 10px}
.arch-ba{background:var(--card-bg-soft);border:1px solid var(--border);border-radius:9px;padding:9px 11px}
.arch-ba--after{border-color:var(--accent-border)}
.arch-ba-label{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.arch-ba p{font-size:12px;color:var(--ink-soft);margin:3px 0 0;line-height:1.5}
@media (max-width:640px){.arch-ba-row{grid-template-columns:1fr}}

.arch-details{background:var(--card-bg);border:1px solid var(--border);border-radius:11px;margin-bottom:8px}
.arch-summary{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:11px 14px;cursor:pointer;list-style:none}
.arch-summary::-webkit-details-marker{display:none}
.arch-summary:hover{background:var(--card-bg-soft)}
.arch-summary-title{font-size:13px;font-weight:700;color:var(--ink)}
.arch-summary-basis{font-size:11px;color:var(--muted);margin-left:auto}
.arch-details-body{padding:0 14px 14px;border-top:1px solid var(--border);padding-top:11px}
.arch-pri{font-size:10px;font-weight:800;letter-spacing:.04em;border-radius:5px;padding:2px 6px;border:1px solid var(--border);color:var(--ink-soft)}
.arch-pri--p1{color:var(--warn-ink);background:var(--warn-bg);border-color:var(--warn-border)}
.arch-pri--p2{color:var(--orange);border-color:var(--orange)}
.arch-pri--p3{color:var(--muted)}

.arch-sources{display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin-top:9px;padding-top:9px;border-top:1px dashed var(--border)}
.arch-source-label{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.arch-source{font-size:11px;color:var(--accent-ink);text-decoration:none;border-bottom:1px solid transparent}
.arch-source:hover{border-bottom-color:currentColor}
