/* able-runtime.css — bundled blueprint chrome CSS for SSR first-paint. */

/* able-admin-console */

.aac{container-type:inline-size;display:block;background:var(--surface-base);
     color:var(--text-primary);font-family:var(--font-sans);
     --acv-series:var(--accent)}

/* ── the SERIES colour: one token, four marks ──────────────────────────────
   The sparkline stroke, the share bar, the per-day bars and the legend swatch
   are all "the series being measured", so they are all drawn in one colour and
   they may never disagree with each other. That is why this is a variable and
   not four copies of var(--accent).

   In LIGHT it IS the tenant accent, untouched. In DARK the raw accent cannot be
   trusted, and re-binding it per tenant is NOT the fix: sunstate@fleet already
   re-binds its accent for dark (deep navy to a lighter navy) and its marks still
   measured 2.42:1 on the card and 2.28:1 on the share track -- the tenant lifts
   its accent enough to read as TEXT on a pane, not enough for a 1.6px stroke on
   a near-black card. So dark mixes the accent toward --text-primary, which every
   theme re-binds by contract. That is hue-preserving (a navy tenant stays navy,
   a copper tenant stays copper) and its floor is a function of --text-primary
   rather than of the tenant's choice: measured after, fleet 6.67:1 and
   max@able 6.76:1 on the card, 6.21:1 and 6.31:1 against the share track, with
   the worst plausible near-black accent still landing 3.89:1.

   color-mix is already the established idiom for a dark-safe brand colour in
   this bundle (see able-notification-bell.js). If it ever fails to parse the
   declaration is simply dropped and the mark inherits var(--accent) from .aac
   above -- today's behaviour, never a blank. */
:root[data-theme="dark"] .aac{
     --acv-series:color-mix(in srgb, var(--accent) 55%, var(--text-primary))}

/* ── console title bar ── */
.aac-top{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);
     padding:var(--space-4) var(--space-5);background:var(--surface-card);
     border-bottom:1px solid var(--border-default)}
.aac-brand{display:flex;flex-direction:column;min-width:0}
.aac-brand strong{font-size:var(--font-base);font-weight:680;letter-spacing:-.01em}
.aac-brand span{font-size:var(--font-xs);color:var(--text-muted);
     overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ── body: rail + detail ── */
/* The COLUMN is painted by the body, so the card ground and the divider run the
   full height of whatever the pane is showing while the rail itself stays only
   as tall as the sections it lists. Stretching the rail to match the pane is
   what buried it: a list of 79 components made that column 6547px tall, and the
   group pinned to its foot sat 6000px below the fold -- the section you were
   standing in could not be seen, and no other section could be reached without
   scrolling to the end of the page. */
.aac-body{display:grid;grid-template-columns:248px minmax(0,1fr);min-height:660px;
     background:linear-gradient(to right, var(--surface-card) 0 247px,
     var(--border-default) 247px 248px, transparent 248px)}
.aac-rail{align-self:start;padding:var(--space-4) var(--space-3)}
/* Sticky is kept for the shells that DO clamp their page area, where it holds
   the rail in view. Under a shell that lets the page grow instead, the platform
   page host is an auto-height scroll box that never scrolls, so this simply has
   no range to work in and the rail scrolls with the page like any other column. */
.aac-rail-in{position:sticky;top:0;display:flex;flex-direction:column;gap:var(--space-1);
     max-height:100dvh;overflow-y:auto;scrollbar-width:thin}
/* A section caption is TEXT someone reads, so it clears AA like everything else
   here. On --text-subtle it measured 2.54:1 -- the very number that put that
   token off-limits for reading in the first place. --text-subtle stays on the
   separators, chevrons and icons below, which carry no reading load. */
/* ...and one step further, for the same reason the tab counts took it: this
   caption sits on the PANE, not on a card, where --text-muted measures 4.48:1
   on a light theme — a hair under AA, exactly as it did there. */
.aac-rail-cap{margin:var(--space-3) var(--space-3) var(--space-1);font-size:var(--font-xs);
     font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-secondary)}
.aac-rail-item{display:flex;align-items:center;gap:var(--space-3);width:100%;min-height:44px;
     padding:0 var(--space-3);border:0;border-radius:var(--radius-md);cursor:pointer;
     background:transparent;color:var(--text-secondary);font:inherit;
     font-size:var(--font-sm);font-weight:600;text-align:left;text-decoration:none;
     transition:background 160ms ease,color 160ms ease}
.aac-rail-item svg{width:17px;height:17px;flex:none;color:var(--text-subtle)}
.aac-rail-item span.lbl{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.aac-rail-item:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
@media (hover:hover) and (pointer:fine){
  .aac-rail-item:hover{background:var(--surface-hover);color:var(--text-primary)}
}
/* The selected section. It reads as selected from the soft fill, the weight and
   the accent bar — NOT from accent-coloured text, which is the one part that
   cannot be trusted here: --accent and --accent-soft are BOTH tenant-set, and a
   tenant that picks a mid indigo for the accent and an indigo-900 for the soft
   fill lands its own accent on its own fill at 2.56:1 (measured, victor@victor,
   dark). A blueprint may not depend on a tenant's two tokens contrasting with
   each other. Text is --text-primary, which every theme re-binds per mode, so
   the label is legible against the fill whatever accent the tenant chose. */
.aac-rail-item[data-active]{background:var(--accent-soft);color:var(--text-primary);font-weight:680;
     box-shadow:inset 2px 0 0 0 var(--accent)}
.aac-rail-item[data-active] svg{color:var(--text-primary)}
/* Same story as the caption: a rail count sits on the pane, where muted is
   4.48:1 on a light theme. */
.aac-rail-n{flex:none;font-size:var(--font-xs);font-weight:700;color:var(--text-secondary);
     font-variant-numeric:tabular-nums}
.aac-rail-item[data-active] .aac-rail-n{color:var(--text-primary)}
.aac-rail-dot{flex:none;width:7px;height:7px;border-radius:var(--radius-full);
     background:var(--danger);display:block}
/* A deliberate gap rather than every pixel of leftover column: what demotes
   this group is the rule above it, the quieter type and being shut, not how far
   down the page it floats -- and floating is what buried it. */
.aac-rail-plat{margin-top:var(--space-6);padding-top:var(--space-3);
     border-top:1px solid var(--border-subtle)}
.aac-rail-item--plat{color:var(--text-secondary);font-weight:600;font-size:var(--font-xs);
     letter-spacing:.04em;text-transform:uppercase}
.aac-rail-item--plat svg.chev{width:14px;height:14px;margin-left:auto;
     transition:transform 160ms ease}
.aac-rail-item--plat svg.chev[data-open]{transform:rotate(90deg)}
/* The group's own items are demoted a step below the three a tenant admin owns
   -- same shape, quieter type -- so the rail still reads as three things and a
   drawer, not as eight peers. */
.aac-rail-sub{display:flex;flex-direction:column;gap:2px;margin-top:2px}
.aac-rail-sub .aac-rail-item{font-size:var(--font-sm);font-weight:560;min-height:38px}
.aac-rail-sub .aac-rail-item svg{width:15px;height:15px}
/* Prose, so it takes the readable step up -- and doubly so here, because the
   rail's ground is painted by the body's gradient rather than by a background
   colour of its own, which makes "what is this sitting on" a question the next
   person should not have to answer. */
.aac-rail-note{margin:var(--space-2) var(--space-3) 0;font-size:var(--font-sm);line-height:1.5;
     color:var(--text-secondary)}

/* ── detail pane ── */
.aac-pane{min-width:0;padding:var(--space-6) var(--space-6) var(--space-10)}
/* An app's own section. The mounted page brings its own styles scoped to
   itself, so this is a plain container: give it the width and stay out of the
   way.

   overflow-x:auto is the BACKSTOP, not the mechanism. These pages were written
   for the full width of the app and lose the rail's width in here, so a wide
   table has less room than its author gave it. A well-built page brings its own
   scroller and needs nothing from us — fleet's audit log does: a 995px table
   inside its own fv-scrollbody at overflow-x:auto, fully reachable. (Worth
   recording how that was nearly mis-called: walking up from the table, the first
   element with scrollWidth > clientWidth is <able-table> itself at
   overflow:visible, which reads as "clipped" — the scroller is its PARENT. Read
   the whole ancestor chain, not the first hit.) The rule stays for the page that
   does NOT bring one: better a scrollbar here than content nobody can reach.
   min-width:0 keeps any such overflow in this box instead of pushing the whole
   document sideways. */
.aac-appunit{min-width:0;overflow-x:auto}
/* The original failure text behind "Show technical detail". Wraps (the sentence
   above it is the one-liner) and sits at caption scale — it is evidence to hand
   to somebody, not something anyone reads by choice. */
/* A link OUT to a builder screen. Reads as a door, not a button: the arrow says
   you are leaving, and the note says what is on the other side. 44px min so it
   is a real target on a phone. */
.aac-out{display:flex;align-items:center;gap:var(--space-3);min-height:44px;
  margin-top:var(--space-3);padding:var(--space-3) var(--space-4);
  border:1px dashed var(--border-default);border-radius:var(--radius-lg);
  background:var(--surface-card);color:var(--text-primary);
  text-decoration:none;transition:border-color 160ms ease,background 160ms ease}
@media (hover:hover) and (pointer:fine){
  .aac-out:hover{border-color:var(--accent);background:var(--surface-hover)}
}
.aac-out:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.aac-out-tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}
.aac-out-lb{font-size:var(--font-sm);font-weight:600}
.aac-out-nt{font-size:var(--font-xs);color:var(--text-secondary)}
.aac-out-ic{width:16px;height:16px;flex:none;color:var(--text-secondary)}
.aac-rail-item--out .aac-out-ic{margin-left:auto}
/* Scoped to the rows that can actually carry a third child — putting wrap on
   every .aac-row would change the layout of rows that have nothing to wrap. */
.aac-row--open{flex-wrap:wrap}
.aac-run-more{display:block;margin-top:4px;font-size:var(--font-xs);
  color:var(--text-secondary);text-decoration:underline}
.aac-run-raw{flex:1 0 100%;margin:var(--space-2) 0 0;padding:var(--space-3);
  background:var(--surface-subtle);border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);color:var(--text-secondary);
  font-family:var(--font-mono);font-size:var(--font-xs);line-height:1.5;
  white-space:pre-wrap;word-break:break-word;overflow-x:auto}
.aac-head{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--space-4);
     justify-content:space-between;margin-bottom:var(--space-5)}
.aac-head-txt{min-width:0}
.aac-h1{margin:0;font-size:var(--font-xl);font-weight:700;letter-spacing:-.015em}
.aac-lede{margin:var(--space-2) 0 0;font-size:var(--font-sm);line-height:1.55;
     color:var(--text-secondary);max-width:64ch}

/* ── buttons ── */
.aac-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;flex:none;
     min-height:44px;padding:0 var(--space-4);cursor:pointer;
     border:1px solid var(--border-default);border-radius:var(--radius-md);
     background:var(--surface-card);color:var(--text-primary);font:inherit;
     font-size:var(--font-sm);font-weight:600;
     transition:background 160ms ease,border-color 160ms ease,color 160ms ease}
.aac-btn svg{width:15px;height:15px}
.aac-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (hover:hover) and (pointer:fine){
  .aac-btn:hover{background:var(--surface-hover);border-color:var(--border-strong)}
}
.aac-btn--primary{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
@media (hover:hover) and (pointer:fine){
  .aac-btn--primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
}
.aac-btn--quiet{color:var(--text-secondary)}
.aac-btn--danger{color:var(--danger)}
.aac-btn--sm{min-height:34px;padding:0 var(--space-3);font-size:var(--font-xs)}
.aac-btn[disabled]{opacity:.55;cursor:default}

/* ── tabs ── */
.aac-tabs{display:flex;gap:var(--space-1);border-bottom:1px solid var(--border-default);
     margin-bottom:var(--space-4)}
.aac-tab{position:relative;display:inline-flex;align-items:center;gap:7px;min-height:44px;
     padding:0 var(--space-3);border:0;background:transparent;cursor:pointer;
     font:inherit;font-size:var(--font-sm);font-weight:600;color:var(--text-secondary);
     border-bottom:2px solid transparent;margin-bottom:-1px}
.aac-tab:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
@media (hover:hover) and (pointer:fine){ .aac-tab:hover{color:var(--text-primary)} }
.aac-tab[data-active]{color:var(--text-primary);border-bottom-color:var(--accent)}
.aac-tab-n{font-size:var(--font-xs);font-weight:700;color:var(--text-muted);
     font-variant-numeric:tabular-nums}
/* A count inside a TAB sits on the pane background, not on a card, and there
   --text-muted measures 4.48:1 -- a hair under AA, where the same token on a
   card measures 4.83:1 and passes. The contrast rule is that anything a person
   reads clears AA, so the tab counts take the next step up. Counts inside a
   chip stay muted: a chip IS a card surface, and they measure a pass. */
.aac-tab .aac-tab-n{color:var(--text-secondary)}

/* ── toolbar ── */
.aac-tools{display:flex;flex-wrap:wrap;gap:var(--space-3);margin-bottom:var(--space-4)}
.aac-search{display:flex;align-items:center;gap:var(--space-2);flex:1 1 240px;min-width:0;
     min-height:44px;padding:0 var(--space-3);border:1px solid var(--border-default);
     border-radius:var(--radius-md);background:var(--surface-card)}
.aac-search svg{width:16px;height:16px;color:var(--text-subtle);flex:none}
/* align-self:stretch so the field FILLS the 44px box. The box already looked
   like a 44px control; the input inside it was 26px tall, so the top and bottom
   strips were dead to a finger and the real target was 26px. Filling makes the
   thing you can tap the same as the thing you can see. */
.aac-search input{flex:1 1 auto;min-width:0;align-self:stretch;border:0;background:transparent;
     outline:none;font:inherit;font-size:max(16px,var(--font-sm));color:var(--text-primary)}
.aac-search input::placeholder{color:var(--text-muted)}
.aac-chip{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 var(--space-3);
     border:1px solid var(--border-default);border-radius:var(--radius-md);cursor:pointer;
     background:var(--surface-card);color:var(--text-secondary);font:inherit;
     font-size:var(--font-sm);font-weight:600}
.aac-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Selected. Exactly the story the rail item tells above, and the same fix: the
   soft fill and the accent border say "on", the LABEL does not. Accent text on
   accent-soft is two tenant tokens asked to contrast with each other, which a
   blueprint may not depend on -- measured 2.86:1 on max@able and 1.95:1 on a
   tenant whose soft fill sits closer to its accent, both under AA for a 14px
   label. --text-primary re-binds per mode by contract, so the label is legible
   on the fill whatever accent the tenant chose (12.39:1 measured after). */
.aac-chip[data-on]{background:var(--accent-soft);border-color:var(--accent);color:var(--text-primary)}
.aac-chip svg{width:13px;height:13px}

/* ── list + rows ── */
.aac-list{display:flex;flex-direction:column;gap:var(--space-2)}
.aac-row{display:flex;align-items:stretch;min-width:0;
     border:1px solid var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-card);
     transition:border-color 160ms ease,box-shadow 160ms ease}
@media (hover:hover) and (pointer:fine){
  .aac-row:hover{border-color:var(--border-strong);box-shadow:var(--shadow-sm)}
}
.aac-row-main{display:flex;flex-direction:column;gap:6px;flex:1 1 auto;min-width:0;
     min-height:44px;padding:var(--space-3) var(--space-4);cursor:pointer;text-align:left;
     border:0;border-radius:var(--radius-lg);background:transparent;font:inherit;color:inherit}
.aac-row-main:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* A row that is a fact rather than a door: no pointer, out of the tab order. */
.aac-row-main[disabled]{cursor:default}
/* Line 1 — the identity string owns this band. Nothing else competes for slack. */
.aac-l1{display:flex;align-items:center;gap:var(--space-3);min-width:0}
.aac-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
     font-size:var(--font-base);font-weight:640;color:var(--text-primary)}
/* Line 2 — every element intrinsic-width, wraps rather than truncates. */
.aac-l2{display:flex;flex-wrap:wrap;align-items:center;gap:4px var(--space-2);min-width:0;
     font-size:var(--font-sm);color:var(--text-muted)}
.aac-f{display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:100%;
     overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* LITERAL middot — never a unicode escape (see the note above). */
.aac-f + .aac-f::before{content:"·";color:var(--text-subtle);flex:none}
.aac-f--tz{color:var(--text-muted)}
.aac-f--bad{color:var(--danger);font-weight:600}
.aac-f--own{color:var(--info);font-weight:600}
/* Right column — reserves NOTHING when a job is off (no em-dash placeholder),
   but when present it is a FIXED width so the outcomes form a scannable column.
   Content-sized, the divider lands at a different x on every row and the eye
   has to re-find it each time. Sized to the longest real string in the corpus,
   "16 hr ago · 12m 41s". */
.aac-row-side{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;
     gap:3px;flex:none;width:158px;padding:var(--space-3) var(--space-4);
     border-left:1px solid var(--border-subtle);text-align:right}
/* An OFF job has no last run. Keep the slot (so the status column above it does
   not jump 158px right on those rows) but drop its divider -- reserving the
   space is grid stability; printing an em-dash would be the placeholder we ban. */
.aac-row-side:empty{border-left-color:transparent}
/* Roles need more room than an outcome: two chips plus an overflow count, sized
   to the corpus worst case (five roles on one person). */
.aac-row-side--roles{width:208px}
.aac-row-side--roles .aac-side-1{flex-wrap:wrap;gap:5px}
.aac-side-1{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:5px;
     font-size:var(--font-sm);font-weight:640}
.aac-side-1[data-tone="good"]{color:var(--success)}
.aac-side-1[data-tone="bad"]{color:var(--danger)}
.aac-side-1[data-tone="warn"]{color:var(--warning)}
.aac-side-2{font-size:var(--font-xs);color:var(--text-muted);
     font-variant-numeric:tabular-nums;white-space:nowrap}
/* The failure sentence is a THIRD line INSIDE the row, never a floating band
   between cards — detached from its card it reads as page text, not as this
   job's problem. */
.aac-err-txt{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
     margin-top:2px;font-size:var(--font-sm);color:var(--danger);max-width:100%}

/* CONTRAST RULE (measured, both modes): --text-subtle is 2.54:1 on light and
   3.77:1 on dark -- it FAILS WCAG AA for text. It is therefore used ONLY for
   separators and icons, which carry no reading load.
   AND THE FLOOR DEPENDS ON WHAT IT IS SITTING ON. --text-muted measures 4.83:1
   on a card, but 4.48:1 on the pane and 4.41:1 on a subtle fill -- both under
   AA. So it is kept for readable text ON A CARD, and anything readable on the
   pane or on a subtle fill takes the next step up to --text-secondary (9.5:1
   and better everywhere). Muted still carries the un-read furniture on those
   surfaces: timestamps, counts, durations. */

/* ── status ── */
.aac-st{display:inline-flex;align-items:center;gap:6px;flex:none;
     font-size:var(--font-sm);font-weight:600;white-space:nowrap}
.aac-st i{width:8px;height:8px;border-radius:var(--radius-full);background:currentColor;
     display:block;flex:none}
.aac-st[data-tone="good"]{color:var(--success)}
.aac-st[data-tone="bad"]{color:var(--danger)}
.aac-st[data-tone="warn"]{color:var(--warning)}
/* OFF is grey, never red. About half of a real app's scheduled work is
   deliberately off; a red console that screams permanently is one people stop
   reading. */
.aac-st[data-tone="off"]{color:var(--text-muted)}

/* ── small pills ── */
.aac-pill{display:inline-flex;align-items:center;height:22px;padding:0 9px;flex:none;
     border-radius:var(--radius-full);font-size:var(--font-xs);font-weight:600;
     background:var(--surface-subtle);color:var(--text-secondary);white-space:nowrap}
.aac-pill--role{background:var(--surface-subtle);color:var(--text-secondary)}
/* Same rule as the selected rail item: the tint may come from --accent-soft,
   the TEXT may not come from --accent. Both are tenant-set and nothing makes
   them contrast — on one live theme this pill measured 3.63:1 light / 2.56:1
   dark. The fill still separates an admin from an ordinary role. */
.aac-pill--admin{background:var(--accent-soft);color:var(--text-primary);font-weight:660}
.aac-pill--more{background:transparent;color:var(--text-muted);padding:0 4px}
/* Template variables read as words, not mustache syntax. */
.aac-var{display:inline-flex;align-items:center;height:19px;padding:0 7px;
     border-radius:var(--radius-sm);background:var(--info-soft);color:var(--info);
     font-size:.92em;font-weight:600;white-space:nowrap}

/* ── detail ── */
.aac-back{display:inline-flex;align-items:center;gap:7px;min-height:44px;padding:0 var(--space-2) 0 0;
     margin-bottom:var(--space-2);border:0;background:transparent;cursor:pointer;font:inherit;
     font-size:var(--font-sm);font-weight:600;color:var(--text-secondary)}
.aac-back svg{width:16px;height:16px}
.aac-back:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.aac-card{border:1px solid var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-card);padding:var(--space-5);margin-bottom:var(--space-4)}
.aac-card-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
     margin-bottom:var(--space-2)}
.aac-card-title{margin:0;font-size:var(--font-lg);font-weight:680;min-width:0}
.aac-card-note{margin:0;font-size:var(--font-sm);line-height:1.6;color:var(--text-muted);max-width:68ch}
.aac-facts{display:grid;gap:var(--space-4);margin:var(--space-5) 0 0;grid-template-columns:1fr}
@container (min-width: 620px){ .aac-facts{grid-template-columns:repeat(2,minmax(0,1fr))} }
.aac-fact{min-width:0}
.aac-fact dt{font-size:var(--font-xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;
     color:var(--text-muted)}
.aac-fact dd{margin:4px 0 0;font-size:var(--font-sm);line-height:1.5;min-width:0;
     overflow-wrap:anywhere;color:var(--text-primary)}
.aac-fact dd code{font-family:var(--font-mono);font-size:.92em;padding:2px 6px;
     border-radius:var(--radius-sm);background:var(--surface-subtle);color:var(--text-secondary)}
.aac-kv{display:flex;flex-direction:column;gap:5px;margin:0}
.aac-kv div{display:flex;gap:var(--space-2);font-size:var(--font-sm);min-width:0}
.aac-kv dt{flex:none;width:110px;color:var(--text-muted);font-size:var(--font-sm);
     font-weight:500;letter-spacing:0;text-transform:none}
.aac-kv dd{margin:0;min-width:0;overflow-wrap:anywhere;font-family:var(--font-mono);font-size:.9em}
.aac-actions{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-5);
     padding-top:var(--space-5);border-top:1px solid var(--border-subtle)}
.aac-sub{margin:var(--space-6) 0 var(--space-3);font-size:var(--font-sm);font-weight:680;
     color:var(--text-primary)}
.aac-banner{display:flex;gap:var(--space-3);align-items:flex-start;margin-top:var(--space-4);
     padding:var(--space-3) var(--space-4);border-radius:var(--radius-md);
     font-size:var(--font-sm);line-height:1.55}
.aac-banner[data-tone="bad"]{background:var(--danger-soft);color:var(--danger)}
.aac-banner[data-tone="warn"]{background:var(--warning-soft);color:var(--warning)}
.aac-banner svg{width:18px;height:18px;flex:none;margin-top:1px}
.aac-detail-txt{margin:var(--space-3) 0 0;font-size:var(--font-sm);line-height:1.6;
     color:var(--text-secondary);white-space:pre-wrap;overflow-wrap:anywhere}

/* ── grouped delivery log ── */
.aac-grp{border:1px solid var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-card);overflow:hidden}
.aac-grp + .aac-grp{margin-top:var(--space-2)}
.aac-grp-head{display:flex;align-items:center;gap:var(--space-3);width:100%;min-height:44px;
     padding:var(--space-3) var(--space-4);border:0;background:transparent;cursor:pointer;
     font:inherit;color:inherit;text-align:left}
.aac-grp-head:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.aac-grp-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
     font-size:var(--font-base);font-weight:640}
.aac-grp-when{flex:none;font-size:var(--font-xs);color:var(--text-muted);
     font-variant-numeric:tabular-nums}
.aac-grp-chev{flex:none;width:16px;height:16px;color:var(--text-subtle)}
.aac-legs{border-top:1px solid var(--border-subtle);background:var(--surface-subtle);
     padding:var(--space-2) var(--space-4) var(--space-3)}
.aac-leg{display:flex;align-items:center;gap:var(--space-3);min-height:32px;
     font-size:var(--font-sm);color:var(--text-secondary);min-width:0}
.aac-leg-who{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.aac-leg-st{flex:none;font-size:var(--font-xs);font-weight:600}
.aac-leg-st[data-tone="good"]{color:var(--success)}
.aac-leg-st[data-tone="bad"]{color:var(--danger)}
.aac-leg-st[data-tone="warn"]{color:var(--warning)}
.aac-leg-st[data-tone="off"]{color:var(--text-muted)}

/* ── what the AI remembers ── */
/* The bodies are the agent's own words: user data, shown verbatim. We rewrite
   chrome, never content. Two lines on the card, all of it when you open one. */
.aac-mem{border:1px solid var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-card);padding:var(--space-4)}
.aac-mem + .aac-mem{margin-top:var(--space-2)}
.aac-mem-top{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);margin-bottom:7px}
.aac-mem-body{margin:0;font-size:var(--font-sm);line-height:1.6;color:var(--text-secondary);
     white-space:pre-wrap;overflow-wrap:anywhere}
.aac-mem-body[data-clamp]{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;
     overflow:hidden;white-space:normal}
.aac-mem-when{margin-left:auto;flex:none;font-size:var(--font-xs);color:var(--text-muted);
     font-variant-numeric:tabular-nums}
.aac-mem-acts{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-3)}

/* ── forms ── */
/* An inline panel, not an overlay: inviting someone is a two-field answer to a
   question you just asked, and a dialog would put chrome between you and it. */
.aac-form{border:1px solid var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-card);padding:var(--space-5);margin-bottom:var(--space-4)}
.aac-form-title{margin:0 0 var(--space-4);font-size:var(--font-base);font-weight:680}
.aac-fields{display:grid;gap:var(--space-4);grid-template-columns:1fr}
@container (min-width: 620px){ .aac-fields{grid-template-columns:repeat(2,minmax(0,1fr))} }
.aac-field{display:flex;flex-direction:column;gap:6px;min-width:0}
.aac-field > label{font-size:var(--font-xs);font-weight:700;letter-spacing:.06em;
     text-transform:uppercase;color:var(--text-muted)}
.aac-input,.aac-select{width:100%;min-width:0;min-height:44px;padding:0 var(--space-3);
     border:1px solid var(--border-default);border-radius:var(--radius-md);
     background:var(--surface-base);color:var(--text-primary);font:inherit;
     font-size:max(16px,var(--font-sm))}
.aac-select{padding-right:var(--space-2)}
.aac-input:focus-visible,.aac-select:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.aac-input::placeholder{color:var(--text-muted)}
.aac-hint{margin:6px 0 0;font-size:var(--font-xs);line-height:1.5;color:var(--text-muted)}
.aac-textarea{min-height:120px;padding:var(--space-3);line-height:1.55;resize:vertical}

/* ── access: one row per role, so removing one is a full-size target ── */
.aac-grants{display:flex;flex-direction:column;gap:var(--space-2);margin:var(--space-3) 0 0}
.aac-grant{display:flex;align-items:center;gap:var(--space-3);min-height:44px;
     padding:0 var(--space-2) 0 var(--space-3);border:1px solid var(--border-subtle);
     border-radius:var(--radius-md);background:var(--surface-subtle)}
.aac-grant-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
     font-size:var(--font-sm);font-weight:600;color:var(--text-primary)}
.aac-grant-note{flex:none;font-size:var(--font-xs);color:var(--text-secondary)}
.aac-addrole{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-3);align-items:center}
.aac-addrole .aac-select{flex:1 1 220px;width:auto}

/* ── a value shown exactly once ── */
.aac-once{margin-top:var(--space-4);padding:var(--space-4);border-radius:var(--radius-md);
     background:var(--success-soft);color:var(--success)}
.aac-once p{margin:0 0 var(--space-2);font-size:var(--font-sm);line-height:1.55;font-weight:600}
.aac-once-val{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2)}
.aac-once code{flex:1 1 220px;min-width:0;overflow-wrap:anywhere;padding:9px var(--space-3);
     border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-primary);
     font-family:var(--font-mono);font-size:var(--font-sm)}

/* ── platform panels ── */
/* Where a thing lives, in its own repo. Reads as an address, not as prose. */
.aac-path{font-family:var(--font-mono);font-size:.9em;color:var(--text-muted);
     overflow-wrap:anywhere;word-break:break-all;min-width:0}
.aac-note{margin:var(--space-4) 0 0;font-size:var(--font-sm);line-height:1.6;color:var(--text-secondary)}
.aac-sum{display:flex;flex-wrap:wrap;gap:var(--space-2) var(--space-5);margin:0 0 var(--space-4);
     padding:var(--space-3) var(--space-4);border:1px solid var(--border-subtle);
     border-radius:var(--radius-lg);background:var(--surface-subtle)}
.aac-sum div{min-width:0}
.aac-sum dt{font-size:var(--font-xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;
     color:var(--text-secondary)}
.aac-sum dd{margin:2px 0 0;font-size:var(--font-base);font-weight:680;color:var(--text-primary);
     font-variant-numeric:tabular-nums}
.aac-sum dd[data-tone="bad"]{color:var(--danger)}
.aac-sum dd[data-tone="good"]{color:var(--success)}

/* ── empty / error ── */
.aac-empty{display:flex;flex-direction:column;align-items:center;text-align:center;
     gap:var(--space-4);padding:var(--space-12) var(--space-4);
     border:1px dashed var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-subtle)}
.aac-empty svg{width:38px;height:38px;color:var(--text-subtle)}
.aac-empty h3{margin:0;font-size:var(--font-lg);font-weight:650}
.aac-empty p{margin:0;max-width:48ch;font-size:var(--font-sm);line-height:1.65;color:var(--text-secondary)}

/* ── skeleton ── */
.aac-skel{height:12px;border-radius:var(--radius-sm);background:var(--surface-hover);
     animation:aac-pulse 1.4s ease-in-out infinite;display:block}
@keyframes aac-pulse{0%,100%{opacity:1}50%{opacity:.45}}

/* ═══ COLLAPSE — container queries, so a narrow SLOT collapses like a narrow
   screen, and a 375px phone is genuinely this same CSS. ═══ */
@container (max-width: 860px){
  /* One column: the painted rail column would run straight down the middle.
     minmax(0,...) rather than a bare 1fr, because a bare fr floors at the
     MIN-CONTENT of what is inside it -- and one unbreakable 60-character file
     path stretched this track to 1384px inside a 375px phone. The page area
     clips instead of scrolling, so a third of every row simply could not be
     reached. The desktop track has always carried the guard; the narrow one
     dropped it, and nothing had a long enough string to show it until now. */
  .aac-body{grid-template-columns:minmax(0,1fr);background:none}
  .aac-rail{align-self:stretch;background:var(--surface-card);
       border-bottom:1px solid var(--border-default);padding:var(--space-2) var(--space-3)}
  /* One strip across the top: nothing to pin, and the sections scroll sideways. */
  .aac-rail-in{position:static;flex-direction:row;align-items:center;overflow-x:auto;
       overflow-y:visible;max-height:none;gap:var(--space-2);scrollbar-width:none}
  .aac-rail-cap,.aac-rail-note{display:none}
  .aac-rail-item{width:auto;flex:none;white-space:nowrap}
  .aac-rail-plat{margin-top:0;padding-top:0;border-top:0;flex:none;display:flex;
       align-items:center;gap:var(--space-2)}
  .aac-rail-sub{flex-direction:row;margin-top:0;gap:var(--space-2)}
  /* Full-size targets on a touch screen: the quieter rail items and the small
     buttons are only allowed to be small where there is a mouse. */
  .aac-rail-sub .aac-rail-item{min-height:44px}
  .aac-btn--sm{min-height:44px;padding:0 var(--space-3)}
  .aac-pane{padding:var(--space-4) var(--space-4) var(--space-8)}
}
@container (max-width: 560px){
  /* Line 1 keeps the name alone; the status chip drops to the head of line 2
     and the right column moves to its tail. No truncation, no idle column. */
  .aac-row{flex-direction:column}
  .aac-row-main{padding:var(--space-3)}
  .aac-l1 .aac-st{display:none}
  .aac-l2 .aac-st{display:inline-flex;order:-1}
  .aac-row-side{flex-direction:row;align-items:center;gap:var(--space-2);
       justify-content:flex-start;border-left:0;border-top:1px solid var(--border-subtle);
       padding:var(--space-2) var(--space-3);text-align:left;width:100%}
  .aac-row-side:empty{border-top-color:transparent;padding:0}
  .aac-name{white-space:normal;overflow:visible;text-overflow:clip}
  /* Line 2 wraps here for the same reason the name does: there is room below a
     row on a phone and none beside it, so a fact that does not fit should take
     another line rather than be cut off at the edge. */
  .aac-l2 .aac-f{white-space:normal;overflow:visible;text-overflow:clip}
  .aac-head{gap:var(--space-3)}
  .aac-facts{grid-template-columns:1fr}
  .aac-tabs{overflow-x:auto;scrollbar-width:none}
  .aac-kv div{flex-direction:column;gap:2px}
  .aac-kv dt{width:auto}
  /* Search takes the whole row so the filters share the next one evenly.
     Sharing a row, the search box crowds the first chip up beside it and
     strands the rest on a second line with a gap where the box was. */
  .aac-search{flex:1 1 100%}
  .aac-chip{flex:1 1 auto;justify-content:center}
}
@container (min-width: 561px){ .aac-l2 .aac-st{display:none} }

@media (prefers-reduced-motion: reduce){
  .aac-skel{animation:none}
  .aac-row,.aac-btn,.aac-rail-item,.aac-tab{transition:none}
}

/* ── measurement (acv-*) — the analytics console's own vocabulary ──
   In THIS literal on purpose. The bundle extractor pulls one chrome block per
   blueprint into able-runtime.css; a second blueprint would mean a second block
   that can drift from this one. One shell, one stylesheet, two consoles.
   Canonical semantic tokens only — no --grey-N, which is mode-INDEPENDENT and
   goes invisible in whichever theme it was not authored in. */

/* the tile row. Grid, never flex. Container queries, so the rail's width is
   what decides the columns rather than the browser window's. */
.acv-tiles{display:grid;gap:var(--space-3);grid-template-columns:1fr;
     margin-bottom:var(--space-6)}
@container (min-width:520px){ .acv-tiles{grid-template-columns:repeat(2,1fr)} }
@container (min-width:800px){ .acv-tiles{grid-template-columns:repeat(3,1fr)} }
@container (min-width:1040px){ .acv-tiles{grid-template-columns:repeat(5,1fr)} }
.acv-tile{border:1px solid var(--border-default);border-radius:var(--radius-lg);
     padding:var(--space-4);background:var(--surface-card);display:grid;
     gap:var(--space-1);align-content:start;min-width:0}
.acv-tile-v{font-size:var(--font-2xl);font-weight:640;letter-spacing:-.02em;
     line-height:1.1;font-variant-numeric:tabular-nums;min-width:0;
     overflow-wrap:anywhere}
.acv-tile-l{font-size:var(--font-xs);font-weight:700;text-transform:uppercase;
     letter-spacing:.06em;color:var(--text-muted)}
.acv-tile-n{font-size:var(--font-xs);color:var(--text-muted);
     font-variant-numeric:tabular-nums}
/* The toned note. --success / --danger are TENANT tokens, and a tenant is free
   to pick a bright one: fryaway@asuite's light --danger (#E34800) measures
   4.04:1 on the card, under AA for this 11-12px line, while the same rule reads
   6.47:1 on the tenants that keep the platform red. The tone is the POINT here,
   so it is not dropped for a neutral -- it is mixed toward --text-primary, which
   every theme re-binds per mode. That is hue-preserving (this stays plainly red
   or plainly green) and its floor stops depending on the tenant's choice:
   fryaway 4.04 to 6.52:1, and the tenants that already passed only get safer
   (fleet 6.47 to 9.34:1 light, 6.53 to 8.66:1 dark). Colour still carries the
   tone; it no longer carries the legibility. */
.acv-tile-n[data-tone="good"]{color:color-mix(in srgb, var(--success) 70%, var(--text-primary))}
.acv-tile-n[data-tone="bad"]{color:color-mix(in srgb, var(--danger) 70%, var(--text-primary))}
/* NOT MEASURED is grey and says so in words. Never a red zero, never $0.00. */
.acv-tile[data-tone="none"] .acv-tile-v{color:var(--text-muted);font-weight:500;
     font-size:var(--font-lg)}
.acv-none{color:var(--text-muted)}

/* the sparkline. One path, geometry from the endpoint. */
.acv-spark{width:100%;height:26px;display:block;margin-top:var(--space-2);
     overflow:visible}
.acv-spark path{fill:none;stroke:var(--acv-series);stroke-width:1.6;
     vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}

/* cards + the per-day bars */
.acv-card{border:1px solid var(--border-default);border-radius:var(--radius-lg);
     background:var(--surface-card);padding:var(--space-5);margin-bottom:var(--space-5)}
.acv-card-head{display:flex;align-items:baseline;justify-content:space-between;
     gap:var(--space-3);margin-bottom:var(--space-4);flex-wrap:wrap}
.acv-card-t{font-size:var(--font-base);font-weight:640;margin:0}
.acv-card-n{font-size:var(--font-xs);color:var(--text-muted);margin:2px 0 0;max-width:62ch}
.acv-legend{display:flex;gap:var(--space-4);font-size:var(--font-xs);
     color:var(--text-muted);flex-wrap:wrap}
.acv-legend i{display:inline-block;width:9px;height:9px;border-radius:2px;
     margin-right:5px;vertical-align:-1px;background:var(--acv-series)}
.acv-legend i[data-tone="bad"]{background:var(--danger)}
/* Amber is HELD BACK — a mute, a quiet hour, a duplicate the system caught. It is
   the system working, so it must never be drawn in the colour of a failure. */
.acv-legend i[data-tone="warn"]{background:var(--warning)}
/* An out-link in an analytics pane, capped to the same 58rem the lists use.
   ".aac-out" is a full-width flex row with its arrow pushed to the far edge —
   which is right in the admin rail's narrow pane and, at 1440px here, puts a
   thousand pixels between a label and the arrow that belongs to it.
   (NO BACKTICKS in this comment, or in any other one below this line: it lives
   inside a backtick template literal, so one closes the literal and the rest of
   the stylesheet is parsed as JavaScript.) */
.acv-out{max-width:58rem}
/* A list whose NAME is a sentence rather than a label.
   .acv-name is nowrap-with-ellipsis, which is right for a channel or a title and
   wrong for "the address is not on the allowed list for that channel": measured at
   375px, every row of the reasons list clipped, by 53 to 148px, and the clipped
   part is the part that says what happened. Prose wraps; labels still truncate. */
.acv-prose .acv-name{white-space:normal;overflow:visible;text-overflow:clip}
.acv-prose .acv-row{align-items:start}
.acv-plot{height:132px;width:100%;display:block}
.acv-plot rect{fill:var(--acv-series)}
.acv-plot rect.acv-b-warn{fill:var(--warning)}
.acv-plot rect.acv-b-fail{fill:var(--danger)}
.acv-axis{display:flex;justify-content:space-between;font-size:var(--font-xs);
     color:var(--text-muted);margin-top:var(--space-2);font-variant-numeric:tabular-nums}

/* the top-N list with its share bar.

   The max-width is load-bearing, not taste. These rows put an elastic NAME on the
   left and its number on the right, and on a wide pane the name column absorbs
   every pixel of slack: measured on a 1440-wide screen the name column was 1030px
   holding 62px of text, leaving 984px between "Data read" and the number that
   belongs to it. A row that wide is not a row, it is two things on the same line.
   Capping the list keeps a name and its count inside one glance; the chart above
   still gets the full pane, because a chart is the one thing that wants it. */
.acv-list{display:grid;gap:1px;background:var(--border-subtle);
     border:1px solid var(--border-subtle);border-radius:var(--radius-md);overflow:hidden;
     max-width:58rem}
.acv-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:var(--space-4);
     align-items:center;padding:9px var(--space-4);background:var(--surface-card);min-width:0}
@media (hover:hover) and (pointer:fine){ .acv-row:hover{background:var(--surface-hover)} }
/* The name is the ONE elastic element; everything beside it is intrinsic. */
.acv-name{min-width:0;font-size:var(--font-sm);font-weight:500;overflow:hidden;
     text-overflow:ellipsis;white-space:nowrap}
.acv-name small{display:block;font-size:var(--font-xs);color:var(--text-muted);
     font-weight:400;text-transform:none;letter-spacing:0;overflow:hidden;
     text-overflow:ellipsis}
/* 9 tabular characters — budgeted for 1,289,082, not for the 3 digits a typical
   app shows. The tail rows are the ones somebody is hunting for. */
.acv-n{font-size:var(--font-sm);font-variant-numeric:tabular-nums;text-align:right;
     min-width:9ch;color:var(--text-primary)}
.acv-sub{font-size:var(--font-xs);color:var(--text-muted);
     font-variant-numeric:tabular-nums;text-align:right;min-width:8ch}
.acv-share{grid-column:1 / -1;height:3px;border-radius:var(--radius-full);
     background:var(--surface-subtle);overflow:hidden;margin-top:2px}
.acv-share i{display:block;height:100%;background:var(--acv-series);border-radius:inherit}
.acv-kind{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;
     letter-spacing:.05em;padding:1px 6px;border-radius:var(--radius-full);
     border:1px solid var(--border-default);color:var(--text-muted);
     margin-right:var(--space-2);vertical-align:1px}

/* needs-a-look. Rendered only when it has something in it. */
.acv-look{border:1px solid var(--border-default);border-left:3px solid var(--warning);
     border-radius:var(--radius-md);background:var(--surface-card);padding:var(--space-4);
     display:grid;gap:var(--space-2);margin-bottom:var(--space-5);max-width:58rem}
.acv-look-t{font-size:var(--font-sm);font-weight:640}
.acv-look a{display:flex;align-items:center;justify-content:space-between;
     gap:var(--space-3);font-size:var(--font-sm);color:var(--text-secondary);
     text-decoration:none;padding:5px 0;border-top:1px solid var(--border-subtle);
     min-height:var(--tap-target,44px)}
.acv-look a:first-of-type{border-top:0}
/* A finding with no screen to open is text, not a dead link. */
.acv-look-x{font-size:var(--font-sm);color:var(--text-secondary);margin:0;
     padding:5px 0;border-top:1px solid var(--border-subtle)}
.acv-look-t + .acv-look-x{border-top:0}
/* The action word is --text-primary, NOT --accent. Measured: --accent (#2563eb)
   on the dark card (#161b22) is 3.35:1, which fails AA for 12px text — the accent
   does not re-bind between modes, so it is fine on white and dim on black. It was
   also the wrong colour by this console's own rule, where colour carries exactly
   one meaning (accent = the series being measured) and never decorates. The arrow
   and the anchor carry the affordance; 14.64:1 carries the words. */
.acv-look a span:last-child{color:var(--text-primary);font-weight:600;
     font-size:var(--font-xs);flex:none}
@media (hover:hover) and (pointer:fine){
  .acv-look a:hover span:first-child{color:var(--text-primary)}
}

/* A finding may carry its own one-line explanation under it — "a tool it used
   failed" is the headline, "the assistant answered, but something it reached for
   did not work" is what that means. Same treatment the top-N rows give a note. */
.acv-look-x small{display:block;font-size:var(--font-xs);color:var(--text-muted);
     margin-top:2px}

/* Two cards abreast where the pane is wide enough for both to stay readable.
   Generic on purpose — any unit with sibling breakdowns wants this and none of
   them should invent its own grid.

   The lists inside keep their 58rem cap rather than overriding it: in two columns
   the cap never binds, and in ONE column (a narrow pane) it is the thing that
   stops a name and its count drifting to opposite ends of the row. */
/* align-items:start is the load-bearing word. A grid stretches its items to the
   tallest in the row by default, so a one-row breakdown beside an eight-row one
   grew to match it: measured 735px of card holding 161px of list, 574px of white
   under a single line. Two cards side by side are not one card; each is its own
   height. */
.acv-cols{display:grid;gap:var(--space-5);grid-template-columns:1fr;
     align-items:start;margin-bottom:var(--space-5)}
@container (min-width:860px){ .acv-cols{grid-template-columns:repeat(2,1fr)} }
.acv-cols > .acv-card{margin-bottom:0}

/* A row of measurements inside a card — four numbers that answer one question
   together, so they share a scale and sit on one line where there is room.
   Not tiles: tiles are the page's headline and these are a detail of one card. */
.acv-stats{display:grid;gap:var(--space-5);grid-template-columns:1fr}
@container (min-width:520px){ .acv-stats{grid-template-columns:repeat(2,1fr)} }
@container (min-width:960px){ .acv-stats{grid-template-columns:repeat(4,1fr)} }
.acv-stat{min-width:0}
.acv-stat-l{font-size:var(--font-xs);font-weight:700;text-transform:uppercase;
     letter-spacing:.06em;color:var(--text-muted);margin-bottom:var(--space-1)}
.acv-stat-v{font-size:var(--font-xl);font-weight:640;letter-spacing:-.01em;
     line-height:1.15;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
/* Not measured is grey and says so in words, at a smaller size — the same rule
   the tiles keep, so an absent number never arrives looking like a failure. */
.acv-stat-v[data-tone="none"]{color:var(--text-muted);font-weight:500;
     font-size:var(--font-base)}
.acv-stat-n{font-size:var(--font-xs);color:var(--text-muted);margin-top:2px}

/* the two-lane divider: the machine lane is visibly a different population */
.acv-lane{margin-top:var(--space-8);padding-top:var(--space-6);
     border-top:1px dashed var(--border-strong)}
.acv-lane-t{font-size:var(--font-xs);font-weight:700;text-transform:uppercase;
     letter-spacing:.07em;color:var(--text-muted);margin:0 0 var(--space-1)}
.acv-lane-n{font-size:var(--font-sm);color:var(--text-secondary);
     margin:0 0 var(--space-4);max-width:58ch}

/* the honest empty state. Grey, explanatory, never an error.
   --text-muted measures 4.83:1 on white but 4.41:1 on this tinted panel, which
   fails AA — measured, not assumed, so the body steps up to --text-secondary. */
.acv-empty{border:1px dashed var(--border-strong);border-radius:var(--radius-lg);
     padding:var(--space-10) var(--space-6);text-align:center;color:var(--text-muted);
     background:var(--surface-subtle)}
.acv-empty h4{font-size:var(--font-base);font-weight:640;color:var(--text-secondary);
     margin:0 0 var(--space-2)}
.acv-empty p{font-size:var(--font-sm);color:var(--text-secondary);margin:0 auto;max-width:54ch}
.acv-empty p + p{margin-top:var(--space-3)}

/* the estimate marker. Money renders no other way. */
.acv-est{font-size:var(--font-xs);font-weight:600;color:var(--text-muted);
     text-transform:none;letter-spacing:0;margin-left:5px}
.acv-foot{font-size:var(--font-xs);color:var(--text-muted);margin-top:var(--space-4);
     padding-top:var(--space-3);border-top:1px solid var(--border-subtle);max-width:58ch}

@container (max-width:620px){
  /* The percentage drops before the name is ever allowed to truncate — the
     elastic element keeps its width. */
  .acv-row{grid-template-columns:minmax(0,1fr) auto}
  .acv-sub{display:none}
}


/* able-admin-nav */

able-admin-nav { display: contents; }
able-admin-nav .aan { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
able-admin-nav .aan[data-variant="inline"] { flex-direction: row; align-items: center; gap: 1px; flex-wrap: wrap; }
able-admin-nav .aan-label {
  font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-muted, #6b7280); padding: 8px 10px 3px;
}
able-admin-nav .aan-item {
  display: inline-flex; align-items: center; gap: 10px; min-height: 40px; padding: 8px 10px;
  border-radius: var(--radius-md, 8px); text-decoration: none;
  font-size: 13.5px; font-weight: 600; font-family: inherit; color: var(--text-secondary, #3f3f46);
  transition: background .12s ease, color .12s ease;
}
able-admin-nav .aan[data-variant="inline"] .aan-item { min-height: 34px; gap: 7px; }
able-admin-nav .aan-item[data-aan-active="true"] {
  color: var(--text-primary, #1d1c17); background: var(--surface-hover, rgba(0, 0, 0, .05));
}
@media (hover: hover) and (pointer: fine) {
  able-admin-nav .aan-item:hover {
    color: var(--text-primary, #1d1c17); background: var(--surface-hover, rgba(0, 0, 0, .05));
  }
}
able-admin-nav .aan-ico {
  flex: 0 0 auto; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; color: inherit;
}
able-admin-nav .aan-ico svg { width: 18px; height: 18px; }
able-admin-nav .aan-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }


/* able-app-header */

able-app-header { display: block; }
.aah-bar {
  display: grid;
  grid-template-columns: auto auto 1fr auto auto auto auto;
  gap: 16px;
  align-items: center;
  padding: 12px 20px;
  height: 60px;
  box-sizing: border-box;
  background-color: var(--aah-fill, var(--accent, #0f172a));
  /* Use --on-accent (always white, semantically pinned to accent bg) — NOT
     --text-inverse (which flips to dark in dark mode per the inverse-
     surface semantic). The masthead bg is always --accent, so the text
     must always be white-on-accent regardless of theme. */
  color: var(--on-accent, #fff);
}
/* Notifications opt-in adds a bell cell before the theme toggle. The desktop
   grid gains one auto column so the 8th participating item never wraps to a
   second row (the same failure the burger cell documents). Gated on the
   modifier so a header WITHOUT the bell keeps the untouched 7-column grid. */
.aah-bar--with-bell { grid-template-columns: auto auto 1fr auto auto auto auto auto; }
.aah-area { display: flex; align-items: center; gap: 8px; min-width: 0; }
.aah-area--logo { justify-content: flex-start; }
.aah-area--title { padding-left: 4px; }
/* Logo + title are anchor tags (home link) — strip default link chrome
 * but keep them cursor:pointer + focusable. */
a.aah-home-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  border-radius: 6px;
}
a.aah-home-link:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 2px;
}
a.aah-home-link:hover { opacity: 0.9; }
.aah-area--nav { gap: 16px; flex: 0 1 auto; }
.aah-area--extra { gap: 8px; }
.aah-area--ask-able { justify-content: flex-end; }
.aah-area--user { position: relative; }
.aah-logo-img { height: 36px; max-height: 40px; width: auto; display: block; }
.aah-logo-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.1); color: inherit;
  font-weight: 700; font-size: 14px;
}
.aah-title { margin: 0; font-size: 17px; font-weight: 700; color: inherit; white-space: nowrap; }
.aah-ask-able {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(255, 255, 255, 0.08); color: inherit;
  border: 1px solid rgba(255, 255, 255, 0.12);
  padding: 6px 14px; border-radius: 9999px; font-size: 13px;
  cursor: pointer; transition: background-color 120ms;
}
.aah-ask-able:hover { background: rgba(255, 255, 255, 0.16); }
.aah-ask-icon { font-size: 14px; }
.aah-theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 9999px;
  background: rgba(255, 255, 255, 0.06); color: inherit;
  border: 0; cursor: pointer; transition: background-color 120ms;
}
.aah-theme-toggle:hover { background: rgba(255, 255, 255, 0.14); }
/* The notifications bell trigger — <able-notification-bell> ships a deliberately
   minimal .anb-btn (32x32, transparent, currentColor) for host shells to dress.
   Mirror the theme toggle exactly: same square, same round radius, same
   white-on-accent scrim + hover. The masthead bg is always --accent, so the
   scrim is a theme-agnostic white overlay (same rationale as the toggle), and
   the icon inherits the always-white-on-accent currentColor. Hover is gated to
   fine pointers so touch devices never sticky-hover the trigger. */
.aah-bell .anb-btn {
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.06);
  transition: background-color 120ms;
}
@media (hover: hover) and (pointer: fine) {
  .aah-bell .anb-btn:hover { background: rgba(255, 255, 255, 0.14); }
}
/* The account dropdown is the nested <able-user-menu> blueprint — it ships its
 * own styles (.aum-*) tuned for a dark navbar + the impersonation treatment.
 * The header only positions the cell (.aah-area--user is position:relative). */
/* Burger button — hidden by default, shown only on mobile via @media.
   The CELL must hide too: the desktop grid declares 7 columns for 8 emitted
   areas — an empty participating burger cell shifts every later area one
   column and wraps .aah-area--user onto a second row (the 2026-06-11
   build-admin "user menu fell out of the header" bug). */
.aah-area--burger {
  display: none;
}
.aah-burger {
  display: none;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 0;
  color: inherit;
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  padding: 8px;
}
.aah-burger span {
  display: block;
  width: 24px;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
  transition: transform 200ms, opacity 200ms;
}
/* Hamburger → X animation */
.aah-burger[aria-expanded="true"] span:first-child {
  transform: rotate(45deg) translate(7px, 7px);
}
.aah-burger[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.aah-burger[aria-expanded="true"] span:last-child {
  transform: rotate(-45deg) translate(7px, -7px);
}
/* iOS HIG / Android material — 44×44 minimum touch target on coarse pointers.
   Keeps the desktop (fine pointer) dense; expands hit area on phones/tablets. */
@media (pointer: coarse) {
  .aah-theme-toggle, .aah-bell .anb-btn, .aah-area--logo, .aah-area--user, .aah-ask-able {
    min-width: 44px; min-height: 44px;
  }
  .aah-area--logo { padding: 0 6px; }
}
/* Safe-area-inset for iPhone notch / dynamic island */
.aah-bar {
  padding-top: max(12px, env(safe-area-inset-top));
  padding-left: max(20px, env(safe-area-inset-left));
  padding-right: max(20px, env(safe-area-inset-right));
}
@media (max-width: 600px) {
  .aah-bar {
    grid-template-columns: auto 1fr auto auto auto auto;
    padding: 8px 12px;
    gap: 8px;
    position: relative;
  }
  /* With the bell present, the mobile row (logo · title · ask-able · burger ·
     bell · theme · user) needs one more column too. */
  .aah-bar--with-bell { grid-template-columns: auto 1fr auto auto auto auto auto; }
  .aah-area--nav, .aah-area--extra { display: none; }
  .aah-area--burger { display: flex; }
  .aah-burger { display: flex; }
  /* When burger toggled open, show nav + extra as overlay below header */
  able-app-header.aah-mobile-nav-open .aah-area--nav,
  able-app-header.aah-mobile-nav-open .aah-area--extra {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--aah-fill, var(--accent, #0f172a));
    border-bottom: 1px solid var(--border-default, rgba(255, 255, 255, 0.08));
    padding: 12px 16px;
    z-index: 50;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  }
  .aah-title { font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .aah-ask-label { display: none; }
}


/* able-automation-cmdk */

able-automation-cmdk { display: contents; }
.ac-cmdk-back { position: fixed; inset: 0; z-index: 200; background: var(--surface-overlay, rgba(15,18,28,.44)); backdrop-filter: blur(2px); opacity: 0; pointer-events: none; transition: opacity .16s; }
.ac-cmdk-back.on { opacity: 1; pointer-events: auto; }
.ac-cmdk { position: fixed; top: 11vh; left: 50%; transform: translateX(-50%) translateY(-10px); z-index: 201; width: min(620px, calc(100vw - 28px)); max-height: 72dvh; display: flex; flex-direction: column;
  background: var(--surface-card, #fff); color: var(--text-primary, #1d1c17); border: 1px solid var(--border-default, #e2e6ec); border-radius: var(--radius-lg, 14px); box-shadow: var(--shadow-lg, 0 18px 44px -18px rgba(20,26,44,.3)); opacity: 0; pointer-events: none; transition: opacity .16s, transform .16s; overflow: hidden; }
.ac-cmdk.on { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.ac-cmdk-inp { display: flex; align-items: center; gap: 10px; padding: 13px 16px; border-bottom: 1px solid var(--border-subtle, #eef1f5); }
.ac-cmdk-inp svg { width: 18px; height: 18px; color: var(--text-subtle, #9ca3af); flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.ac-cmdk-inp input { flex: 1; border: 0; outline: none; background: transparent; color: inherit; font: 500 15px var(--font-sans, sans-serif); }
.ac-cmdk-inp input::placeholder { color: var(--text-subtle, #9ca3af); }
.ac-cmdk-inp .kbd { font: 600 10px var(--font-mono, monospace); color: var(--text-muted, #6b7280); border: 1px solid var(--border-default, #e2e6ec); border-radius: 5px; padding: 2px 6px; flex: none; }
.ac-cmdk-body { flex: 1; overflow-y: auto; padding: 6px; }
.ac-cmdk-grp-h { display: flex; align-items: center; gap: 7px; padding: 9px 10px 5px; font: 600 10px var(--font-mono, monospace); letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted, #6b7280); }
.ac-cmdk-grp-h svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ac-cmdk-grp-h .c { margin-left: auto; opacity: .7; }
.ac-cmdk-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; cursor: pointer; }
.ac-cmdk-row.active, .ac-cmdk-row:hover { background: var(--surface-hover, #f4f6fb); }
.ac-cmdk-row .rico { width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center; flex: none; background: var(--surface-subtle, #f1f5f9); color: var(--text-muted, #6b7280); }
.ac-cmdk-row .rico svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.ac-cmdk-row .rn { flex: 1; min-width: 0; }
.ac-cmdk-row .rn b { font: 500 13px/1.3 var(--font-mono, monospace); color: var(--text-primary, #1d1c17); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac-cmdk-row .rn small { font-size: 11px; color: var(--text-muted, #6b7280); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac-cmdk-row .rt { font-size: 9px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; padding: 1px 6px; border-radius: 999px; border: 1px solid; flex: none; }
.ac-cmdk-row .rt.db { color: var(--db, #5a6b82); border-color: color-mix(in srgb, var(--db, #5a6b82) 40%, transparent); background: var(--db-soft, #eef1f6); }
.ac-cmdk-row .rt.git { color: var(--git, #1b2a4a); border-color: color-mix(in srgb, var(--git, #1b2a4a) 35%, transparent); background: var(--git-soft, #e6ebf5); border-style: dashed; }
.ac-cmdk-empty { padding: 26px 18px; text-align: center; color: var(--text-muted, #6b7280); font-size: 12.5px; line-height: 1.6; }
.ac-cmdk-empty b { color: var(--text-secondary, #3f3f46); }
@media (max-width: 560px) { .ac-cmdk { top: 0; left: 0; transform: none; width: 100vw; max-height: 100dvh; height: 100dvh; border-radius: 0; } .ac-cmdk.on { transform: none; } }


/* able-cart-drawer */

able-cart-drawer {
  position: fixed; top: 0; bottom: 0; right: 0;
  width: 420px; max-width: 100vw;
  z-index: 901;
  background: var(--surface-card, #ffffff);
  color: var(--text-primary, #1d1c17);
  box-shadow: -12px 0 36px rgba(0, 0, 0, 0.18);
  transform: translateX(100%);
  transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
  display: flex; flex-direction: column;
  overflow: hidden;
}
able-cart-drawer[data-open="true"] { transform: translateX(0); }
@media (max-width: 479px) {
  able-cart-drawer {
    width: 100%;
    top: auto; right: 0; left: 0; bottom: 0;
    height: 90dvh; max-height: 90dvh;
    transform: translateY(100%);
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
    box-shadow: 0 -12px 36px rgba(0, 0, 0, 0.18);
  }
  able-cart-drawer[data-open="true"] { transform: translateY(0); }
  able-cart-drawer::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 4px;
    background: rgba(0, 0, 0, 0.18);
    border-radius: 2px;
    pointer-events: none;
  }
}
.acd-backdrop {
  position: fixed; inset: 0; z-index: 900;
  background: rgba(11, 15, 26, 0.45);
  opacity: 0; pointer-events: none;
  transition: opacity 220ms ease;
}
.acd-backdrop--open { opacity: 1; pointer-events: auto; }
.acd-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-subtle, #f1f5f9);
  flex-shrink: 0;
  padding-top: max(16px, env(safe-area-inset-top));
}
.acd-title {
  font-size: 16px; font-weight: 600;
  display: flex; align-items: center; gap: 8px;
  margin: 0;
}
.acd-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  background: var(--accent, #1b2a4a); color: var(--on-accent, #fff);
  border-radius: 11px;
  font-size: 12px; font-weight: 600;
}
.acd-close {
  width: 44px; height: 44px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: inherit; border: 0; cursor: pointer;
  font-size: 24px; line-height: 1;
}
.acd-close:hover { background: rgba(0, 0, 0, 0.05); }
.acd-body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px 0;
}
.acd-empty {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center;
  padding: 48px 24px;
  color: var(--text-muted, #6b7280);
  text-align: center;
  gap: 12px;
}
.acd-empty-icon {
  font-size: 48px;
  opacity: 0.4;
}
.acd-empty-text {
  font-size: 14px;
  margin: 0;
}
.acd-footer {
  flex-shrink: 0;
  border-top: 1px solid var(--border-subtle, #f1f5f9);
  padding: 16px 20px;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  background: var(--surface-base, #ffffff);
  display: flex; flex-direction: column; gap: 14px;
}
.acd-checkout {
  min-height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #1b2a4a); color: var(--on-accent, #fff);
  border: 0; border-radius: 8px;
  font-size: 15px; font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  padding: 0 20px;
  transition: background 160ms ease;
}
.acd-checkout:hover { background: var(--accent-hover, #16223d); }
.acd-checkout:active { background: var(--accent-active, #111a2e); }
.acd-checkout[aria-disabled="true"] {
  background: var(--surface-active, #e5e7eb);
  color: var(--text-muted, #6b7280);
  pointer-events: none;
  cursor: not-allowed;
}


/* able-cart-line */

able-cart-line {
  display: block;
  border-bottom: 1px solid var(--border-subtle, #f1f5f9);
}
able-cart-line:last-child { border-bottom: 0; }
.acl-line {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  grid-template-rows: auto auto;
  grid-template-areas:
    "image body remove"
    "image qty   price";
  gap: 4px 12px;
  align-items: start;
  padding: 14px 20px;
}
.acl-image {
  grid-area: image;
  width: 64px; height: 64px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface-subtle, #f1f5f9);
}
.acl-image img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.acl-body {
  grid-area: body;
  min-width: 0;
}
.acl-name {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary, #1d1c17);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acl-name:hover { text-decoration: underline; }
.acl-variant {
  font-size: 12px;
  color: var(--text-secondary, #3f3f46);
  margin: 2px 0 0;
}
.acl-sku {
  font-size: 11px;
  color: var(--text-muted, #6b7280);
  margin: 2px 0 0;
  letter-spacing: 0.02em;
}
.acl-qty {
  grid-area: qty;
  display: flex; align-items: center;
}
.acl-price {
  grid-area: price;
  display: flex; align-items: center; justify-content: flex-end;
  font-size: 14px; font-weight: 600;
  color: var(--text-primary, #1d1c17);
  font-variant-numeric: tabular-nums;
}
.acl-remove {
  grid-area: remove;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; cursor: pointer;
  font-size: 20px; color: var(--text-muted, #6b7280);
  border-radius: 6px;
  align-self: flex-start;
  justify-self: end;
}
.acl-remove:hover {
  background: var(--danger-soft, #fee2e2);
  color: var(--danger, #b91c1c);
}
.acl-line--empty { display: none; }


/* able-cart-summary */

able-cart-summary { display: block; }
.acs {
  display: flex; flex-direction: column;
  gap: 8px;
  width: 100%;
}
.acs-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 14px;
  color: var(--text-secondary, #3f3f46);
  font-variant-numeric: tabular-nums;
}
.acs-label { font-weight: 400; }
.acs-discount-row { color: var(--success, #15803d); }
.acs-savings {
  color: var(--success, #15803d);
  font-weight: 500;
}
.acs-shipping-free {
  color: var(--success, #15803d);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: none;
}
.acs-total-row {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-primary, #1d1c17);
  border-top: 1px solid var(--border-default, #e5e7eb);
  padding-top: 12px;
  margin-top: 4px;
}
.acs-total-row .acs-label { font-weight: 700; }
.acs-total-row able-price { font-size: 18px; }


/* able-checkout-stepper */

able-checkout-stepper { display: block; }
.achs-wrap { width: 100%; }
.achs--desktop {
  display: flex;
  list-style: none;
  padding: 0; margin: 0;
  gap: 12px;
  align-items: center;
  justify-content: center;
}
.achs--mobile { display: none; }
@media (max-width: 639px) {
  .achs--desktop { display: none; }
  .achs--mobile { display: block; }
}
.achs-step {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  position: relative;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted, #6b7280);
  user-select: none;
}
.achs-step + .achs-step::before {
  content: '';
  display: inline-block;
  width: 32px; height: 1px;
  background: var(--border-default, #e5e7eb);
  margin-right: 8px;
  vertical-align: middle;
}
.achs-step[data-state="completed"] + .achs-step::before {
  background: var(--accent, #1b2a4a);
}
.achs-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--surface-subtle, #f1f5f9);
  color: var(--text-muted, #6b7280);
  font-size: 12px; font-weight: 600;
  border: 1px solid var(--border-default, #e5e7eb);
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.achs-step[data-state="completed"] .achs-num {
  background: var(--accent, #1b2a4a);
  color: var(--on-accent, #fff);
  border-color: var(--accent, #1b2a4a);
}
.achs-step[data-state="current"] .achs-num {
  background: var(--surface-base, #ffffff);
  color: var(--accent, #1b2a4a);
  border-color: var(--accent, #1b2a4a);
  font-weight: 700;
}
.achs-step[data-state="current"] {
  color: var(--text-primary, #1d1c17);
}
.achs-step[data-state="completed"] {
  color: var(--text-secondary, #3f3f46);
}
.achs-step[data-clickable="true"] {
  cursor: pointer;
}
.achs-step[data-clickable="true"]:hover .achs-num {
  background: var(--accent-hover, #16223d);
  border-color: var(--accent-hover, #16223d);
}
.achs-label { white-space: nowrap; }
.achs--mobile {
  display: none;
  padding: 12px 4px;
}
@media (max-width: 639px) { .achs--mobile { display: block; } }
.achs-mobile-text {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary, #1d1c17);
  margin-bottom: 8px;
}
.achs-progress {
  width: 100%;
  height: 4px;
  background: var(--surface-subtle, #f1f5f9);
  border-radius: 2px;
  overflow: hidden;
}
.achs-progress-fill {
  height: 100%;
  background: var(--accent, #1b2a4a);
  transition: width 280ms ease;
}


/* able-claw */

able-claw {
  /* Layout knobs */
  --ableclaw-sidebar-width:      240px;
  --ableclaw-artifact-width:     360px;
  --ableclaw-mobile-breakpoint:  720px;
  --ableclaw-radius:             12px;
  --ableclaw-radius-sm:          8px;

  /* Surfaces — every var resolves through theme tokens first; fallback is
     the dark default that ships with the legacy scanner/asuite themes. To
     opt into light mode in your theme, set --surface-card and friends
     to light values under your [data-theme='light'] block; the blueprint
     will follow automatically. */
  --ableclaw-bg:                 var(--surface-card, #141415);
  --ableclaw-fg:                 var(--text-primary, #e2e8f0);
  --ableclaw-sidebar-bg:         var(--surface-subtle, var(--surface-card, rgba(0, 0, 0, 0.18)));
  --ableclaw-sidebar-fg:         var(--text-primary, #e2e8f0);
  --ableclaw-sidebar-active-bg:  var(--surface-hover, var(--surface-subtle, rgba(127, 127, 127, 0.18)));
  --ableclaw-sidebar-hover-bg:   var(--surface-hover, rgba(127, 127, 127, 0.10));
  --ableclaw-artifact-bg:        var(--surface-subtle, rgba(0, 0, 0, 0.18));
  --ableclaw-border:             var(--border-default, rgba(127, 127, 127, 0.20));
  --ableclaw-border-soft:        var(--border-default, rgba(127, 127, 127, 0.12));

  /* Chat bubbles */
  --ableclaw-bubble-user-bg:     var(--accent-secondary, #3b82f6);
  --ableclaw-bubble-user-fg:     var(--on-accent-secondary, #ffffff);
  --ableclaw-bubble-agent-bg:    var(--surface-subtle, rgba(127, 127, 127, 0.10));
  --ableclaw-bubble-agent-fg:    var(--text-primary, #e2e8f0);

  /* Input bar */
  --ableclaw-input-bg:           var(--surface-card, #141415);
  --ableclaw-input-fg:           var(--text-primary, #e2e8f0);
  --ableclaw-input-border:       var(--border-default, rgba(127, 127, 127, 0.20));
  --ableclaw-input-bar-bg:       var(--surface-subtle, rgba(0, 0, 0, 0.12));

  /* Code + tables (the bug-D surface) */
  --ableclaw-code-bg:            rgba(0, 0, 0, 0.4);
  --ableclaw-code-fg:            inherit;
  --ableclaw-table-header-bg:    rgba(99, 102, 241, 0.18);
  --ableclaw-table-header-fg:    var(--text-primary, #f1f5f9);
  --ableclaw-table-row-bg:       transparent;
  --ableclaw-table-border:       var(--border-default, rgba(255, 255, 255, 0.18));

  /* Buttons + accents */
  --ableclaw-link:               #93c5fd;
  --ableclaw-accent:             var(--accent-secondary, #3b82f6);
  --ableclaw-accent-fg:          #ffffff;
  --ableclaw-stop-bg:            #dc2626;
  --ableclaw-stop-bg-hover:      #b91c1c;

  /* Conversation channel badges (dot to the left of each row title).
     Host pages rebrand by overriding any of these. Channel keys map to
     ai.conversations.channel_type values (case-insensitive — ABLEUI and
     ableui both resolve to the default). */
  --ableclaw-channel-default:    #6366f1;   /* ABLEUI / ableui — indigo */
  --ableclaw-channel-telegram:   #38bdf8;   /* cyan */
  --ableclaw-channel-email:      #94a3b8;   /* slate */
  --ableclaw-channel-slack:      #c026d3;   /* magenta */
  --ableclaw-channel-sms:        #22c55e;   /* green (also whatsapp) */
  --ableclaw-channel-web:        #64748b;   /* gray */
  --ableclaw-channel-voice:      #f59e0b;   /* amber — spoken (voice) turns */

  /* Host height clamp.
     ============================================================================
     <able-claw> MUST have a bounded height for its internal grid to lay out
     correctly. Without this, an unbounded parent (height:auto, min-height:100vh)
     lets the sidebar's conversation list inflate the host past the viewport,
     pushing the chat input row BELOW the fold.
     Strategy: clamp the host to 100dvh minus an optional offset for chrome
     above us (a sticky page header, an outer padding, etc). Host pages
     calibrate the offset via the --ableclaw-viewport-offset custom property:
         <style>able-claw { --ableclaw-viewport-offset: 60px; }</style>
     Default 0 → host fills the full dynamic viewport (correct for pages with
     no chrome above <able-claw>).
     100dvh tracks the dynamic viewport (mobile address bar collapse) better
     than 100vh. contain: size tells the browser our intrinsic height is
     independent of content — internal grid scrolls instead of inflating us. */
  --ableclaw-viewport-offset:    0px;

  display: block;
  width: 100%;
  height: calc(100dvh - var(--ableclaw-viewport-offset));
  max-height: calc(100dvh - var(--ableclaw-viewport-offset));
  min-height: 480px;
  color: var(--ableclaw-fg);
  box-sizing: border-box;
  /* contain: layout only — NOT size or style. size caused grid-snap
     glitches when toggling data-sidebar-collapsed (chat column went 0-width
     during the grid-template-columns transition). overflow: hidden is
     what actually prevents content from inflating the host. */
  contain: layout;
  overflow: hidden;
}
/* When the host explicitly opts out by setting --ableclaw-viewport-offset
   to a non-zero value AND the parent has its own definite height, the
   100dvh clamp still wins. Host pages with a SHORTER definite container
   (e.g. a 600px-tall card) should use height:100% on a wrapper and pass
   the offset that accounts for the shell + their wrapper math. */
.aclaw-grid {
  display: grid;
  grid-template-columns: var(--ableclaw-sidebar-width) 1fr 0fr;
  width: 100%;
  height: 100%;
  min-height: 0;
  min-width: 0;
  background: var(--ableclaw-bg);
  border: 1px solid var(--ableclaw-border-soft);
  border-radius: var(--ableclaw-radius);
  overflow: hidden;
  /* Anchor point for the floating Agent Thinking overlay used in
     helper/launcher modes (it positions: absolute against this box). */
  position: relative;
  /* NO grid-template-columns transition — Chrome's interpolation between
     "var(--w) 1fr 0fr" and "0 1fr 0fr" left the chat column at 0 width
     mid-flight, presenting as a blank screen. Snap is fine; the visual
     change is intentional and instant. */
  box-sizing: border-box;
}
.aclaw-grid:has(.aclaw-artifact:not([hidden])) { grid-template-columns: var(--ableclaw-sidebar-width) 1fr var(--ableclaw-artifact-width); }
/* Collapsed state — driven by the data-sidebar-collapsed attribute on the
   host element. We deliberately use ONLY this single selector path (the
   older .aclaw-grid--sidebar-collapsed class is no longer toggled by JS;
   see _setSidebarCollapsed). Rules are tightly scoped: hide ONLY the
   .aclaw-sidebar element. .aclaw-chat (the main content column) and
   .aclaw-artifact (when visible) MUST remain rendered — the chat column
   expands to fill the freed grid track. */
able-claw[data-sidebar-collapsed="true"] > .aclaw-grid {
  grid-template-columns: 0 1fr 0fr;
}
able-claw[data-sidebar-collapsed="true"] > .aclaw-grid:has(.aclaw-artifact:not([hidden])) {
  grid-template-columns: 0 1fr var(--ableclaw-artifact-width);
}
/* When collapsed, the sidebar's grid column is 0px (see grid-template-columns
   above), but we MUST NOT use display:none — that removes the element from
   the grid placement entirely, which shifts the .aclaw-chat element into
   the now-empty column 1 (also 0px). Result: chat width collapses to 0 and
   the page renders empty. visibility:hidden + pointer-events:none keeps the
   sidebar element in flow so the chat stays anchored in grid column 2. */
able-claw[data-sidebar-collapsed="true"] > .aclaw-grid > .aclaw-sidebar {
  visibility: hidden;
  pointer-events: none;
  overflow: hidden;
}
/* Bug #6 (desktop) — when the sidebar is collapsed, the floating expand
   (hamburger) button sits absolutely at the chat's top-left over the message
   stream. Without clearance, the agent greeting's ONLINE row collides with it
   (and the brain toggle at top-right). The mobile @media already pads the
   stream; this collapsed-state rule extends the same clearance to DESKTOP
   (where the user collapsed the sidebar). Specificity (0,2,1) beats the later
   Liquid-Glass able-claw .aclaw-messages rule; only fires while collapsed so
   the expanded desktop layout is untouched. */
able-claw[data-sidebar-collapsed="true"] .aclaw-messages { padding-top: 60px; }
able-claw[data-sidebar-collapsed="true"] .aclaw-welcome  { padding-top: 60px; }

.aclaw-sidebar {
  display: flex; flex-direction: column;
  background: var(--ableclaw-sidebar-bg);
  color: var(--ableclaw-sidebar-fg);
  border-right: 1px solid var(--ableclaw-border-soft);
  min-height: 0;
  min-width: 0;
  /* No overflow:hidden — agent-popover (absolute in header) needs to extend
     below the header. The conversation list inside has its own overflow-y. */
}
.aclaw-sidebar-header {
  padding: 12px;
  border-bottom: 1px solid var(--ableclaw-border-soft);
  display: flex; flex-direction: column; gap: 8px;
  position: relative;
  flex-shrink: 0;
}
.aclaw-sidebar-header-row {
  display: flex; align-items: center; gap: 6px;
}
.aclaw-new-chat {
  flex: 1;
  padding: 8px 12px;
  background: var(--ableclaw-accent); color: var(--ableclaw-accent-fg);
  border: 0; border-radius: var(--ableclaw-radius-sm); cursor: pointer; font-size: 13px; font-weight: 600;
  transition: opacity 120ms;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-width: 0;
}
.aclaw-new-chat:hover { opacity: 0.92; }
.aclaw-kbd-hint {
  display: inline-flex; align-items: center;
  padding: 2px 6px;
  font-size: 11px; font-weight: 500;
  background: rgba(255, 255, 255, 0.18);
  border-radius: 4px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}

/* Sidebar brand header — small AbleClaw label + agent welcome title that
   sits above the New Conversation button. Mirrors the target design. */
.aclaw-sidebar-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 4px 8px 4px;
  border-bottom: 1px dashed var(--border-default, rgba(255, 255, 255, 0.06));
  margin-bottom: 4px;
}
.aclaw-sidebar-brand-icon {
  width: 28px; height: 28px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #a78bfa, #7c3aed);
  color: #fff; font-size: 14px;
  flex: 0 0 auto;
}
.aclaw-sidebar-brand-text {
  display: flex; flex-direction: column; min-width: 0; line-height: 1.2;
}
.aclaw-sidebar-brand-text strong {
  font-size: 12px; font-weight: 700; letter-spacing: 0.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aclaw-sidebar-brand-text span {
  font-size: 11px; opacity: 0.65;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aclaw-sidebar-collapse {
  flex: 0 0 auto;
  width: 32px; height: 32px;
  background: transparent; color: inherit;
  border: 1px solid var(--ableclaw-border);
  border-radius: var(--ableclaw-radius-sm); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1;
  opacity: 0.7;
  transition: opacity 120ms, background-color 120ms;
}
.aclaw-sidebar-collapse:hover { opacity: 1; background: var(--ableclaw-sidebar-hover-bg); }
.aclaw-sidebar-expand {
  position: absolute; top: 12px; left: 12px;
  width: 32px; height: 32px;
  background: var(--surface-subtle, var(--ableclaw-sidebar-bg));
  color: var(--text-primary, inherit);
  border: 1px solid var(--border-default, var(--ableclaw-border));
  border-radius: var(--ableclaw-radius-sm); cursor: pointer;
  /* Hidden by default; flipped to inline-flex when the host carries
     data-sidebar-collapsed="true". !important guards against page-level
     CSS that might otherwise overdetermine the display property. */
  display: none; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 600; line-height: 1;
  opacity: 0.95; z-index: 50;
  pointer-events: auto;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  transition: opacity 120ms, background-color 120ms, transform 120ms;
}
able-claw[data-sidebar-collapsed="true"] .aclaw-sidebar-expand { display: inline-flex !important; }
.aclaw-sidebar-expand:hover {
  opacity: 1;
  background: var(--surface-card, var(--ableclaw-sidebar-active-bg));
  transform: translateX(1px);
}
.aclaw-search {
  width: 100%;
  padding: 6px 10px;
  background: var(--surface-card, #141415); color: inherit;
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.10));
  border-radius: 6px;
  font: inherit; font-size: 12px;
  box-sizing: border-box;
}
.aclaw-search:focus {
  outline: none;
  border-color: var(--accent-secondary, #3b82f6);
}

/* TALKING TO — agent-selector dropdown trigger in sidebar header. */
.aclaw-talking-to {
  display: flex; flex-direction: column; gap: 6px;
}
.aclaw-talking-to-label {
  font-size: 10px; font-weight: 600; letter-spacing: 0.10em;
  text-transform: uppercase;
  opacity: 0.55;
  padding: 0 2px;
}
.aclaw-agent-selector {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  background: var(--surface-card, rgba(255, 255, 255, 0.04));
  color: inherit;
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.10));
  border-radius: 8px; cursor: pointer;
  text-align: left;
  transition: background-color 120ms, border-color 120ms;
}
.aclaw-agent-selector:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: var(--accent-secondary, #3b82f6);
}
.aclaw-agent-selector .aclaw-agent-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: #fff;
  background: var(--accent-secondary, #3b82f6);
  flex: 0 0 auto;
}
.aclaw-agent-selector .aclaw-agent-meta {
  min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
}
.aclaw-agent-selector .aclaw-agent-name {
  font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aclaw-agent-selector .aclaw-agent-tagline {
  font-size: 11px; opacity: 0.6;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aclaw-agent-selector .aclaw-agent-chevron {
  flex: 0 0 auto;
  font-size: 14px; opacity: 0.5;
}

/* MODEL override picker — compact row under the agent selector. A/B a
   different model on the same agent; selection persists per agent. */
.aclaw-model-pick {
  display: flex; align-items: center; gap: 8px;
  margin-top: 6px; padding: 0 2px;
}
.aclaw-model-pick-label {
  font-size: 9px; font-weight: 700; letter-spacing: 0.08em;
  opacity: 0.55; flex: none;
}
.aclaw-model-select {
  flex: 1; min-width: 0;
  font-size: 11px; padding: 3px 6px;
  border-radius: 6px;
  border: 1px solid var(--ableclaw-sidebar-border, rgba(127,127,127,0.25));
  background: var(--ableclaw-sidebar-bg, transparent);
  color: inherit;
  cursor: pointer;
}
.aclaw-model-select:hover { border-color: var(--ableclaw-accent, #2563eb); }

/* ── Composer MODEL·EFFORT chip + menu (the Claude-style picker on the input
   bar). The chip shows the effective model (+ effort when overridden); the
   menu lists the FEATURED models with taglines and an Effort submenu. Shares
   the _modelOverride state with the sidebar select. ── */
.aclaw-model-chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600;
  padding: 6px 10px; border-radius: 999px;
  border: 1px solid var(--border-default, rgba(127,127,127,0.25));
  background: var(--surface-subtle, rgba(127,127,127,0.08));
  color: inherit; cursor: pointer; white-space: nowrap;
  max-width: 220px; overflow: hidden; text-overflow: ellipsis;
}
.aclaw-model-chip:hover { border-color: var(--ableclaw-accent, #2563eb); }
.aclaw-model-chip .amc-effort { opacity: 0.6; font-weight: 500; }
.aclaw-model-chip .amc-caret { opacity: 0.5; font-size: 10px; }
.aclaw-model-menu {
  position: absolute; right: 8px; bottom: calc(100% + 8px);
  min-width: 280px; max-width: 340px; max-height: 420px; overflow-y: auto;
  background: var(--surface-card, #1a1a1c);
  border: 1px solid var(--border-default, rgba(255,255,255,0.12));
  border-radius: 12px; padding: 6px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.35);
  z-index: 30; display: flex; flex-direction: column; gap: 2px;
}
.aclaw-model-menu[hidden] { display: none !important; }
.aclaw-mm-item {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px;
  text-align: left; width: 100%;
  padding: 8px 10px; border: none; border-radius: 8px;
  background: transparent; color: inherit; cursor: pointer;
}
.aclaw-mm-item:hover { background: var(--surface-hover, rgba(127,127,127,0.12)); }
.aclaw-mm-item .amm-name { font-size: 13px; font-weight: 600; }
.aclaw-mm-item .amm-desc { font-size: 11px; opacity: 0.6; margin-top: 1px; }
.aclaw-mm-item .amm-check { color: var(--ableclaw-accent, #2563eb); font-weight: 700; }
.aclaw-mm-divider {
  height: 1px; margin: 4px 6px;
  background: var(--border-default, rgba(127,127,127,0.2));
}
.aclaw-mm-hint {
  font-size: 11px; opacity: 0.6; padding: 6px 10px 4px; line-height: 1.4;
}
/* the menu anchors to the input bar (relative w/o offsets = zero layout change) */
.aclaw-input-bar { position: relative; }

.aclaw-agent-popover {
  position: absolute;
  background: var(--surface-card, #1a1a1c);
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.12));
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.40);
  padding: 6px;
  z-index: 10;
  display: flex; flex-direction: column; gap: 2px;
  max-height: 320px; overflow-y: auto;
  min-width: 220px;
}
.aclaw-agent-popover[hidden] { display: none !important; }
.aclaw-agent-option {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: transparent; color: inherit; border: 0; cursor: pointer;
  text-align: left;
  border-radius: 6px;
  transition: background-color 120ms;
}
.aclaw-agent-option:hover { background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10)); }
.aclaw-agent-option.is-active { background: var(--ableclaw-sidebar-active-bg, rgba(127, 127, 127, 0.18)); }
.aclaw-agent-option .aclaw-agent-avatar {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: #fff;
  background: var(--accent-secondary, #3b82f6);
  flex: 0 0 auto;
}
.aclaw-agent-option .aclaw-agent-meta {
  min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
}
.aclaw-agent-option .aclaw-agent-name {
  font-size: 13px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aclaw-agent-option .aclaw-agent-tagline {
  font-size: 11px; opacity: 0.6;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* YOUR CHATS group header + day-bucket sub-headers. Static labels rendered
   inside the conversation list; bucket headers are emitted between rows
   when conversations span multiple recency windows. */
.aclaw-conversation-group-header {
  font-size: 10px; font-weight: 600; letter-spacing: 0.10em;
  text-transform: uppercase;
  opacity: 0.55;
  padding: 8px 10px 4px 10px;
}
.aclaw-conversation-bucket-header {
  font-size: 11px; font-weight: 500;
  opacity: 0.45;
  padding: 8px 10px 2px 10px;
  text-transform: uppercase; letter-spacing: 0.05em;
}

.aclaw-conversation-row[hidden] { display: none !important; }
.aclaw-conversation-list {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 8px;
  display: flex; flex-direction: column; gap: 4px;
  /* Bug #119 — thin overlay scrollbar that blends with the sidebar
     surface. Default browser scrollbars render as a chunky dark column on
     light themes, which looks heavier than the content. scrollbar-width
     drives Firefox + modern Chromium; webkit-scrollbar rules tune
     Chrome/Safari directly. Thumb fades in on hover so the bar mostly
     disappears at rest, ChatGPT/Claude-style. */
  scrollbar-width: thin;
  scrollbar-color: var(--ableclaw-scrollbar-thumb, rgba(120, 120, 130, 0.32)) transparent;
}
.aclaw-conversation-list::-webkit-scrollbar { width: 8px; background: transparent; }
.aclaw-conversation-list::-webkit-scrollbar-track { background: transparent; }
.aclaw-conversation-list::-webkit-scrollbar-thumb {
  background: var(--ableclaw-scrollbar-thumb, rgba(120, 120, 130, 0.22));
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background-color 140ms ease;
}
.aclaw-conversation-list:hover::-webkit-scrollbar-thumb {
  background: var(--ableclaw-scrollbar-thumb-hover, rgba(120, 120, 130, 0.45));
  background-clip: padding-box;
}
.aclaw-conversation-list::-webkit-scrollbar-thumb:hover {
  background: var(--ableclaw-scrollbar-thumb-active, rgba(120, 120, 130, 0.6));
  background-clip: padding-box;
}
.aclaw-empty-conversations {
  padding: 12px; font-size: 12px; opacity: 0.6; text-align: center;
}
/* COMPACT rows (restructure spec) — ~32px single line, ~2x the density. */
.aclaw-conversation-row {
  position: relative;
  border-radius: 6px;
  border-left: 2px solid transparent;
  transition: background-color 120ms;
}
.aclaw-conversation-row:hover { background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10)); }
.aclaw-conversation-row.is-active {
  background: var(--ableclaw-sidebar-active-bg, rgba(127, 127, 127, 0.18));
  border-left-color: var(--conv-accent, var(--ableclaw-accent, #6366f1));
}
.aclaw-conversation-row.is-active .aclaw-conv-glyph { color: var(--conv-accent, var(--ableclaw-accent, #6366f1)); }
/* Bug #101 — streaming-in-progress indicator. Pulsing dot on rows whose
   conversation has an in-flight stream. Shown for background streams
   (when the user has navigated away from a conv that's still receiving
   deltas) AND for the active conv (subtle reinforcement of the in-bar
   indicator). The :before is anchored bottom-right of the row so it
   doesn't push other content; pulses with a 1.4s cycle. */
.aclaw-conversation-row[data-streaming="true"]::after,
.aclaw-conversation[data-streaming="true"]::after {
  content: "";
  position: absolute;
  right: 8px; top: 50%; transform: translateY(-50%);
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ableclaw-accent, #6366f1);
  box-shadow: 0 0 0 0 var(--ableclaw-accent, #6366f1);
  animation: aclaw-conv-stream-pulse 1.4s ease-out infinite;
  pointer-events: none;
}
@keyframes aclaw-conv-stream-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.5); opacity: 1; }
  100% { box-shadow: 0 0 0 8px rgba(99, 102, 241, 0);   opacity: 0.6; }
}
.aclaw-conversation {
  width: 100%; min-width: 0;
  display: grid; grid-template-columns: 16px 1fr auto; align-items: center; gap: 7px;
  text-align: left;
  padding: 5px 10px; min-height: 32px;
  background: transparent; color: inherit; border: 0; cursor: pointer;
  font-size: 12.5px; line-height: 1.25;
  border-radius: 6px;
}
.aclaw-conv-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex-shrink: 0;
  color: var(--conv-accent, var(--ableclaw-text-muted, #9ca3af));
}
.aclaw-conv-time {
  font-size: 11px; color: var(--ableclaw-text-muted, #9ca3af);
  opacity: 0; transition: opacity 120ms; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.aclaw-conversation-row:hover .aclaw-conv-time,
.aclaw-conversation-row.is-active .aclaw-conv-time { opacity: 1; }
/* Hover-reveal actions, absolutely placed so they never reflow the row. */
.aclaw-conv-actions {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  display: none; gap: 2px; align-items: center;
  background: var(--ableclaw-sidebar-active-bg, rgba(127,127,127,.18));
  border-radius: 6px; padding: 1px;
}
.aclaw-conversation-row:hover .aclaw-conv-actions { display: flex; }
.aclaw-conversation-row:hover .aclaw-conv-time { opacity: 0; }  /* actions replace the time on hover */
.aclaw-conversation.is-active { background: transparent; }
.aclaw-conversation-title-row {
  display: flex; align-items: center; gap: 6px; min-width: 0;
}
.aclaw-conv-badge {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 999px;
  flex-shrink: 0;
  background: var(--ableclaw-channel-default);
}
.aclaw-conv-badge[data-channel="telegram"]  { background: var(--ableclaw-channel-telegram); }
.aclaw-conv-badge[data-channel="email"]     { background: var(--ableclaw-channel-email); }
.aclaw-conv-badge[data-channel="slack"]     { background: var(--ableclaw-channel-slack); }
.aclaw-conv-badge[data-channel="sms"]       { background: var(--ableclaw-channel-sms); }
.aclaw-conv-badge[data-channel="whatsapp"]  { background: var(--ableclaw-channel-sms); }
.aclaw-conv-badge[data-channel="web"]       { background: var(--ableclaw-channel-web); }
.aclaw-conv-badge[data-channel="voice"]     { background: var(--ableclaw-channel-voice); }

/* Conversation row icons — one round, brand-colored badge per channel
   that participated in the conversation. Inside each badge sits a
   FontAwesome glyph (loaded via the theme's vendorLibraries declaration).
   Hosts without FA still get the colored badge (just no glyph inside),
   which still signals channel origin via color + the title attribute. */
.aclaw-conv-icons {
  display: inline-flex; align-items: center; gap: 4px;
  flex-shrink: 0;
}
.aclaw-conv-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  border-radius: 50%;
  color: #ffffff;
  background: var(--ableclaw-channel-default);
  font-size: 9px; line-height: 1;
  flex-shrink: 0;
}
.aclaw-conv-icon i { color: inherit; line-height: 1; }
.aclaw-conv-icon[data-channel="telegram"]  { background: var(--ableclaw-channel-telegram); }
.aclaw-conv-icon[data-channel="email"]     { background: var(--ableclaw-channel-email); }
.aclaw-conv-icon[data-channel="slack"]     { background: var(--ableclaw-channel-slack); }
.aclaw-conv-icon[data-channel="sms"]       { background: var(--ableclaw-channel-sms); }
.aclaw-conv-icon[data-channel="whatsapp"]  { background: var(--ableclaw-channel-sms); }
.aclaw-conv-icon[data-channel="web"]       { background: var(--ableclaw-channel-web); }
.aclaw-conv-icon[data-channel="ableui"]    { background: var(--ableclaw-channel-default); }
.aclaw-conv-icon[data-channel="voice"]     { background: var(--ableclaw-channel-voice); }

/* Main-chat channel separator — hair-thin line gradient with a soft tinted
   pill centered. Modern minimal aesthetic: the pill background uses
   color-mix() with the channel color at 8% opacity, falling back to a
   neutral tint for older browsers. */
.aclaw-channel-divider {
  display: flex; align-items: center; gap: 14px;
  width: 100%; margin: 20px 0 14px;
  color: var(--text-muted, var(--ableclaw-sidebar-fg));
  user-select: none;
}
.aclaw-channel-divider::before,
.aclaw-channel-divider::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent 0%,
    var(--border-default, var(--ableclaw-border, rgba(127,127,127,0.20))) 30%,
    var(--border-default, var(--ableclaw-border, rgba(127,127,127,0.20))) 70%,
    transparent 100%
  );
}
.aclaw-channel-divider-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.10em; text-transform: uppercase;
  line-height: 1;
  background: color-mix(in srgb, currentColor 8%, transparent);
}
.aclaw-channel-divider-pill svg { width: 11px; height: 11px; flex-shrink: 0; }
.aclaw-channel-divider-pill i { font-size: 10px; line-height: 1; flex-shrink: 0; }
.aclaw-channel-divider[data-channel="telegram"] .aclaw-channel-divider-pill { color: var(--ableclaw-channel-telegram); }
.aclaw-channel-divider[data-channel="email"]    .aclaw-channel-divider-pill { color: var(--ableclaw-channel-email); }
.aclaw-channel-divider[data-channel="slack"]    .aclaw-channel-divider-pill { color: var(--ableclaw-channel-slack); }
.aclaw-channel-divider[data-channel="sms"]      .aclaw-channel-divider-pill { color: var(--ableclaw-channel-sms); }
.aclaw-channel-divider[data-channel="whatsapp"] .aclaw-channel-divider-pill { color: var(--ableclaw-channel-sms); }
.aclaw-channel-divider[data-channel="web"]      .aclaw-channel-divider-pill { color: var(--ableclaw-channel-web); }
.aclaw-channel-divider[data-channel="ableui"]   .aclaw-channel-divider-pill { color: var(--ableclaw-channel-default); }
.aclaw-channel-divider[data-channel="voice"]    .aclaw-channel-divider-pill { color: var(--ableclaw-channel-voice); }
/* Spoken vs typed — a small mic glyph beside the timestamp on voice turns.
   FA-gated exactly like the divider icons (themes opt in via vendorLibraries). */
.aclaw-message[data-channel="voice"] .aclaw-message-time::before {
  content: '\f130'; font-family: 'Font Awesome 6 Free', 'FontAwesome';
  font-weight: 900; font-size: 9px; margin-right: 5px;
  opacity: .45;   /* the row no longer dims children — match the time text */
}
.aclaw-conversation-title {
  font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  flex: 1; min-width: 0;
}
.aclaw-conversation-meta { font-size: 11px; opacity: 0.5; margin-top: 2px; }
/* Bug #119 — copy + delete buttons OVERLAY the row from the right edge so
   they never compress the title. Title gets 100% width always; the buttons
   fade in on row :hover with a gradient mask underneath that hides the
   tail of the title under the buttons (ChatGPT / Claude sidebar pattern).
   Pre-fix the buttons were flex 0/0/24px reserving ~48px of horizontal
   space at all times even when opacity:0, which forced titles like
   "Image Analysi…" to truncate on a 240px sidebar. */
/* Bug #119 — buttons OVERLAY at the bottom-right of the row, aligned
   with the meta row baseline (the "Yesterday 14:04" timestamp). They
   sit on row 2 instead of dead-centering on row 1's title, which made
   them look like they were colliding with the title text on hover. */
/* Inline in the hover-reveal .aclaw-conv-actions container (compact rows). */
.aclaw-conversation-delete,
.aclaw-conversation-copy-id {
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: inherit; border: 0;
  cursor: pointer; opacity: 0.7;
  font-size: 12px; line-height: 1;
  border-radius: 4px;
  transition: opacity 120ms, background-color 120ms;
}
.aclaw-conversation-delete { font-size: 14px; }
.aclaw-conversation-row:hover .aclaw-conversation-delete,
.aclaw-conversation-row:hover .aclaw-conversation-copy-id {
  opacity: 0.7;
  pointer-events: auto;
}
.aclaw-conversation-delete:hover,
.aclaw-conversation-copy-id:hover {
  opacity: 1; background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.20));
}
.aclaw-conversation-copy-id.is-copied {
  opacity: 1 !important;
  pointer-events: auto;
  color: var(--success, #16a34a);
  background: rgba(22, 163, 74, 0.10);
}

.aclaw-chat {
  display: grid;
  /* Welcome AND messages share row 1 (only one visible at a time via [hidden]);
     attachments + input + footer stay fixed at the bottom regardless of
     conversation list length in the sidebar. min-height: 0 propagates through
     the grid so the middle row scrolls instead of pushing the input off-screen. */
  grid-template-rows: minmax(0, 1fr) auto auto auto;
  /* width-law-v1 companion — the column track was IMPLICIT (auto-sized), so
     the widest child's min-content INFLATED it past the container: on a 375px
     phone a datagrid-bearing thread blew the track to ~463px and .aclaw-chat's
     overflow:hidden CLIPPED the right edge of every message (pre-existing for
     long prose; the width law made widget bubbles hit it too). minmax(0,1fr)
     pins the track to the container — wide content stays inside the bubble and
     scrolls in its own overflow-x wrapper (claw-tbl / claw-grid-wrap). */
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "stream"
    "attachments"
    "input"
    "footer";
  min-width: 0; min-height: 0;
  position: relative;
  overflow: hidden;
}
.aclaw-welcome,
.aclaw-messages    { grid-area: stream; }
.aclaw-attachments { grid-area: attachments; }
.aclaw-input-bar   { grid-area: input; }
.aclaw-input-footer { grid-area: footer; }
.aclaw-welcome {
  min-height: 0; min-width: 0;
  overflow-y: auto; overflow-x: hidden;
  padding: 24px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px;
  /* Ensures narrow viewports never cause inner inline flow to break into
     single-character columns — children get a width budget, not the
     intrinsic content width. */
  box-sizing: border-box;
}
/* Welcome text always reflows as a paragraph, even at very narrow widths.
   Without these, the inline children of .aclaw-welcome shrink to fit the
   smallest word and overflow vertically one-character-per-line. */
.aclaw-welcome > * { max-width: 100%; box-sizing: border-box; }
.aclaw-welcome p, .aclaw-welcome h1, .aclaw-welcome .aclaw-welcome-subtitle,
.aclaw-welcome .aclaw-welcome-helper {
  word-wrap: break-word; overflow-wrap: break-word;
}
/* Explicit hide — author-level [hidden] beats the implicit user-agent rule
   that the explicit display:flex above otherwise overrides. Without this
   the welcome panel + shortcut grid stay visible above the message stream
   when the conversation transitions from welcome state to messages. */
.aclaw-welcome[hidden] { display: none !important; }
.aclaw-welcome-identity {
  display: flex; align-items: center; gap: 12px;
}
.aclaw-welcome-avatar {
  width: 44px; height: 44px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 700; color: #fff;
  background: var(--accent-secondary, #3b82f6);
}
.aclaw-welcome-name-block { display: flex; flex-direction: column; gap: 2px; }
.aclaw-welcome-name { font-size: 16px; font-weight: 600; }
.aclaw-welcome-tagline { font-size: 12px; opacity: 0.6; }
.aclaw-welcome-headline { text-align: center; max-width: 720px; }
.aclaw-welcome-title { font-size: 22px; font-weight: 600; margin: 0 0 6px 0; }
.aclaw-welcome-subtitle { font-size: 14px; opacity: 0.7; margin: 0; line-height: 1.5; }
.aclaw-shortcut-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
  width: 100%; max-width: 720px;
}
.aclaw-shortcut {
  display: flex; flex-direction: column; gap: 6px; align-items: flex-start;
  padding: 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.08));
  border-radius: 10px; color: inherit; cursor: pointer;
  text-align: left;
  transition: background-color 120ms, border-color 120ms;
}
.aclaw-shortcut:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--accent-secondary, #3b82f6);
}
.aclaw-shortcut-icon { font-size: 18px; opacity: 0.85; }
.aclaw-shortcut-category {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  opacity: 0.6;
}
.aclaw-shortcut-text { font-size: 13px; line-height: 1.4; }

/* WELCOME REDESIGN — large sparkle icon + headline + 4-category shortcut
   grid (ANALYZE / MONITOR / ACT / REPORT). Each column has a colored
   header and stacked bordered cards. */
.aclaw-welcome-icon {
  width: 96px; height: 96px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #a78bfa, #7c3aed);
  color: #fff;
  box-shadow: 0 12px 32px rgba(124, 58, 237, 0.35);
  margin-bottom: 6px;
}
.aclaw-welcome-icon svg {
  width: 48px; height: 48px;
  fill: currentColor;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
}
.aclaw-welcome-headline-h1 {
  font-size: 28px; font-weight: 700;
  text-align: center;
  margin: 0;
  letter-spacing: -0.01em;
}
.aclaw-welcome-categories {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  width: 100%; max-width: 960px;
  margin-top: 8px;
}
@media (max-width: 1100px) {
  .aclaw-welcome-categories { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .aclaw-welcome-categories { grid-template-columns: 1fr; }
}
.aclaw-welcome-category {
  display: flex; flex-direction: column; gap: 8px;
}
.aclaw-welcome-category-header {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.10em;
  text-transform: uppercase;
  padding: 4px 0;
}
.aclaw-welcome-category-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 6px;
  font-size: 13px;
  flex: 0 0 auto;
}
.aclaw-welcome-category-items {
  display: flex; flex-direction: column; gap: 8px;
}
.aclaw-welcome-category-items .aclaw-shortcut {
  flex-direction: column; gap: 4px; align-items: flex-start;
}
/* Per-category accent — header label color + card border accent on hover. */
.aclaw-welcome-category--analyze .aclaw-welcome-category-header { color: #10b981; }
.aclaw-welcome-category--analyze .aclaw-welcome-category-icon  { background: rgba(16, 185, 129, 0.18); color: #10b981; }
.aclaw-welcome-category--analyze .aclaw-shortcut:hover         { border-color: #10b981; }

.aclaw-welcome-category--monitor .aclaw-welcome-category-header { color: #3b82f6; }
.aclaw-welcome-category--monitor .aclaw-welcome-category-icon  { background: rgba(59, 130, 246, 0.18); color: #3b82f6; }
.aclaw-welcome-category--monitor .aclaw-shortcut:hover         { border-color: #3b82f6; }

.aclaw-welcome-category--act .aclaw-welcome-category-header { color: #eab308; }
.aclaw-welcome-category--act .aclaw-welcome-category-icon  { background: rgba(234, 179, 8, 0.18); color: #eab308; }
.aclaw-welcome-category--act .aclaw-shortcut:hover         { border-color: #eab308; }

.aclaw-welcome-category--report .aclaw-welcome-category-header { color: #ef4444; }
.aclaw-welcome-category--report .aclaw-welcome-category-icon  { background: rgba(239, 68, 68, 0.18); color: #ef4444; }
.aclaw-welcome-category--report .aclaw-shortcut:hover         { border-color: #ef4444; }

.aclaw-welcome-helper {
  font-size: 13px; opacity: 0.55;
  text-align: center;
  margin: 4px 0 0 0;
}
.aclaw-welcome-helper em { font-style: italic; }

.aclaw-messages {
  min-height: 0; min-width: 0;
  overflow-y: auto; overflow-x: hidden;
  padding: 16px 24px;
  display: flex; flex-direction: column; gap: 12px;
  box-sizing: border-box;
}
.aclaw-messages[hidden] { display: none !important; }
/* Jump-to-latest — the arrow-down affordance (2026-08-03 scroll pass).
   Sticky at the scroller's bottom edge; ONLY rendered while the reader is
   scrolled up (hidden at the bottom). While new content arrives with the
   reader scrolled up we NEVER yank the view — the pill flips to its accent
   "new" state instead; clicking it returns to the live tail and re-engages
   follow. In-flow last child of the column, so a wiped thread re-render just
   re-appends the same node. */
.aclaw-jump-latest {
  position: sticky; bottom: 10px; align-self: center; z-index: 30;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-width: 38px; height: 38px; padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--border-default, rgba(127,127,127,.28));
  background: var(--surface-card, rgba(255,255,255,.92));
  color: var(--text-primary, #1d1c17);
  font: inherit; font-size: 13px; font-weight: 600; line-height: 1;
  cursor: pointer; box-shadow: var(--shadow-md, 0 4px 14px rgba(0,0,0,.18));
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  flex: 0 0 auto;
}
.aclaw-jump-latest[hidden] { display: none !important; }
.aclaw-jump-latest:hover { background: var(--surface-hover, rgba(255,255,255,1)); }
.aclaw-jump-latest .aclaw-jump-label { display: none; }
.aclaw-jump-latest[data-new="true"] {
  background: var(--accent, var(--ableclaw-accent, #6366f1));
  border-color: var(--accent, var(--ableclaw-accent, #6366f1));
  color: var(--on-accent, #fff);
}
.aclaw-jump-latest[data-new="true"] .aclaw-jump-label { display: inline; }
@media (pointer: coarse) {
  .aclaw-jump-latest { min-width: 44px; height: 44px; }   /* tap-target law */
}
.aclaw-message { display: flex; flex-direction: column; gap: 4px; }
.aclaw-message--user { align-items: flex-end; }
.aclaw-message--assistant { align-items: flex-start; }

/* Greeting bubble — assistant intro shown when the conversation is fresh
   (no real messages yet) or has just been started via "+ New chat".
   ONLINE pill above the bubble matches the agent-online affordance. */
.aclaw-greeting-status {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #10b981;
}
.aclaw-greeting-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #10b981;
  box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
  animation: aclaw-greeting-pulse 2s infinite;
}
@keyframes aclaw-greeting-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
  70%  { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
  100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
}
.aclaw-message-bubble {
  max-width: 80%;
  padding: 11px 16px;
  /* Asymmetric radius — assistant bubble has flat bottom-left ("speaking
     from the left"); user bubble has flat bottom-right ("speaking from
     the right"). Modern chat-bubble convention. */
  border-radius: 16px 16px 16px 4px;
  background: var(--ableclaw-bubble-agent-bg);
  color: var(--ableclaw-bubble-agent-fg);
  font-size: 14px; line-height: 1.55;
  word-wrap: break-word;
  overflow-wrap: break-word;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.aclaw-message--user .aclaw-message-bubble {
  background: var(--ableclaw-bubble-user-bg); color: var(--ableclaw-bubble-user-fg);
  border-radius: 16px 16px 4px 16px;
}
/* THE ASSISTANT WIDTH LAW (width-law-v1 — composer-enterprise, Raul
   2026-08-02: "limiting the response to that small area on the left makes it
   look cramped in web"). Assistant rows OWN the content column. max-width:100%
   alone was NOT enough: .aclaw-message is a column flex with align-items:
   flex-start, so the bubble is shrink-to-fit — a response whose widest block
   is a widget (guided-run card / datagrid / kpi band) collapsed to that
   widget's INTRINSIC width (~55-65% of the column) with a dead right gutter.
   width:100% is the floor: the message CONTAINER always spans the column
   (small symmetric gutter = .aclaw-messages padding), widget/figure blocks
   (.aclaw-face cards, claw-tbl, claw-kpis, grids, decks, code, tables,
   headings) fill it edge-to-edge, and body PROSE keeps a readable measure
   via the cap below — figures exceed the text column, the editorial pattern.
   User rows are UNTOUCHED: compact right-aligned chips under the 80% cap. */
.aclaw-message--assistant .aclaw-message-bubble {
  width: 100%; max-width: 100%; box-sizing: border-box;
}
/* Affordance bubbles stay compact chips — the greeting one-liner + the
   typing dots are chrome, not responses. width:auto restores shrink-to-fit
   (flex cross-axis fit-content); order-after the law rule so it wins the
   (0,2,0) tie for the greeting. */
.aclaw-greeting .aclaw-message-bubble,
.aclaw-message--assistant .aclaw-message-bubble--pending { width: auto; }
/* The PROSE MEASURE — body-text blocks inside the full-width surface cap at
   ~76ch (left-aligned), so reclaiming the column never mints 1100px text
   lines. Scope is TOP-LEVEL prose only: markdown-path direct children, and
   claw-path direct children of .claw-root / a top-level .claw-section.
   Prose INSIDE a card / hero / sidebar fills its card — cards own their
   internal layout. Headings + eyebrows are deliberately uncapped
   (display type spans the composition like figures do; ch resolves against
   EACH element's own font, so a 36px .claw-h1 cap would be fiction anyway).
   THE CALLOUT IS PROSE, NOT A CARD (P1, 2026-08-03 — Recovr conv f88203cb):
   it was in the card exemption, so a callout carrying a full paragraph broke
   out to the bubble and rendered the widest, smallest, most-saturated block
   in the message — measured 108.5ch at 13px beside 76.0ch body prose at 14px
   (Raul's "full screen prose vs one part / inconsistent font sizes"). A
   callout is an ASIDE — emphasized running prose doing the same reading job —
   already distinguished by a 3px border, a wash AND semantic color; a fourth
   signal (breaking the column) buys nothing and costs the measure. It is
   border-box, so the 76ch cap lands its 13px content at ~77ch — the same
   line length and the same column edges as body prose. Genuine cards
   (.aclaw-face, grids, decks, tables) keep the exemption and stay full-bleed. */
.aclaw-message--assistant .aclaw-message-bubble > :is(p, ul, ol, blockquote, dl, .claw-callout),
.aclaw-message--assistant .aclaw-message-bubble > [data-ent-sec] > :is(p, ul, ol, blockquote, dl, .claw-callout),
.aclaw-message--assistant .aclaw-message-bubble > :is(.claw-root, .claw-root--editorial) > :is(p, ul, ol, blockquote, dl, .claw-body, .claw-body--editorial, .claw-body--muted, .claw-callout),
.aclaw-message--assistant .aclaw-message-bubble > :is(.claw-root, .claw-root--editorial) > :is(.claw-section, [data-ent-sec]) > :is(p, ul, ol, blockquote, dl, .claw-body, .claw-body--editorial, .claw-body--muted, .claw-callout) {
  max-width: 76ch;
}
/* Recovr forensics 2026-08-03 (conv f88203cb): _entSectionChrome (ENT-E1)
   re-parents every section body into a <div data-ent-sec> wrapper, which
   broke the direct-child prose selectors above — paragraphs BEFORE the first
   <h3> kept the 76ch measure while everything after rendered full-bubble
   (measured 671px vs 1292px in one message). The [data-ent-sec] hops above
   restore ONE measure for the whole thread; sections only ever wrap direct
   children of the bubble or of .claw-root (the h3 scan runs on that host),
   so one hop is the complete set. */
/* WIDGET BUBBLES TAKE THE FULL ROW — the "flashcards go back to being not
   stretched" regression. .aclaw-message is a column flex with align-items:
   flex-start, so a bubble is SHRINK-TO-FIT on the cross axis: max-width caps
   it, nothing gives it a floor. A bubble carrying a whole lesson (headings,
   prose, tables) is pushed to the cap; a bubble whose only content is a widget
   collapses to that widget's INTRINSIC width — so the same deck rendered 247px
   after a follow-up ask and 652px on the first ask. Measured on max@able
   conv 9eaf5284 (2026-07-30): 35 decks across 8 distinct widths
   (247/251/279/281/411/422/500/652) and 142 asks across 8 more
   (240/415/422/432/459/507/546/652). With this rule: one width, 652, for all.
   Widgets are page-furniture, not prose — they get the row, and the reader
   gets one column edge instead of a ragged staircase.
   :has() over a renderer-applied class DELIBERATELY: it is declarative (no
   mount-time walk to re-apply on every stream re-render), it covers all three
   widgets in one rule, and it is already the house pattern here (see
   .aclaw-grid:has(), body:has(), .aclaw-vocab-row:has(+ …)). Widgets mount
   post-stream, so the rule engages exactly when the widget lands. */
.aclaw-message-bubble:has(.aclaw-deck),
.aclaw-message-bubble:has(.aclaw-ask),
.aclaw-message-bubble:has(.aclaw-vocab-row) { width: 100%; }
/* NEWLINE-LAID-OUT HTML — a telegram-grammar message viewed on the web
   (Justin, 2026-08-06: "manda mucha información en 1 párrafo… en Telegram
   lo corta"). A telegram conversation's messages are stored as the bytes
   Telegram renders: inline tags only (<b>/<i>/<a>/<code>…) with the LAYOUT
   carried by newlines — which the HTML path collapses into one wall, and
   with no <p>/<ul> children the 76ch prose law above never engages either.
   renderMarkdown wraps that shape in .aclaw-plainflow: pre-wrap restores
   every break exactly as Telegram shows them, and the wrapper carries the
   same 76ch measure as structured prose. <pre> children keep their own
   whitespace (UA per-element white-space), so figure blocks don't double. */
.aclaw-message-bubble .aclaw-plainflow {
  white-space: pre-wrap;
  overflow-wrap: break-word;
  max-width: 76ch;
}
/* User bubbles: the typed text is escaped into ONE <p> — a multi-line
   telegram message (or a pasted list) collapsed the same way. */
.aclaw-message--user .aclaw-message-bubble p { white-space: pre-wrap; }
.aclaw-message-time {
  /* Opacity moved OFF the row and onto the time text (.aclaw-mt-t): CSS opacity
     COMPOUNDS onto children, so the model badge + interrupted badge could never
     exceed the row's 0.45 — the interrupted badge's documented 4.7:1 contrast
     (Bug #93) was silently dimmed to ~2.1:1, and the model badge failed visual
     review as illegible. Row at 1; each child owns its own muting. */
  font-size: 10px;
  padding: 0 4px;
  font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; gap: 6px;
  flex-wrap: wrap;
}
.aclaw-mt-t { opacity: 0.45; }
/* Partial-turn badge — surfaces on assistant bubbles whose underlying
   conversation_messages.metadata.partial=true (server-side marker written
   when the agent runtime crashed mid-stream). Subtle, muted-gray, sits
   inline with the timestamp; wraps below on narrow viewports. */
.aclaw-message-interrupted {
  /* Bug #93 — raise contrast to WCAG AA 4.5:1 on a typical white background.
     Old: rgba(120,120,120,0.95) text on rgba(120,120,120,0.10) bg ≈ 2.5:1.
     New: #475569 text on #e2e8f0 bg ≈ 4.7:1. */
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 6px;
  border-radius: 8px;
  background: #e2e8f0;
  color: #475569;
  font-size: 9.5px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  font-style: italic;
  cursor: help;
  opacity: 1;
}
.aclaw-message-interrupted i { font-size: 9px; opacity: 0.85; }
/* Per-message model badge — the SUBSTRATE truth for the composer's model picker
   (A/B testing): each assistant bubble is labeled with the model that actually
   produced it (persisted metadata.model on history; the requested model on live
   turns). Never trust the model's own self-report — flash-class models misstate
   their identity even when told. Inherits the time-line's muted color so it
   flips with the theme (no hardcoded hex — the interrupted-badge trap). */
.aclaw-message-model {
  display: inline-flex; align-items: center;
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  opacity: 0.85;   /* measured 5.13:1 on the dark grid bg (WCAG AA; 0.75 was 4.11) */
  cursor: default;
}
.aclaw-code {
  position: relative;
  margin: 8px 0; padding: 8px 12px;
  background: var(--ableclaw-code-bg);
  color: var(--ableclaw-code-fg);
  border-radius: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 12px;
  overflow-x: auto;
}
.aclaw-code-copy {
  position: absolute; top: 6px; right: 6px;
  padding: 2px 8px;
  background: rgba(255, 255, 255, 0.1);
  color: inherit;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 4px;
  font-size: 11px; line-height: 1.4; cursor: pointer;
  opacity: 0; transition: opacity 120ms;
}
.aclaw-code:hover .aclaw-code-copy { opacity: 1; }
.aclaw-code-copy:hover { background: rgba(255, 255, 255, 0.18); }

/* Widget lane — a mounted <able-lesson> becomes this sandboxed iframe. Sized
   by content via the postMessage resize bridge; 440px until the frame reports. */
.aclaw-widget {
  display: block;
  width: 100%;
  margin: 12px 0;
  border: 1px solid var(--ableclaw-table-border, rgba(0, 0, 0, 0.12));
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  min-height: 120px;
}

/* Streaming stand-in for an <able-lesson> — shown while the turn is still
   streaming so the real iframe mounts exactly ONCE, on the final render
   (see _updateStreamingBubble). Prevents per-delta iframe reload flicker. */
.aclaw-widget-loading {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin: 12px 0;
  padding: 16px 14px;
  border: 1px dashed var(--ableclaw-table-border, rgba(0, 0, 0, 0.18));
  border-radius: 12px;
  color: var(--ableclaw-muted, #6b7280);
  font-size: 13px;
  background: rgba(0, 0, 0, 0.02);
}

/* ═══════════ THE STAGE — rail · board · glance · status · receipts ═══════ */
/* Rail — the day's work at the top of the sidebar; conversations demote. */
/* Legacy left-rail (now unused — the route/map lives in the right workspace). */
.aclaw-rail { display: none; }
.aclaw-convs-toggle {
  display: block; width: calc(100% - 20px); margin: 2px 10px; padding: 7px 10px;
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted, #6b7280); background: transparent;
  border: none; border-top: 1px solid var(--border-subtle, rgba(0,0,0,.08));
  text-align: left; cursor: pointer; min-height: 34px;
}
/* Stage cards — shared by rail + board. Wave 2 (C-spec §5): the stage tier
   adopts the COMPOSER-card face family — surface-card / radius 16 /
   border-subtle / shadow-sm, padding 14×16 — same body as every rich block. */
.aclaw-stage-card {
  margin: 0 0 10px; padding: 14px 16px; border-radius: 16px;
  background: var(--surface-card, #fff);
  border: 1px solid var(--border-subtle, rgba(0,0,0,.08));
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(0,0,0,.05));
  font-size: 13px; line-height: 1.45; overflow-wrap: break-word;
}
.aclaw-stage-card-title {
  font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted, #6b7280); margin: 0 0 7px;
}
@keyframes aclaw-stage-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 35%, transparent); } 100% { box-shadow: 0 0 0 9px color-mix(in srgb, var(--accent) 0%, transparent); } }
.aclaw-stage-card--pulse { animation: aclaw-stage-pulse .5s ease-out 1; }
.aclaw-board { padding: 12px; overflow-y: auto; }
/* Thread ref line — where an extracted card / pinned widget used to be.
   The view affordance is a real CHIP of the face family (tokens only). */
.aclaw-card-ref {
  display: flex; align-items: center; gap: 7px; margin: 6px 0;
  font-size: 12px; color: var(--text-muted, #6b7280);
}
.aclaw-card-ref i { opacity: .7; }
.aclaw-card-ref-open {
  border: 1px solid var(--border-default, rgba(0,0,0,.14)); background: transparent;
  border-radius: 999px; padding: 3px 11px; font-size: 11.5px; font-weight: 600;
  color: inherit; cursor: pointer; min-height: 26px;
}
/* Receipts — the ✓ one-liner for every completed write (mid-stream styling;
   at settle _groupReceipts upgrades every run into the ledger card below). */
able-receipt {
  display: flex; align-items: baseline; gap: 8px; margin: 8px 0;
  padding: 9px 12px; border-radius: 10px; font-size: 13px; font-weight: 600;
  background: color-mix(in srgb, var(--success) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
  color: inherit;
}
/* THE COMPOSER CARD (C-spec §2) — ONE surface for every rich content block:
   figures, vocab groups, receipt groups, degrade cards (math/ask keep their
   already-carded chrome). Semantic tokens only — dark mode by construction. */
.aclaw-face {
  background: var(--surface-card); border: 1px solid var(--border-subtle);
  border-radius: 16px; box-shadow: var(--shadow-sm);
  padding: 14px 16px; margin: 12px 0;
}
/* w7/W24 — the receipt-group LEDGER: consecutive receipts in ONE card (a ✓
   glyph column + one row per receipt, single border, success-tinted wash). */
.aclaw-receipt-group {
  padding: 4px 12px;
  background: color-mix(in srgb, var(--success) 5%, var(--surface-card));
  border-color: color-mix(in srgb, var(--success) 24%, transparent);
}
.aclaw-receipt-item {
  display: flex; align-items: baseline; gap: 9px; padding: 8px 2px;
  font-size: 13px; font-weight: 600; line-height: 1.45;
}
.aclaw-receipt-item + .aclaw-receipt-item {
  border-top: 1px solid color-mix(in srgb, var(--success) 14%, transparent);
}
.aclaw-receipt-glyph { flex: 0 0 auto; color: var(--success); font-weight: 700; }
.aclaw-receipt-body { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; }
/* Pin slot — the docked widget above the thread. */
.aclaw-pinslot {
  position: sticky; top: 0; z-index: 5;
  padding: 8px 16px 4px; background: inherit;
}
.aclaw-pinslot .aclaw-widget { margin: 0; box-shadow: 0 6px 18px -8px rgba(0,0,0,.25); }
/* Armed-entity pill (the context wire). Wave-2 shell-chrome tokens (C10):
   the accent token carries the wash — dark by construction. */
.aclaw-armed {
  display: inline-flex; align-items: center; gap: 6px; margin: 0 16px 4px;
  align-self: flex-start; padding: 4px 6px 4px 12px; border-radius: 999px;
  font-size: 12px; font-weight: 700;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
.aclaw-armed-clear {
  border: none; background: transparent; cursor: pointer; font-size: 14px;
  line-height: 1; padding: 4px 7px; color: inherit; border-radius: 999px; min-height: 24px;
}
[data-entity] { cursor: pointer; }
/* Status — the demoted reasoning verb in the footer. */
.aclaw-status {
  display: inline-flex; align-items: center; gap: 6px;
  border: none; background: transparent; cursor: pointer;
  font-size: 11.5px; font-weight: 600; color: var(--ableclaw-muted, #6b7280);
  padding: 2px 8px; border-radius: 999px; min-height: 24px;
}
.aclaw-status--done { color: var(--success); }
.aclaw-status-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  animation: aclaw-status-blink 1.1s ease-in-out infinite;
}
@keyframes aclaw-status-blink { 0%,100% { opacity: .35; } 50% { opacity: 1; } }
/* Live elapsed clock on the streaming status pill (mirrors iOS WorkingIndicator). */
.aclaw-status-clock { opacity: .6; font-variant-numeric: tabular-nums; font-size: .92em; }
/* Mic — push-to-talk (hidden unless the browser has speech recognition). */
.aclaw-mic {
  border: none; background: transparent; cursor: pointer; font-size: 15px;
  color: var(--ableclaw-muted, #6b7280); padding: 8px 10px; border-radius: 10px; min-height: 40px;
}
.aclaw-mic--live { color: var(--danger); animation: aclaw-status-blink 1s ease-in-out infinite; }
/* Glance layer — the ONE read-and-dismiss sheet. */
.aclaw-glance { position: fixed; inset: 0; z-index: 720; }
.aclaw-glance[hidden] { display: none !important; }
.aclaw-glance-backdrop { position: absolute; inset: 0; background: rgba(15,14,20,.38); }
.aclaw-glance-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(460px, 94vw); display: flex; flex-direction: column;
  background: var(--surface-card, #fff);
  box-shadow: -18px 0 48px -18px rgba(0,0,0,.4);
  animation: aclaw-glance-in 200ms cubic-bezier(.22,1,.36,1);
}
@keyframes aclaw-glance-in { from { transform: translateX(28px); opacity: 0; } to { transform: none; opacity: 1; } }
.aclaw-glance-header {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 13px 16px; border-bottom: 1px solid var(--border-subtle, rgba(0,0,0,.1));
  font-weight: 800; font-size: 14px;
}
.aclaw-glance-close {
  border: none; background: transparent; cursor: pointer; font-size: 16px;
  padding: 8px 10px; border-radius: 10px; color: inherit; min-height: 40px; min-width: 40px;
}
.aclaw-glance-body { padding: 14px 16px; overflow-y: auto; font-size: 13.5px; line-height: 1.5; }
.aclaw-glance-empty { color: var(--ableclaw-muted, #6b7280); }
@media (max-width: 640px) {
  .aclaw-glance-panel {
    top: auto; left: 0; width: 100%; max-height: 82dvh; border-radius: 16px 16px 0 0;
    animation: aclaw-glance-up 220ms cubic-bezier(.22,1,.36,1);
  }
  @keyframes aclaw-glance-up { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
}
/* Ledger — dismissed sheets collapse to reopenable pills under the board. */
.aclaw-ledger { padding: 4px 12px 12px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.aclaw-ledger-label { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted, #6b7280); }
.aclaw-ledger-pill {
  border: 1px solid var(--border-default, rgba(0,0,0,.14)); background: transparent;
  border-radius: 999px; padding: 4px 11px; font-size: 11.5px; font-weight: 600;
  color: inherit; cursor: pointer; min-height: 28px; max-width: 160px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Native asks — first-party question cards (data-only agent markup). */
.aclaw-ask {
  margin: 10px 0; padding: 14px 15px; border-radius: 14px;
  background: var(--surface-card, #fff);
  border: 1px solid var(--ableclaw-table-border, rgba(0,0,0,.12));
  box-shadow: 0 1px 3px rgba(0,0,0,.05);
}
.aclaw-ask-topic {
  font-size: 10.5px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ableclaw-muted, #6b7280); margin: 0 0 5px;
}
.aclaw-ask-prompt { font-size: 14.5px; font-weight: 700; line-height: 1.45; margin: 0 0 11px; }
.aclaw-ask-opt {
  display: block; width: 100%; text-align: left; margin: 6px 0; padding: 11px 13px;
  border: 1.5px solid var(--ableclaw-table-border, rgba(0,0,0,.14));
  border-radius: 11px; background: transparent; color: inherit;
  font: inherit; font-size: 13.5px; line-height: 1.4; cursor: pointer; min-height: 44px;
  transition: border-color 140ms, background 140ms;
}
/* w5/L4 — the two-form options wrap. CHIP ROW (every option ≤28 graphemes):
   wrap-flex pills, 44px min tap. MARKER LIST (any longer): stacked buttons with
   a leading letter chip + hanging-indent text that wraps freely. */
.aclaw-ask-opts { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 0; }
.aclaw-ask-opts .aclaw-ask-opt { margin: 0; }
.aclaw-ask-opts[data-form="chips"] { flex-direction: row; flex-wrap: wrap; gap: 8px; }
.aclaw-ask-opts[data-form="chips"] .aclaw-ask-opt {
  display: inline-flex; align-items: center; justify-content: center;
  width: auto; min-width: 44px; padding: 10px 16px; border-radius: 999px;
}
.aclaw-ask-opts[data-form="list"] .aclaw-ask-opt { display: flex; align-items: flex-start; gap: 10px; }
.aclaw-ask-marker {
  flex: 0 0 auto; width: 22px; height: 22px; margin-top: 1px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; line-height: 1;
  color: var(--text-muted); background: var(--surface-subtle);
  border: 1px solid var(--border-subtle);
}
.aclaw-ask-opt-text { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; }
@media (hover: hover) and (pointer: fine) {
  .aclaw-ask-opt:not(:disabled):hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
}
.aclaw-ask-opt:disabled { cursor: default; opacity: .92; }
.aclaw-ask-opt--right { border-color: var(--success); background: color-mix(in srgb, var(--success) 10%, transparent); }
.aclaw-ask-opt--wrong { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 9%, transparent); }
.aclaw-ask-opt--picked { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.aclaw-ask-opt--reveal { border-color: var(--success); border-style: dashed; }
.aclaw-ask-why {
  margin: 10px 0 0; padding: 9px 12px; border-radius: 9px; font-size: 12.5px; line-height: 1.5;
  color: var(--ableclaw-muted, #4b5563);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border-left: 3px solid var(--accent);
}
/* Quiz-set progress footer — "3 of 8 answered" on each card in a riff set. */
.aclaw-ask-setbar {
  margin: 9px 0 0; padding-top: 8px; border-top: 1px dashed var(--ableclaw-border-soft, rgba(0,0,0,.1));
  font-size: 11px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  color: var(--ableclaw-text-muted, #9ca3af);
}
.aclaw-ask-setbar.is-complete { color: var(--ableclaw-accent, var(--accent)); }
.aclaw-ask-inputrow { display: flex; gap: 8px; }
.aclaw-ask-input {
  flex: 1; padding: 10px 12px; font: inherit; font-size: max(16px, 13.5px);
  border: 1.5px solid var(--ableclaw-table-border, rgba(0,0,0,.14));
  border-radius: 11px; background: transparent; color: inherit; min-height: 44px;
}
.aclaw-ask-submit {
  border: none; border-radius: 11px; padding: 10px 18px; font-weight: 700; font-size: 13px;
  background: var(--accent); color: var(--on-accent, #fff); cursor: pointer; min-height: 44px;
}
/* PRE-EXISTING AA FAIL, surfaced by the verdict row landing right beneath it: the
   --ableclaw-muted/#6b7280 pattern is mode-independent (the var is unset), so this
   line reads 3.58:1 on the dark card. Same one-token fix, same reason as the note. */
.aclaw-ask-answered { font-size: 13px; color: var(--text-muted, #6b7280); }
/* ── FREE-FORM VERDICT (the submit seam) — a typed answer is adjudicated by the
   server in ~1 s instead of by a ~40 s conversational turn, so the card needs a
   place to say so. Three honest states and no fourth: checking (bounded — the
   seam client aborts, so this can never become a permanent spinner), a verdict,
   or a degrade line. is-pending is the RULE 4 state: recorded, not judged.
   ⚠ NO BACKTICKS ANYWHERE IN THIS BLOCK — it is a template literal, so one
   backtick in a comment closes the CSS and the WHOLE bundle stops parsing
   (i.e. chat dies fleet-wide). node --check catches it; run it before push. */
.aclaw-ask-verdict {
  margin: 8px 0 0; display: flex; align-items: baseline; gap: 8px;
  font-size: 12.5px; line-height: 1.45; color: var(--ableclaw-muted, #4b5563);
}
.aclaw-ask-verdict b { font-weight: 700; letter-spacing: .01em; }
.aclaw-ask-verdict.is-checking { opacity: .72; }
.aclaw-ask-verdict.is-checking b::after {
  content: '…'; display: inline-block; animation: aclawAskDots 1.1s steps(4, end) infinite;
}
@keyframes aclawAskDots { 0% { opacity: .35; } 50% { opacity: 1; } 100% { opacity: .35; } }
.aclaw-ask-verdict.is-correct b { color: var(--success); }
.aclaw-ask-verdict.is-partial b { color: var(--warning); }
.aclaw-ask-verdict.is-incorrect b { color: var(--danger); }
.aclaw-ask-verdict.is-pending b, .aclaw-ask-verdict.is-degraded b { color: var(--text-muted); }
/* --text-muted, NOT the --ableclaw-muted/#6b7280 pattern the rest of this card uses:
   --ableclaw-muted is UNSET, so that pattern resolves to the hardcoded literal, which
   is mode-INDEPENDENT — 4.83:1 on the light card but 3.58:1 on the dark one, i.e. it
   fails AA in exactly the mode you were not looking at. Measured live on build.
   --text-muted is semantic and re-binds: 4.83 light / 5.62 dark. */
.aclaw-ask-verdict-note { color: var(--text-muted, #6b7280); }
@media (prefers-reduced-motion: reduce) {
  .aclaw-ask-verdict.is-checking b::after { animation: none; }
}
/* Answer pill — the honest transcript record of a click (not a fake bubble). */
.aclaw-message-bubble--answer { background: transparent !important; border: none !important; box-shadow: none !important; padding: 0 !important; }
.aclaw-answer-pill {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 6px 13px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  border: 1px solid var(--ableclaw-table-border, rgba(0,0,0,.14));
  color: var(--ableclaw-muted, #4b5563); background: var(--surface-card, #fff);
}
.aclaw-answer-pill--correct { border-color: color-mix(in srgb, var(--success) 45%, transparent); }
.aclaw-answer-pill--correct b { color: var(--success); }
.aclaw-answer-pill--incorrect { border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.aclaw-answer-pill--incorrect b { color: var(--danger); }

/* The [hidden] contract — our display: declarations above would beat the UA's
   [hidden]{display:none} (lower specificity), leaving "hidden" stage chrome
   visibly rendered (an empty armed pill, a stray Conversations toggle). */
.aclaw-rail[hidden], .aclaw-convs-toggle[hidden], .aclaw-pinslot[hidden],
.aclaw-armed[hidden], .aclaw-status[hidden], .aclaw-mic[hidden],
.aclaw-ledger[hidden] { display: none !important; }
/* ── HERO-SLOT-FLIP (council spec) — the wide column follows the persona. ──
   Study: the THREAD is the hero (Max tunnels on the lesson), the board is a
   fixed readout. Floor: the BOARD/dossier is the hero (the collector stares
   at it), the thread narrows to a coaching column. Driven by data-stage which
   the agent sets via <able-stage name>. */
able-claw[data-stage="study-hall"][data-mode="full"] > .aclaw-grid:has(.aclaw-artifact:not([hidden])) {
  grid-template-columns: var(--ableclaw-sidebar-width) 1fr 380px;   /* thread hero */
}
able-claw[data-stage="the-floor"][data-mode="full"] > .aclaw-grid:has(.aclaw-artifact:not([hidden])) {
  grid-template-columns: 320px minmax(380px, 0.9fr) 1.35fr;         /* dossier hero */
}

/* ── THE WORKSPACE (right pane) — one sticky head + one scroll, NO tabs
   (restructure spec). The route (rail), the board, and the reasoning drawer
   all co-scroll; the head holds the adaptive title + the stable fly-to meter. */
.aclaw-workspace-head {
  position: sticky; top: 0; z-index: 2; flex-shrink: 0;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px 10px 16px;
  border-bottom: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-artifact-bg, var(--ableclaw-bg));
}
.aclaw-ws-title {
  font-family: var(--font-display, inherit);
  font-size: 13px; font-weight: 700; letter-spacing: -0.01em;
  color: var(--ableclaw-fg, #1d1c17); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto;
}
.aclaw-ws-meter { flex: 1 1 auto; min-width: 0; }   /* stable reward fly-to target */
.aclaw-ws-head-actions { flex: 0 0 auto; display: flex; align-items: center; }
.aclaw-ws-head-actions .aclaw-artifact-close {
  border: none; background: transparent; cursor: pointer; color: inherit;
  padding: 6px 8px; min-height: 32px; border-radius: 8px; opacity: .6;
}
.aclaw-ws-head-actions .aclaw-artifact-close:hover { opacity: 1; background: var(--ableclaw-sidebar-hover-bg, rgba(127,127,127,.1)); }
.aclaw-workspace-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  padding: 12px;
}
.aclaw-ws-rail:empty, .aclaw-ws-board:empty { display: none; }
.aclaw-ws-rail, .aclaw-ws-board { display: flex; flex-direction: column; gap: 10px; }
/* Reasoning drawer — a co-scrolling <details> at the bottom, collapsed default. */
.aclaw-reasoning-drawer {
  margin-top: auto;   /* sink to the bottom of the scroll when content is short */
  border-top: 1px solid var(--ableclaw-border-soft);
  padding-top: 8px;
}
.aclaw-reasoning-summary {
  display: flex; align-items: center; gap: 7px; cursor: pointer;
  list-style: none; font-size: 12px; font-weight: 700;
  color: var(--ableclaw-text-muted, #6b7280); padding: 4px 2px;
  user-select: none;
}
.aclaw-reasoning-summary::-webkit-details-marker { display: none; }
.aclaw-reasoning-summary::before {
  content: "▸"; font-size: 10px; transition: transform .15s ease;
}
.aclaw-reasoning-drawer[open] .aclaw-reasoning-summary::before { transform: rotate(90deg); }
.aclaw-reasoning-summary i { color: var(--ableclaw-accent, #6366f1); }
.aclaw-reasoning-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  font-size: 10px; font-weight: 800; color: #fff; background: var(--ableclaw-accent, #6366f1);
}
.aclaw-reasoning-drawer .aclaw-timeline { padding: 8px 2px 4px; }

/* ⭐ Instant-reward chip — flies from a correct answer into the mastery meter. */
.aclaw-reward-chip {
  position: fixed; z-index: 900; pointer-events: none;
  padding: 4px 11px; border-radius: 999px;
  font-family: var(--font-mono, 'IBM Plex Mono', monospace);
  font-size: 14px; font-weight: 800; letter-spacing: .02em;
  color: #fff; background: #16a34a;
  box-shadow: 0 4px 14px rgba(22,163,74,.45);
  transform: translate(0,0);
}
@keyframes aclaw-board-reward { 0% { box-shadow: 0 0 0 0 rgba(22,163,74,.5); } 100% { box-shadow: 0 0 0 12px rgba(22,163,74,0); } }
.aclaw-board--reward { animation: aclaw-board-reward .7s ease-out 1; border-radius: 12px; }
@media (prefers-reduced-motion: reduce) { .aclaw-board--reward { animation: none; } }

/* Collector queue keyboard focus (j/k/↑/↓ + Enter, floor mode). */
.aclaw-chip--focus {
  outline: 2px solid var(--ableclaw-accent, #6366f1);
  outline-offset: 1px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--ableclaw-accent, #6366f1) 20%, transparent);
}

/* ═══ REALTIME VOICE — compact in-thread strip (the overlay is gone; z-700 freed) ═══ */
.aclaw-voice-strip {
  position: relative;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  min-height: 44px; padding: 4px 12px; margin: 0 0 6px;
  border: 1px solid var(--ableclaw-border, rgba(127,127,127,.2)); border-radius: 12px;
  background: var(--ableclaw-bubble-agent-bg, rgba(127,127,127,.06));
  font-size: 12.5px; color: var(--ableclaw-fg, #1d1c17);
}
/* State dot — the orb's pulse keyframes, recycled at strip scale. */
.aclaw-voice-strip-dot {
  width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
  background: radial-gradient(circle at 35% 30%, var(--ableclaw-accent, #6366f1), color-mix(in srgb, var(--ableclaw-accent,#6366f1) 55%, #000));
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--ableclaw-accent,#6366f1) 40%, transparent);
}
.aclaw-voice-strip[data-vstate="listening"] .aclaw-voice-strip-dot { animation: aclaw-voice-listen 1.6s ease-in-out infinite; }
.aclaw-voice-strip[data-vstate="speaking"]  .aclaw-voice-strip-dot { animation: aclaw-voice-speak 0.8s ease-in-out infinite; }
.aclaw-voice-strip[data-vstate="connecting"] .aclaw-voice-strip-dot,
.aclaw-voice-strip[data-vstate="reconnecting"] .aclaw-voice-strip-dot { animation: aclaw-voice-think 1s linear infinite; }
.aclaw-voice-strip[data-vstate="error"] .aclaw-voice-strip-dot { background: #dc2626; animation: none; }
@keyframes aclaw-voice-listen { 0%,100%{ box-shadow:0 0 0 0 color-mix(in srgb,var(--ableclaw-accent,#6366f1) 40%,transparent);} 50%{ box-shadow:0 0 0 6px color-mix(in srgb,var(--ableclaw-accent,#6366f1) 0%,transparent);} }
@keyframes aclaw-voice-speak { 0%,100%{ transform:scale(1);} 50%{ transform:scale(1.3);} }
@keyframes aclaw-voice-think { 0%{opacity:.5;} 50%{opacity:1;} 100%{opacity:.5;} }
.aclaw-voice-strip-state { font-weight: 600; white-space: nowrap; }
.aclaw-voice-strip-level { flex: 1 1 60px; max-width: 140px; height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--ableclaw-fg,#888) 12%, transparent); overflow: hidden; }
.aclaw-voice-strip-level-fill { display: block; height: 100%; width: 0%; border-radius: 999px; background: color-mix(in srgb, var(--ableclaw-fg,#888) 35%, transparent); transition: width 90ms linear, background 120ms; }
.aclaw-voice-strip-level[data-live="1"] .aclaw-voice-strip-level-fill { background: #16a34a; }
.aclaw-voice-strip-notice { flex: 1 1 auto; min-width: 0; font-size: 11.5px; color: #b45309; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aclaw-voice-strip button { font: inherit; cursor: pointer; }
.aclaw-voice-strip-start { padding: 6px 14px; border-radius: 999px; border: 1px solid transparent; background: var(--ableclaw-accent,#6366f1); color: var(--on-accent,#fff); font-weight: 700; font-size: 12px; }
.aclaw-voice-strip-mute, .aclaw-voice-strip-more { border: none; background: transparent; color: var(--ableclaw-muted,#6b7280); padding: 6px 8px; border-radius: 8px; min-width: 32px; min-height: 32px; }
.aclaw-voice-strip-mute.is-muted { color: #dc2626; }
.aclaw-voice-strip-end { padding: 5px 12px; border-radius: 999px; border: 1px solid var(--ableclaw-border, rgba(127,127,127,.3)); background: transparent; color: inherit; font-size: 12px; font-weight: 600; }
/* Voice options = an EXPANSION ROW inside the strip (flex-basis 100% wraps it
   to its own line) — the strip grows downward and the layout reflows; it never
   floats OVER the chat thread (the old absolute popover covered the working
   screen — Raul, 2026-07-04). */
.aclaw-voice-strip-pop {
  flex-basis: 100%; min-width: 0;
  padding: 8px 2px 6px; display: flex; align-items: center; gap: 10px;
  border-top: 1px dashed var(--ableclaw-border, rgba(127,127,127,.2));
}
.aclaw-voice-strip-pop .aclaw-voice-mic-select { flex: 1 1 auto; min-width: 0; max-width: 340px; }
.aclaw-voice-strip-poplabel { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ableclaw-text-muted,#6b7280); }
.aclaw-voice-mic-select { font: inherit; font-size: 12px; padding: 6px 10px; border-radius: 8px; border: 1px solid var(--ableclaw-border, rgba(127,127,127,.3)); background: var(--ableclaw-bg,#fff); color: inherit; }
.aclaw-voice-mic-select[data-attn="1"] { border-color: #d97706; box-shadow: 0 0 0 3px color-mix(in srgb, #d97706 22%, transparent); }
.aclaw-voice-strip-hint { font-size: 12px; line-height: 1.45; background: color-mix(in srgb, #d97706 12%, transparent); border: 1px solid color-mix(in srgb,#d97706 30%,transparent); border-radius: 8px; padding: 8px 10px; }
@media (prefers-reduced-motion: reduce) { .aclaw-voice-strip-dot { animation: none !important; } }
@media (prefers-reduced-motion: reduce) {
  .aclaw-stage-card--pulse, .aclaw-glance-panel, .aclaw-status-dot, .aclaw-mic--live { animation: none !important; }
}
/* ═════════════════════ END THE STAGE CSS ═════════════════════ */

.aclaw-table {
  width: 100%; border-collapse: collapse;
  margin: 10px 0;
  font-size: 13px;
  color: inherit;
}
.aclaw-table th, .aclaw-table td {
  padding: 6px 10px;
  border: 1px solid var(--ableclaw-table-border);
  text-align: left;
  color: inherit;
  background: var(--ableclaw-table-row-bg);
}
.aclaw-table th {
  background: var(--ableclaw-table-header-bg);
  color: var(--ableclaw-table-header-fg);
  font-weight: 600;
}
/* Raw enrichment tags are REPLACED by their rendered figure on mount. Hide the
   un-rendered tag until then so its inner spec/JSON never flashes as visible text
   mid-stream (an <able-diagram> whose JSON spec sits as inner content was leaking
   the raw JSON for a beat before the chart drew). Once the renderer swaps the tag
   for a <figure>/<div>, that element shows normally — this only hides the source tag. */
.aclaw-messages able-diagram, .claw-root able-diagram,
.aclaw-messages able-math, .claw-root able-math,
.aclaw-messages able-vocab, .claw-root able-vocab,
.aclaw-messages able-audio, .claw-root able-audio,
.aclaw-messages able-video, .claw-root able-video,
.aclaw-messages able-deck, .claw-root able-deck { display: none; }

/* Content images (lesson photos + inline <img> from agent/lesson HTML) — cap so
   a full-resolution portrait/landscape never dominates the column or bleeds past
   it (a 1280×1968 photo was rendering at natural size). Small chrome
   (avatars/logos) sits far under these caps, so it's unaffected. */
.aclaw-messages img, .claw-root img {
  max-width: 100%;
  max-height: min(52vh, 440px);
  height: auto;
  object-fit: contain;
}
/* Bare <th> / <td> emitted in dark contexts without an .aclaw-table wrapper
   (e.g. sanitized agent output that loses the class). Inherit color and
   apply a subtle tinted header so text is always readable on dark surfaces. */
.aclaw-messages table, .aclaw-artifact-body table {
  width: 100%; border-collapse: collapse;
  margin: 10px 0; font-size: 13px;
  color: inherit;
}
.aclaw-messages table th, .aclaw-artifact-body table th {
  background: var(--ableclaw-table-header-bg);
  color: var(--ableclaw-table-header-fg);
  font-weight: 600;
  padding: 6px 10px;
  border: 1px solid var(--ableclaw-table-border);
  text-align: left;
}
.aclaw-messages table td, .aclaw-artifact-body table td {
  background: var(--ableclaw-table-row-bg);
  color: inherit;
  padding: 6px 10px;
  border: 1px solid var(--ableclaw-table-border);
  text-align: left;
}

.aclaw-attachments {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 8px 16px 0 16px;
  background: var(--surface-subtle, rgba(0, 0, 0, 0.12));
}
.aclaw-attachments[hidden] { display: none !important; }
.aclaw-attachment {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 8px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.10));
  border-radius: 14px;
  font-size: 12px; line-height: 1.2;
  max-width: 240px;
}
.aclaw-attachment.is-loading { opacity: 0.7; }
.aclaw-attachment.is-error {
  border-color: #b91c1c;
  background: rgba(185, 28, 28, 0.12);
}
.aclaw-attachment-icon { font-size: 12px; opacity: 0.85; }
.aclaw-attachment-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 160px;
}
.aclaw-attachment-remove {
  background: transparent; color: inherit; border: 0;
  cursor: pointer; opacity: 0.6; font-size: 14px; line-height: 1;
  padding: 0 2px;
}
.aclaw-attachment-remove:hover { opacity: 1; }
.aclaw-attachment-retry {
  background: transparent; color: inherit; border: 0;
  cursor: pointer; opacity: 0.7; font-size: 11px; padding: 0 4px;
  text-decoration: underline;
}
.aclaw-attachment-retry:hover { opacity: 1; }

/* Bug #107 — image attachment chip becomes a real thumbnail card.
   Wraps tighter than the text-chip layout, lifts the filename to a
   bottom hover-only label, and gives the thumbnail click affordance. */
.aclaw-attachment.is-image {
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  border-color: var(--border-default, rgba(255, 255, 255, 0.18));
  position: relative;
  background: rgba(255, 255, 255, 0.03);
}
.aclaw-attachment-thumb {
  display: block;
  width: 56px; height: 56px;
  object-fit: cover;
  cursor: zoom-in;
  background: rgba(0, 0, 0, 0.15);
  transition: filter 120ms ease-out;
}
.aclaw-attachment-thumb:hover { filter: brightness(0.85); }
.aclaw-attachment.is-image .aclaw-attachment-name { display: none; }
.aclaw-attachment.is-image .aclaw-attachment-remove {
  position: absolute;
  top: 2px; right: 2px;
  width: 18px; height: 18px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border-radius: 50%;
  font-size: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  opacity: 0.9;
}
.aclaw-attachment.is-image .aclaw-attachment-remove:hover {
  background: rgba(220, 38, 38, 0.85);
}

/* Bug #108 — attachment block hanging below user message text. */
.aclaw-message-attachments {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-top: 6px;
}
.aclaw-message-attachment-thumb {
  display: block;
  width: 200px; max-width: 100%;
  max-height: 240px;
  object-fit: cover;
  border-radius: 10px;
  cursor: zoom-in;
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.08));
  background: rgba(0, 0, 0, 0.15);
  transition: filter 120ms ease-out;
}
.aclaw-message-attachment-thumb:hover { filter: brightness(0.92); }
.aclaw-message-attachment-file {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.10));
  border-radius: 14px;
  font-size: 13px; line-height: 1.2;
  max-width: 240px;
  color: inherit; text-decoration: none;
  transition: background 120ms;
}
.aclaw-message-attachment-file:hover {
  background: rgba(255, 255, 255, 0.10);
}
.aclaw-message-attachment-icon { font-size: 14px; opacity: 0.85; }
.aclaw-message-attachment-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 200px;
}

/* Bug #109 — full-screen image lightbox. Backdrop click + close button
   + Esc all dismiss. Uses fixed positioning to escape blueprint scroll. */
.aclaw-lightbox {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.85);
  z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  padding: 32px;
  cursor: zoom-out;
  animation: aclaw-lightbox-fade 140ms ease-out;
}
.aclaw-lightbox[hidden] { display: none !important; }
.aclaw-lightbox-img {
  max-width: 100%; max-height: calc(100vh - 120px);
  border-radius: 6px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
  cursor: default;
}
.aclaw-lightbox-close {
  position: absolute; top: 16px; right: 20px;
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 0;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  font-size: 22px; line-height: 1;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.aclaw-lightbox-close:hover { background: rgba(255, 255, 255, 0.30); }
.aclaw-lightbox-close:focus-visible {
  outline: 2px solid #fff; outline-offset: 2px;
}
.aclaw-lightbox-caption {
  position: absolute; bottom: 24px; left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.85);
  font-size: 13px;
  background: rgba(0, 0, 0, 0.45);
  padding: 6px 12px;
  border-radius: 12px;
  max-width: 60%;
  text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@keyframes aclaw-lightbox-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Bug #112 — drag-over visual cue. The dropzone is the .aclaw-chat
   container; we set data-dragging="true" on it during a drag with files. */
.aclaw-chat[data-dragging="true"]::after {
  content: "Drop file to attach";
  position: absolute; inset: 0;
  background: rgba(99, 102, 241, 0.18);
  border: 2px dashed var(--ableclaw-accent, #6366f1);
  border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ableclaw-accent, #6366f1);
  font-size: 16px; font-weight: 600;
  pointer-events: none;
  z-index: 1000;
}

.aclaw-input-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  border-top: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-input-bar-bg);
  flex-shrink: 0;
  box-sizing: border-box;
  /* Encapsulate the row in a soft pill — gives the input a modern
     "command bar" feel rather than the dated chat-form look. */
  border-radius: 18px;
  margin: 10px 16px 0;
  border-top: 0;
  border: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-input-bg);
  transition: border-color 120ms, box-shadow 120ms;
}
.aclaw-input-bar:focus-within {
  border-color: var(--ableclaw-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ableclaw-accent) 18%, transparent);
}
.aclaw-input-footer {
  /* Bug #93 — opacity 0.55 on 11px text was below WCAG AA. Raised to
     0.78 which puts contrast close to 4.5:1 against typical bg, and
     pin a deliberate color instead of inheriting near-black. */
  display: flex; align-items: center; justify-content: space-between;
  padding: 4px 16px 8px 16px;
  background: var(--ableclaw-input-bar-bg);
  font-size: 11px; opacity: 0.78;
  color: var(--ableclaw-text-muted, #475569);
  flex-shrink: 0;
  box-sizing: border-box;
  /* STABILITY: the footer + the live status verb must NEVER move the input.
     Fixed height + a centered ABSOLUTE status (below) so the composer above
     stays put no matter what the agent is doing. */
  position: relative;
  min-height: 26px;
}
/* The live status floats centered, out of flow — its text can change every
   second ("thinking…" → "checking the data…" → "done") without nudging the
   pinned "Read-only" text or the ⌘↩ hint, so the input never shifts. */
.aclaw-input-footer .aclaw-status {
  position: absolute; left: 50%; transform: translateX(-50%);
  max-width: 60%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aclaw-input-footer-shortcut {
  font-variant-numeric: tabular-nums;
}
.aclaw-upload {
  width: 32px; height: 32px; border-radius: 999px;
  background: transparent; color: inherit; border: 0;
  cursor: pointer; opacity: 0.55;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px;
  flex-shrink: 0;
  transition: opacity 120ms, background-color 120ms, transform 120ms;
}
.aclaw-upload:hover:not(:disabled) {
  opacity: 1;
  background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10));
}
.aclaw-upload:disabled { cursor: not-allowed; opacity: 0.4; }
.aclaw-upload i { font-size: 14px; line-height: 1; }
.aclaw-input {
  flex: 1;
  padding: 8px 4px;
  background: transparent; color: var(--ableclaw-input-fg);
  border: 0;
  border-radius: 0;
  font: inherit; font-size: 14px; line-height: 1.5;
  resize: none;
  min-height: 28px; max-height: 160px;
  min-width: 0;
  box-sizing: border-box;
}
.aclaw-input:focus {
  outline: none;
}
.aclaw-input::placeholder {
  opacity: 0.55;
}
.aclaw-send {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  background: var(--ableclaw-accent); color: var(--ableclaw-accent-fg);
  border: 0; border-radius: 999px; cursor: pointer;
  font-size: 13px; font-weight: 600;
  transition: opacity 120ms, transform 120ms, box-shadow 120ms;
  flex-shrink: 0;
}
.aclaw-send:hover:not(:disabled) {
  opacity: 0.95;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--ableclaw-accent) 30%, transparent);
}
.aclaw-send:active:not(:disabled) { transform: scale(0.97); }
.aclaw-send:disabled { opacity: 0.5; cursor: not-allowed; }
.aclaw-send i { font-size: 11px; }
.aclaw-stop {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  background: var(--ableclaw-stop-bg); color: var(--ableclaw-accent-fg);
  border: 0; border-radius: 999px; cursor: pointer;
  font-size: 13px; font-weight: 600; line-height: 1;
  transition: opacity 120ms, background-color 120ms;
  flex-shrink: 0;
}
.aclaw-stop:hover { opacity: 0.95; background: var(--ableclaw-stop-bg-hover); }
.aclaw-stop i { font-size: 11px; }
/* In-flight: hide Send, show Stop. */
.aclaw-input-bar--in-flight .aclaw-send { display: none; }
.aclaw-stop[hidden] { display: none !important; }
.aclaw-input-bar--in-flight .aclaw-stop { display: inline-flex; align-items: center; }

/* Drag-and-drop overlay — covers the chat surface with a soft frosted
   panel + drop-target card when files are being dragged in. Hidden by
   default; .aclaw-chat[data-dragging="true"] flips visibility. */
.aclaw-dropzone {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  opacity: 0;
  background: color-mix(in srgb, var(--ableclaw-bg) 70%, transparent);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 60;
  transition: opacity 140ms;
}
.aclaw-chat[data-dragging="true"] .aclaw-dropzone {
  opacity: 1;
  pointer-events: auto;
}
.aclaw-dropzone-card {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 32px 40px;
  border-radius: 18px;
  background: var(--ableclaw-bg);
  border: 2px dashed var(--ableclaw-accent);
  color: var(--ableclaw-fg);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
  pointer-events: none;
  text-align: center;
}
.aclaw-dropzone-icon {
  font-size: 36px;
  color: var(--ableclaw-accent);
  margin-bottom: 2px;
}
.aclaw-dropzone-title {
  font-size: 16px; font-weight: 700;
  letter-spacing: 0.01em;
}
.aclaw-dropzone-sub {
  font-size: 12px; opacity: 0.6;
  letter-spacing: 0.04em;
}

.aclaw-artifact {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  border-left: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-artifact-bg);
  color: var(--ableclaw-fg);
  overflow: hidden;
}
.aclaw-artifact[hidden] { display: none !important; }
.aclaw-artifact-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--ableclaw-border-soft);
  font-size: 13px; font-weight: 600;
  flex-shrink: 0;
}
.aclaw-artifact-type { opacity: 0.85; }
.aclaw-artifact-actions {
  display: inline-flex; align-items: center; gap: 4px;
}
.aclaw-artifact-close, .aclaw-artifact-clear {
  background: transparent; color: inherit; border: 0; cursor: pointer;
  font-size: 16px; line-height: 1; opacity: 0.7;
  padding: 2px 6px; border-radius: 4px;
  transition: opacity 120ms, background-color 120ms;
}
.aclaw-artifact-close:hover, .aclaw-artifact-clear:hover {
  opacity: 1; background: rgba(255, 255, 255, 0.06);
}
.aclaw-artifact-body {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 14px;
  font-size: 13px; line-height: 1.5;
}

/* Brand mark in the Agent Thinking header (purple rounded square w/ white
   brain icon). Matches legacy <askAble> visual where the brain logo sits
   next to the title. */
.aclaw-artifact-brand {
  width: 24px; height: 24px;
  border-radius: 6px;
  background: linear-gradient(135deg, #7c3aed 0%, #6366f1 100%);
  color: #ffffff;
  display: inline-flex; align-items: center; justify-content: center;
  margin-right: 8px;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(124, 58, 237, 0.25);
}
.aclaw-artifact-brand i { font-size: 12px; }
.aclaw-artifact-header > .aclaw-artifact-type {
  flex: 1; min-width: 0;
}

/* Subtle footer hint at the bottom of the panel — matches the legacy
   "Agent reasoning log" placeholder strip. */
.aclaw-artifact-footer {
  flex-shrink: 0;
  padding: 10px 14px;
  border-top: 1px solid var(--ableclaw-border-soft);
  font-size: 12px;
  color: var(--grey-500, #94a3b8);
  font-style: italic;
}

/* Brain TOGGLE button — always-visible floating control in the top-right
   of .aclaw-chat. Clicking it shows/hides the Agent Thinking panel.
   Closed state: white background with purple brain. Open state (host
   carries data-thinking-open): purple background with white brain.
   Matches the visual swap in legacy askAble image 1 -> image 2. */
.aclaw-thinking-toggle {
  position: absolute;
  top: 12px; right: 12px;
  z-index: 25;
  width: 36px; height: 36px;
  border-radius: 10px;
  border: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-bg, #ffffff);
  color: #7c3aed;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease,
              transform 120ms ease, box-shadow 160ms ease;
  box-shadow: 0 1px 3px rgba(15, 17, 23, 0.06);
}
/* Active-conversation copy chip — relocated OUT of the chat chrome
   (where it floated top-right and overlapped message content, always on)
   and INTO the sidebar header (the conversation-selection menu, below the
   search). It now appears ONLY when that menu is displayed — on desktop the
   sidebar is always present; on mobile the sidebar is a slide-in drawer, so
   the chip is hidden until the user opens conversation history. In normal
   flow, full-width, shown only when an active conversation exists (.hidden
   attr toggled via _setActiveConvChip). Click copies the full UUID; the
   visible id shows the first 8 chars so users can verify which conversation. */
.aclaw-active-conv-chip {
  margin-top: 2px;
  width: 100%;
  min-height: 30px;
  padding: 6px 10px;
  border-radius: 8px;
  border: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10));
  color: var(--ableclaw-sidebar-fg, var(--text-primary, #1e293b));
  display: flex; align-items: center; gap: 6px;
  font-size: 11px;
  font-family: var(--font-mono, ui-monospace, monospace);
  cursor: pointer;
  text-align: left;
  transition: background-color 160ms ease, transform 120ms ease,
              box-shadow 160ms ease, opacity 160ms ease;
  box-shadow: 0 1px 2px rgba(15, 17, 23, 0.04);
}
.aclaw-active-conv-chip[hidden] { display: none; }
.aclaw-active-conv-chip:hover {
  background: color-mix(in srgb, #7c3aed 8%, var(--ableclaw-bg, #ffffff));
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(124, 58, 237, 0.18);
}
.aclaw-active-conv-chip:active { transform: translateY(0); }
.aclaw-active-conv-chip.is-copied {
  color: var(--success, #16a34a);
  border-color: var(--success, #16a34a);
  background: color-mix(in srgb, var(--success, #16a34a) 10%, var(--ableclaw-bg, #ffffff));
}
.aclaw-active-conv-chip-label {
  /* Bug #93 — opacity 0.65 on 10px text dipped under WCAG AA.
     Raised to 0.85 and made the color deliberate. */
  opacity: 0.85;
  color: var(--ableclaw-text-muted, #475569);
  font-family: var(--font-sans, system-ui, sans-serif);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.aclaw-active-conv-chip-id { font-weight: 600; }
.aclaw-active-conv-chip-glyph { opacity: 0.6; font-size: 12px; margin-left: auto; }
.aclaw-thinking-toggle:hover {
  background: color-mix(in srgb, #7c3aed 8%, var(--ableclaw-bg, #ffffff));
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(124, 58, 237, 0.18);
}
.aclaw-thinking-toggle:active { transform: translateY(0); }
.aclaw-thinking-toggle i { font-size: 16px; }
able-claw[data-thinking-open="true"] .aclaw-thinking-toggle {
  background: linear-gradient(135deg, #7c3aed 0%, #6366f1 100%);
  color: #ffffff;
  border-color: transparent;
  box-shadow: 0 4px 12px rgba(124, 58, 237, 0.32);
}

/* Unread-activity dot — small accent on the brain button when tool / reasoning
   / lifecycle events have landed since the panel was last closed. Reset when
   the user opens the panel (see _openArtifactPane). The dot mirrors the
   notification-bell pattern used elsewhere in the platform. */
.aclaw-thinking-toggle { position: absolute; transition: transform 220ms cubic-bezier(0.22,1,0.36,1), opacity 220ms ease; }
/* While the stream is actively scrolling, the toggle tucks off the right edge
   so it never covers bubbles or steals taps mid-navigation; it returns at rest. */
able-claw[data-msgs-scrolling="true"] .aclaw-thinking-toggle {
  transform: translateX(calc(100% + 16px));
  opacity: 0.4;
  pointer-events: none;
}
.aclaw-thinking-toggle::after {
  content: '';
  position: absolute;
  top: 4px; right: 4px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #f59e0b;
  border: 2px solid var(--ableclaw-bg, #ffffff);
  opacity: 0;
  transform: scale(0.5);
  transition: opacity 160ms ease, transform 160ms ease;
}
able-claw[data-thinking-unread="true"] .aclaw-thinking-toggle::after {
  opacity: 1;
  transform: scale(1);
}
/* Hide the unread dot when the panel is open — opening clears the marker
   but this rule prevents a flash mid-transition. */
able-claw[data-thinking-open="true"] .aclaw-thinking-toggle::after {
  opacity: 0 !important;
}

/* When toggled OPEN in helper / launcher modes (where the artifact pane is
   normally hidden because the grid only has 1 column), surface the pane
   as a right-edge floating slide-in overlay. Full mode keeps the existing
   3-col grid layout — the pane is just an additional column there. */
able-claw[data-mode="helper"][data-thinking-open="true"] > .aclaw-grid > .aclaw-artifact,
able-claw[data-mode="launcher"][data-thinking-open="true"] > .aclaw-grid > .aclaw-artifact {
  display: flex !important;
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(360px, 92%);
  z-index: 30;
  border-left: 1px solid var(--ableclaw-border-soft);
  box-shadow: -8px 0 24px rgba(15, 17, 23, 0.18);
  background: var(--ableclaw-artifact-bg, var(--ableclaw-bg, #ffffff));
  animation: aclaw-thinking-slide-in 200ms ease-out;
}
@keyframes aclaw-thinking-slide-in {
  from { transform: translateX(8px); opacity: 0; }
  to   { transform: translateX(0);   opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MEMORIES panel — "what the agent remembers about me", per user.
   Reads GET /able-api/ai/memory with NO 'user' param: the bare list is self for
   every caller (admin included; see _loadMemories). The server auto-narrows a
   non-admin caller to their OWN rows off the validated JWT, so there is no
   client-side role logic anywhere in here. Agents WRITE memories; the user
   CURATES them — there is no create endpoint and deliberately no "Add" button.

   Mechanism mirrors the thinking panel: a host attribute (data-memories-open)
   + one CSS block reveals the pane in all three modes. The pane is its own
   absolutely-positioned element rather than a borrowed .aclaw-artifact, so it
   never fights _ensureWorkspace for that node's DOM — and because it is
   position:absolute it does NOT participate in the 3-track grid layout (no
   implicit 4th column).
   ═══════════════════════════════════════════════════════════════════════════ */

/* The gear — beside the brain in the chat-column cluster. The brain keeps
   right:12px (learned position, unchanged); the gear sits to its left.
   The FLOATING geometry is scoped to the chat-column copy: helper/launcher
   render a second copy inside .aclaw-helper-actions, which must stay an
   in-flow .aclaw-helper-action button. */
.aclaw-chat > .aclaw-memories-toggle {
  position: absolute;
  top: 12px; right: 56px;
  z-index: 25;
  width: 36px; height: 36px;
  border-radius: 10px;
  border: 1px solid var(--ableclaw-border-soft);
  background: var(--ableclaw-bg, #ffffff);
  color: #7c3aed;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease,
              transform 120ms ease, box-shadow 160ms ease, opacity 220ms ease;
  box-shadow: 0 1px 3px rgba(15, 17, 23, 0.06);
}
.aclaw-chat > .aclaw-memories-toggle:hover {
  background: color-mix(in srgb, #7c3aed 8%, var(--ableclaw-bg, #ffffff));
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(124, 58, 237, 0.18);
}
.aclaw-chat > .aclaw-memories-toggle:active { transform: translateY(0); }
.aclaw-chat > .aclaw-memories-toggle i { font-size: 15px; }
/* Open-state fill applies to BOTH copies so the feedback is identical in
   every mode (specificity 0,2,1 beats .aclaw-helper-action's 0,1,0). */
able-claw[data-memories-open="true"] .aclaw-memories-toggle {
  background: linear-gradient(135deg, #7c3aed 0%, #6366f1 100%);
  color: #ffffff;
  border-color: transparent;
  opacity: 1;
  box-shadow: 0 4px 12px rgba(124, 58, 237, 0.32);
}
/* Travels with the brain when the stream is scrolling (chat copy only). */
able-claw[data-msgs-scrolling="true"] .aclaw-chat > .aclaw-memories-toggle {
  transform: translateX(calc(100% + 60px));
  opacity: 0.4;
  pointer-events: none;
}
/* helper / launcher put the gear in the header action row instead (see
   _renderHelperHeaderHtml) — hide the floating one so there is exactly ONE
   gear per mode. The header copy carries the same class, so the delegated
   click handler serves both without re-wiring. */
able-claw[data-mode="helper"] .aclaw-chat > .aclaw-memories-toggle,
able-claw[data-mode="launcher"] .aclaw-chat > .aclaw-memories-toggle {
  display: none;
}

/* The pane. Absolute in EVERY mode (unlike the thinking pane, which is a 3rd
   grid column in full mode) — it is a transient curation surface, not a
   side-by-side reading surface, and staying absolute keeps the grid untouched. */
.aclaw-memories {
  display: none;
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(380px, 92%);
  z-index: 40;
  flex-direction: column;
  min-width: 0; min-height: 0;
  overflow: hidden;
  border-left: 1px solid var(--ableclaw-border-soft);
  box-shadow: -8px 0 24px rgba(15, 17, 23, 0.18);
  /* OPAQUE — the pane sits ON TOP of the chat, so it must fully cover the
     message stream behind it (--ableclaw-artifact-bg is translucent). */
  background: var(--ableclaw-bg, #ffffff);
  color: var(--ableclaw-fg);
}
able-claw[data-memories-open="true"] > .aclaw-grid > .aclaw-memories {
  display: flex;
  animation: aclaw-thinking-slide-in 200ms ease-out;
}

.aclaw-mem-header {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--ableclaw-border-soft);
  font-size: 13px; font-weight: 600;
  flex-shrink: 0;
}
.aclaw-mem-brand {
  width: 24px; height: 24px;
  border-radius: 6px;
  background: linear-gradient(135deg, #7c3aed 0%, #6366f1 100%);
  color: #ffffff;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(124, 58, 237, 0.25);
}
.aclaw-mem-brand i { font-size: 12px; }
.aclaw-mem-title { flex: 1; min-width: 0; }
.aclaw-mem-close {
  background: transparent; color: inherit; border: 0; cursor: pointer;
  font-size: 16px; line-height: 1; opacity: 0.7;
  min-width: 30px; min-height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 4px; border-radius: 6px;
  transition: opacity 120ms, background-color 120ms;
}
.aclaw-mem-close:hover {
  opacity: 1; background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10));
}

.aclaw-mem-search { padding: 10px 14px 0; flex-shrink: 0; }
.aclaw-mem-q {
  width: 100%; box-sizing: border-box;
  padding: 8px 10px;
  border-radius: var(--ableclaw-radius-sm, 8px);
  border: 1px solid var(--ableclaw-input-border);
  background: var(--ableclaw-input-bg);
  color: var(--ableclaw-input-fg);
  /* 16px floor — anything smaller makes iOS Safari zoom on focus. */
  font-size: max(16px, 13px);
  font-family: inherit;
}
.aclaw-mem-q:focus {
  outline: 2px solid var(--ableclaw-accent, #6366f1);
  outline-offset: 1px;
}

.aclaw-mem-body {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 8px;
  /* macOS overlay scrollbars take zero layout width and fade at rest, so a
     scrollable list shows NO affordance that more rows exist (visual review
     flagged it). Same treatment the conversation list already uses: a thin
     always-present thumb that darkens on hover. */
  scrollbar-width: thin;
  scrollbar-color: var(--ableclaw-scrollbar-thumb, rgba(120, 120, 130, 0.32)) transparent;
}
.aclaw-mem-body::-webkit-scrollbar { width: 8px; background: transparent; }
.aclaw-mem-body::-webkit-scrollbar-track { background: transparent; }
.aclaw-mem-body::-webkit-scrollbar-thumb {
  background: var(--ableclaw-scrollbar-thumb, rgba(120, 120, 130, 0.30));
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background-color 140ms ease;
}
.aclaw-mem-body::-webkit-scrollbar-thumb:hover {
  background: var(--ableclaw-scrollbar-thumb-active, rgba(120, 120, 130, 0.6));
  background-clip: padding-box;
}

/* One memory. The content is the elastic element; the chip + date are
   intrinsic-width and drop to caption scale so they never squeeze it. */
.aclaw-mem-row {
  border: 1px solid var(--ableclaw-border-soft);
  border-radius: var(--ableclaw-radius-sm, 8px);
  background: var(--ableclaw-bubble-agent-bg, rgba(127, 127, 127, 0.06));
  padding: 10px 12px;
  display: flex; flex-direction: column; gap: 6px;
}
.aclaw-mem-row-head {
  display: flex; align-items: center; gap: 8px;
  min-width: 0;
}
.aclaw-mem-chip {
  flex-shrink: 0;
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 999px;
  border: 1px solid transparent;
  background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.12));
  color: var(--ableclaw-text-muted, var(--text-secondary, #475569));
}
/* Per-type hues. The label is 10px uppercase — small text, so it owes 4.5:1
   against its own tint. A RAW brand hue only clears that on a light card
   (measured 2.51:1 for preference / 2.71:1 for fact on the dark card, and
   4.15:1 for fact even on the light one), so each hue is blended 50% toward
   the FOREGROUND: light-on-dark and deep-on-light from one declaration. */
.aclaw-mem-chip--preference {
  background: rgba(124, 58, 237, 0.16);
  color: color-mix(in srgb, #7c3aed 50%, var(--ableclaw-fg));
}
.aclaw-mem-chip--fact {
  background: rgba(37, 99, 235, 0.16);
  color: color-mix(in srgb, #2563eb 50%, var(--ableclaw-fg));
}
.aclaw-mem-chip--pattern {
  background: rgba(13, 148, 136, 0.16);
  color: color-mix(in srgb, #0d9488 50%, var(--ableclaw-fg));
}
.aclaw-mem-chip--insight {
  background: rgba(217, 119, 6, 0.18);
  color: color-mix(in srgb, #b45309 50%, var(--ableclaw-fg));
}
.aclaw-mem-chip--reflection {
  background: rgba(219, 39, 119, 0.16);
  color: color-mix(in srgb, #db2777 50%, var(--ableclaw-fg));
}
.aclaw-mem-date {
  flex: 1; min-width: 0;
  font-size: 11px;
  color: var(--ableclaw-text-muted, var(--text-secondary, #64748b));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Edit sits next to FORGET, which is destructive and has no undo. 2px between
   two 44px touch targets is a misclick waiting to happen, so the gap widens
   with the targets on coarse pointers (see the @media block below). */
.aclaw-mem-row-actions { display: inline-flex; gap: 4px; flex-shrink: 0; }
.aclaw-mem-act {
  background: transparent; color: inherit; border: 0; cursor: pointer;
  font-size: 12px; line-height: 1; opacity: 0.6;
  /* A comfortable desktop hit area — the glyph is 12px, so padding alone
     left a ~26x22 target. Coarse pointers get the 44px block further down. */
  min-width: 28px; min-height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 4px; border-radius: 6px;
  transition: opacity 120ms, background-color 120ms, color 120ms;
}
.aclaw-mem-act:hover {
  opacity: 1; background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.12));
}
.aclaw-mem-act--del:hover { color: var(--danger, #b91c1c); }

.aclaw-mem-content {
  margin: 0;
  font-size: 13px; line-height: 1.5;
  color: var(--ableclaw-fg);
  white-space: pre-wrap; word-break: break-word;
  /* Truncated to 3 lines; the row's expand button lifts the clamp. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.aclaw-mem-row.is-expanded .aclaw-mem-content {
  -webkit-line-clamp: unset; display: block; overflow: visible;
}
.aclaw-mem-more {
  align-self: flex-start;
  background: transparent; border: 0; cursor: pointer;
  padding: 2px 0;
  font-size: 11px; font-weight: 600;
  /* The raw accent is a mid-blue that sits too close to the pane background
     in dark themes (visual review flagged it). Blending it toward the
     FOREGROUND keeps the accent hue while guaranteeing contrast in BOTH
     modes — fg is light on dark and dark on light by definition. */
  color: color-mix(in srgb, var(--ableclaw-accent, #6366f1) 45%, var(--ableclaw-fg));
  text-decoration: underline;
  text-underline-offset: 2px;
}
.aclaw-mem-more:hover { color: var(--ableclaw-fg); }

/* Edit-in-place */
.aclaw-mem-edit-area {
  width: 100%; box-sizing: border-box;
  min-height: 76px; resize: vertical;
  padding: 8px 10px;
  border-radius: var(--ableclaw-radius-sm, 8px);
  border: 1px solid var(--ableclaw-input-border);
  background: var(--ableclaw-input-bg);
  color: var(--ableclaw-input-fg);
  font-size: max(16px, 13px); line-height: 1.5;
  font-family: inherit;
}
.aclaw-mem-edit-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.aclaw-mem-type {
  padding: 6px 8px;
  border-radius: var(--ableclaw-radius-sm, 8px);
  border: 1px solid var(--ableclaw-input-border);
  background: var(--ableclaw-input-bg);
  color: var(--ableclaw-input-fg);
  font-size: max(16px, 12px); font-family: inherit;
}
.aclaw-mem-btn {
  padding: 7px 12px;
  border-radius: var(--ableclaw-radius-sm, 8px);
  border: 1px solid var(--ableclaw-border-soft);
  background: transparent;
  color: var(--ableclaw-fg);
  font-size: 12px; font-weight: 600; font-family: inherit;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms, opacity 120ms;
}
.aclaw-mem-btn:hover { background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.12)); }
.aclaw-mem-btn[disabled] { opacity: 0.5; cursor: default; }
.aclaw-mem-btn--primary {
  background: var(--ableclaw-accent, #6366f1);
  border-color: transparent;
  color: var(--ableclaw-accent-fg, #ffffff);
}
.aclaw-mem-btn--primary:hover {
  background: color-mix(in srgb, var(--ableclaw-accent, #6366f1) 85%, #000);
}
.aclaw-mem-btn--danger {
  background: var(--danger, #b91c1c);
  border-color: transparent;
  color: var(--on-danger, #ffffff);
}
.aclaw-mem-btn--danger:hover {
  background: color-mix(in srgb, var(--danger, #b91c1c) 85%, #000);
}
.aclaw-mem-btn--ghost { margin-left: auto; }
.aclaw-mem-edit-actions { display: flex; align-items: center; gap: 8px; }
.aclaw-mem-error-inline {
  font-size: 11px;
  color: var(--danger, #b91c1c);
}

/* Delete confirm — replaces the row body in place. No undo, so it asks. */
.aclaw-mem-confirm {
  display: flex; flex-direction: column; gap: 8px;
}
.aclaw-mem-confirm-text { font-size: 13px; line-height: 1.45; }
.aclaw-mem-confirm-actions { display: flex; align-items: center; gap: 8px; }

/* Loading skeleton */
.aclaw-mem-skel {
  border: 1px solid var(--ableclaw-border-soft);
  border-radius: var(--ableclaw-radius-sm, 8px);
  padding: 10px 12px;
  display: flex; flex-direction: column; gap: 8px;
}
.aclaw-mem-skel-bar {
  height: 9px; border-radius: 4px;
  background: linear-gradient(90deg,
    var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10)) 25%,
    var(--ableclaw-border-soft) 37%,
    var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10)) 63%);
  background-size: 400% 100%;
  animation: aclaw-mem-shimmer 1.4s ease infinite;
}
.aclaw-mem-skel-bar.is-short { width: 45%; }
@keyframes aclaw-mem-shimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .aclaw-mem-skel-bar { animation: none; }
  able-claw[data-memories-open="true"] > .aclaw-grid > .aclaw-memories { animation: none; }
}

/* Empty / error states */
.aclaw-mem-state {
  margin: auto 0;
  padding: 22px 6px;
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.aclaw-mem-state-icon {
  font-size: 22px;
  color: var(--ableclaw-text-muted, var(--text-secondary, #94a3b8));
  opacity: 0.75;
}
.aclaw-mem-state-title { font-size: 13px; font-weight: 600; }
.aclaw-mem-state-sub {
  font-size: 12px; line-height: 1.5;
  color: var(--ableclaw-text-muted, var(--text-secondary, #64748b));
  max-width: 30ch;
}

.aclaw-mem-footer {
  flex-shrink: 0;
  /* The pane runs to the grid's bottom edge, so the footer owns the last
     line of clearance — plus the notch inset on iOS, where the grid's own
     safe-area padding does not reach an absolutely-positioned child. */
  padding: 11px 14px calc(13px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--ableclaw-border-soft);
  font-size: 11px; line-height: 1.4;
  color: var(--ableclaw-text-muted, var(--text-secondary, #64748b));
}

/* Tool-progress timeline (mounted by _appendToolEvent) */
.aclaw-timeline {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 100%; overflow-y: auto;
}
.aclaw-tool-row {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: 13px; line-height: 1.4;
}
.aclaw-tool-row::before {
  content: '';
  width: 8px; height: 8px; border-radius: 50%;
  margin-top: 5px;
  flex-shrink: 0;
}
.aclaw-tool-tool_call::before    { background: #3b82f6; }
.aclaw-tool-tool_result::before  { background: #10b981; }
.aclaw-tool-reasoning::before {
  background: transparent;
  border: 2px solid var(--grey-500, #94a3b8);
  width: 6px; height: 6px;
}
/* Lifecycle rows: neutral, slightly transparent. Subtle gradient dot so
   they read as "scaffolding" — visible but not competing with real tool
   events for attention. The subkind-driven arrow lives inside the body. */
.aclaw-tool-lifecycle::before {
  background: var(--grey-400, #cbd5e1);
  opacity: 0.7;
}
.aclaw-tool-lifecycle {
  color: var(--grey-600, #64748b);
  font-size: 12px;
  white-space: pre-wrap; word-break: break-word;
}
.aclaw-tool-lifecycle-arrow {
  display: inline-block;
  font-weight: 600;
  margin-right: 4px;
  color: var(--grey-700, #475569);
}
.aclaw-tool-name { font-weight: 600; }
.aclaw-tool-args, .aclaw-tool-result-content {
  color: var(--grey-700, #64748b);
  white-space: pre-wrap; word-break: break-word;
  max-width: 100%;
}
.aclaw-tool-reasoning {
  font-style: italic;
  color: var(--grey-600, #94a3b8);
  white-space: pre-wrap; word-break: break-word;
}
/* Per-row glyph + kind label — visual cue for "this row is a reasoning
   block / tool invocation / tool result". Mirrors the prod UX where each
   row in the Agent Thinking panel starts with an icon + short uppercase
   tag so users can scan the timeline at a glance. */
.aclaw-tool-glyph {
  display: inline-block;
  margin-right: 6px;
  font-size: 13px;
  line-height: 1;
  vertical-align: -1px;
  opacity: 0.85;
}
.aclaw-tool-kind-label {
  display: inline-block;
  margin-right: 8px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--grey-600, #94a3b8);
  vertical-align: 1px;
}
.aclaw-tool-time {
  font-size: 10px; opacity: 0.5;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  align-self: flex-start;
  margin-top: 3px;
  min-width: 36px; text-align: right;
}
.aclaw-tool-body {
  flex: 1; min-width: 0;
}

/* Per-tool latency badge (2026-05-20).
   Server tags tool_result with data-duration-ms; renderer adds a colored
   pill so the user can scan for slow rows at a glance.
   Tiers chosen to match the operator's mental model of "snappy / normal /
   slow / problematic" rather than absolute milliseconds. */
.aclaw-tool-duration {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  border-radius: 8px;
  font-weight: 600;
  vertical-align: 1px;
}
.aclaw-tool-duration--snappy      { background: rgba(34, 197, 94, 0.15);  color: #16a34a; }
.aclaw-tool-duration--normal      { background: rgba(234, 179, 8, 0.15);  color: #ca8a04; }
.aclaw-tool-duration--slow        { background: rgba(249, 115, 22, 0.18); color: #ea580c; }
.aclaw-tool-duration--problematic { background: rgba(220, 38, 38, 0.20);  color: #dc2626; }

/* Server waterfall (turn_trace) — the end-of-turn AgentTurnTrace rendered as
   compact rows: span name | ms (+% of turn) | detail (model/tokens/cache/ttft).
   The non-MCP telemetry surface for live testing. */
.aclaw-turn-trace { font-size: 11px; line-height: 1.5; }
.aclaw-trace-head { font-weight: 600; margin-bottom: 4px; }
.aclaw-trace-hint { font-weight: 400; opacity: 0.6; font-size: 10px; }
.aclaw-trace-row { display: flex; gap: 8px; align-items: baseline; padding: 1px 0; }
.aclaw-trace-row code { font-family: var(--font-mono, ui-monospace, Menlo, monospace); font-size: 10.5px; min-width: 150px; }
.aclaw-trace-ms { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.aclaw-trace-detail { opacity: 0.65; font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Recurring-failure warning row — surfaces inside the tool_result body
   when the SAME (tool, entity) pair has failed N>1 times in the turn.
   Operator-visible signal of broken accessor / missing MV / migration debt. */
.aclaw-tool-recurring {
  margin-top: 4px;
  padding: 4px 8px;
  font-size: 11px;
  font-weight: 500;
  background: rgba(220, 38, 38, 0.08);
  border-left: 3px solid #dc2626;
  border-radius: 0 4px 4px 0;
  color: #991b1b;
  line-height: 1.4;
}
.aclaw-tool-recurring code {
  font-family: var(--font-mono, ui-monospace, Menlo, monospace);
  font-size: 10px;
  padding: 0 4px;
  background: rgba(220, 38, 38, 0.10);
  border-radius: 3px;
}

/* End-of-turn summary box — closes the Thinking panel timeline with the
   wall-clock breakdown so the user can answer "why was this turn slow?"
   without inspecting individual rows. */
.aclaw-turn-summary {
  margin: 8px 0 4px 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--grey-50, #f8fafc);
  border: 1px solid var(--grey-200, #e2e8f0);
  font-size: 12px;
  line-height: 1.5;
}
.aclaw-turn-summary--error {
  border-color: #fca5a5;
  background: rgba(254, 226, 226, 0.4);
}
.aclaw-turn-summary-headline {
  font-size: 13px;
  margin-bottom: 4px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.aclaw-turn-summary-glyph { font-size: 14px; }
.aclaw-turn-summary-status {
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--grey-600, #64748b);
}
.aclaw-turn-summary--error .aclaw-turn-summary-status {
  color: #dc2626;
}
.aclaw-turn-summary-row {
  color: var(--grey-700, #475569);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.aclaw-turn-summary-row--waste {
  color: #b91c1c;
  font-weight: 500;
}
.aclaw-turn-summary-failed {
  color: #dc2626;
  font-weight: 500;
}
.aclaw-turn-summary-pct {
  color: #6b7280;
  font-weight: 400;
  font-size: 11px;
}
.aclaw-turn-summary-where {
  margin-bottom: 6px;
}
/* Section blocks — slowest calls, per-tool, failing entities */
.aclaw-turn-summary-section {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed rgba(15, 23, 42, 0.12);
}
.aclaw-turn-summary-section--action {
  background: rgba(220, 38, 38, 0.05);
  margin-left: -10px;
  margin-right: -10px;
  padding: 8px 10px 6px;
  border-radius: 4px;
  border-top: none;
}
.aclaw-turn-summary-section-title {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #6b7280;
  margin-bottom: 4px;
}
.aclaw-turn-summary-section--action .aclaw-turn-summary-section-title {
  color: #b91c1c;
}
/* Slowest-call row */
.aclaw-turn-summary-call {
  display: grid;
  grid-template-columns: 18px 50px 1fr auto;
  gap: 6px;
  align-items: baseline;
  padding: 2px 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
}
.aclaw-turn-summary-call-glyph { font-size: 12px; }
.aclaw-turn-summary-call-ms {
  font-weight: 600;
  color: #0f172a;
}
.aclaw-turn-summary-call-tool {
  color: #1e3a8a;
  overflow: hidden;
  text-overflow: ellipsis;
}
.aclaw-turn-summary-call-entity {
  color: #475569;
  font-style: italic;
}
.aclaw-turn-summary-call-err {
  color: #b91c1c;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.aclaw-turn-summary-call--error .aclaw-turn-summary-call-ms { color: #b91c1c; }
/* Per-tool row */
.aclaw-turn-summary-tool {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  align-items: baseline;
  padding: 2px 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.aclaw-turn-summary-tool-name {
  color: #1e3a8a;
  font-weight: 500;
}
.aclaw-turn-summary-tool-count { color: #6b7280; }
.aclaw-turn-summary-tool-failed { color: #dc2626; }
.aclaw-turn-summary-tool-ms {
  color: #0f172a;
  font-weight: 600;
}
/* Failing entity row */
.aclaw-turn-summary-entity {
  padding: 2px 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.aclaw-turn-summary-entity-name {
  color: #0f172a;
  font-weight: 600;
}
.aclaw-turn-summary-entity-count {
  color: #b91c1c;
  font-weight: 600;
}
.aclaw-turn-summary-entity-err {
  color: #b91c1c;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* LLM round-trip breakdown rows (v3) */
.aclaw-turn-summary-llm-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: baseline;
  padding: 2px 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.aclaw-turn-summary-llm-label {
  color: #475569;
}
.aclaw-turn-summary-llm-value {
  color: #0f172a;
  text-align: right;
}
.aclaw-turn-summary-llm-warn {
  color: #b91c1c;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-left: 6px;
}
/* Per-round-trip drill-down table (v4) */
.aclaw-turn-summary-rt-details {
  margin-top: 8px;
}
.aclaw-turn-summary-rt-summary {
  cursor: pointer;
  font-size: 11px;
  color: #1e3a8a;
  user-select: none;
  padding: 2px 0;
}
.aclaw-turn-summary-rt-summary:hover {
  color: #1d4ed8;
}
.aclaw-turn-summary-rt-table {
  margin-top: 6px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.aclaw-turn-summary-rt-head,
.aclaw-turn-summary-rt-row {
  display: grid;
  grid-template-columns: 26px 50px 50px 50px 36px 1fr;
  gap: 6px;
  padding: 2px 0;
  align-items: baseline;
}
.aclaw-turn-summary-rt-head {
  font-weight: 600;
  color: #6b7280;
  border-bottom: 1px solid rgba(15, 23, 42, 0.08);
  padding-bottom: 4px;
  margin-bottom: 2px;
}
.aclaw-turn-summary-rt-row { color: #475569; }
.aclaw-turn-summary-rt-idx { color: #6b7280; }
.aclaw-turn-summary-rt-ms  { color: #0f172a; font-weight: 600; }
.aclaw-turn-summary-rt-row--slow {
  background: rgba(245, 158, 11, 0.1);
  margin-left: -6px;
  margin-right: -6px;
  padding-left: 6px;
  padding-right: 6px;
  border-radius: 3px;
}
.aclaw-turn-summary-rt-row--slow .aclaw-turn-summary-rt-ms { color: #b45309; }
/* stop_reason badges */
.aclaw-turn-summary-rt-stop {
  display: inline-block;
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 4px;
  border-radius: 2px;
  line-height: 1.4;
}
.aclaw-turn-summary-rt-stop--end {
  background: rgba(34, 197, 94, 0.12);
  color: #15803d;
}
.aclaw-turn-summary-rt-stop--tool {
  background: rgba(59, 130, 246, 0.12);
  color: #1e40af;
}
.aclaw-turn-summary-rt-stop--truncated {
  background: rgba(220, 38, 38, 0.12);
  color: #b91c1c;
}
.aclaw-turn-summary-rt-stop--other {
  background: rgba(107, 114, 128, 0.12);
  color: #4b5563;
}
.aclaw-turn-summary-rt-stop-empty { color: #9ca3af; }

/* Dark-theme overrides for the end-of-turn summary box. The whole
   .aclaw-turn-summary-* family was authored in light-mode hex (slate labels,
   near-black values, dark-blue tool names, light-pink error surface, dark
   hairline borders) and none of it flips with the theme, so on the dark
   Thinking panel the labels + section headers render near-invisible. Re-color
   to dark-appropriate values. (Box bg/border already flip via var(--grey-*).) */
[data-theme="dark"] able-claw .aclaw-turn-summary-llm-label,
[data-theme="dark"] able-claw .aclaw-turn-summary-call-entity,
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-row { color: #cbd5e1; }
[data-theme="dark"] able-claw .aclaw-turn-summary-status,
[data-theme="dark"] able-claw .aclaw-turn-summary-section-title,
[data-theme="dark"] able-claw .aclaw-turn-summary-pct,
[data-theme="dark"] able-claw .aclaw-turn-summary-tool-count,
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-head,
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-idx,
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-stop-empty { color: #94a3b8; }
[data-theme="dark"] able-claw .aclaw-turn-summary-llm-value,
[data-theme="dark"] able-claw .aclaw-turn-summary-call-ms,
[data-theme="dark"] able-claw .aclaw-turn-summary-tool-ms,
[data-theme="dark"] able-claw .aclaw-turn-summary-entity-name,
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-ms { color: #f1f5f9; }
[data-theme="dark"] able-claw .aclaw-turn-summary-call-tool,
[data-theme="dark"] able-claw .aclaw-turn-summary-tool-name,
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-summary { color: #93c5fd; }
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-summary:hover { color: #bfdbfe; }
/* error / warning reds run a touch dark on the panel — lighten for contrast */
[data-theme="dark"] able-claw .aclaw-turn-summary-row--waste,
[data-theme="dark"] able-claw .aclaw-turn-summary-failed,
[data-theme="dark"] able-claw .aclaw-turn-summary-tool-failed,
[data-theme="dark"] able-claw .aclaw-turn-summary-call-err,
[data-theme="dark"] able-claw .aclaw-turn-summary-entity-count,
[data-theme="dark"] able-claw .aclaw-turn-summary-entity-err,
[data-theme="dark"] able-claw .aclaw-turn-summary-llm-warn,
[data-theme="dark"] able-claw .aclaw-turn-summary--error .aclaw-turn-summary-status,
[data-theme="dark"] able-claw .aclaw-turn-summary-section--action .aclaw-turn-summary-section-title { color: #fca5a5; }
/* hairline dividers + the error surface tint */
[data-theme="dark"] able-claw .aclaw-turn-summary-section { border-top-color: rgba(255, 255, 255, 0.12); }
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-head { border-bottom-color: rgba(255, 255, 255, 0.10); }
[data-theme="dark"] able-claw .aclaw-turn-summary--error {
  background: rgba(127, 29, 29, 0.22);
  border-color: rgba(248, 113, 113, 0.5);
}
/* per-round-trip stop badges — light text on their translucent tints */
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-stop--end       { color: #86efac; }
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-stop--tool      { color: #93c5fd; }
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-stop--truncated { color: #fca5a5; }
[data-theme="dark"] able-claw .aclaw-turn-summary-rt-stop--other     { color: #cbd5e1; }

/* Narrow viewports — sidebar becomes a slide-in DRAWER overlay (legacy
   askAble pattern: hamburger toggle reveals it). Chat takes the full
   width; tapping outside the drawer or the chevron toggles it closed.

   Sidebar is rendered as a fixed-position overlay sliding in from the
   left, with a translucent backdrop behind it. The collapse / expand
   buttons toggle the same data-sidebar-collapsed attribute on the host
   — keeping ONE source of truth for both desktop and mobile state. */
@media (max-width: 720px) {
  .aclaw-grid { grid-template-columns: 1fr !important; }
  .aclaw-grid:has(.aclaw-artifact:not([hidden])) { grid-template-columns: 1fr !important; }
  .aclaw-artifact { display: none; }

  /* Sidebar becomes a slide-in drawer, hidden by default, slides in when
     data-sidebar-collapsed="false" (the default attribute state at boot
     should be data-sidebar-collapsed="true" on mobile — the runtime now
     forces this on first paint when matchMedia(720px) matches). */
  .aclaw-sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: min(86vw, 320px);
    z-index: 200;
    border-right: 1px solid var(--ableclaw-border-soft);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
    transform: translateX(-100%);
    transition: transform 220ms cubic-bezier(0.32, 0.72, 0.32, 1);
    visibility: visible !important;
    pointer-events: auto !important;
    /* When data-sidebar-collapsed="false" on the host, slide IN */
  }
  able-claw:not([data-sidebar-collapsed="true"]) > .aclaw-grid > .aclaw-sidebar {
    transform: translateX(0);
  }
  /* Translucent backdrop behind the drawer — taps dismiss the drawer.
     Rendered as a ::before on the chat column so we don't need new DOM. */
  able-claw:not([data-sidebar-collapsed="true"]) .aclaw-chat::before {
    content: '';
    position: fixed;
    inset: 0;
    background: oklch(0% 0 0 / 0.40);
    z-index: 150;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    animation: aclaw-fade-in 200ms ease;
  }
  @keyframes aclaw-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* Expand chevron — hamburger affordance at top-left.
     Reduced size (32px) and bumped close to the corner so it doesn't
     compete with content. Content (welcome, messages) gets padding-top
     to clear it. The text content uses a proper "bars" icon set via
     JS (data-mobile-bars="true" on this element) — falls back to "›"
     if FA didn't load yet. */
  .aclaw-sidebar-expand {
    display: inline-flex !important;
    top: 8px; left: 8px;
    width: 32px; height: 32px;
    font-size: 14px;
    z-index: 100;
  }
  /* Fade-out strip at the top of the chat — content fades into the
     hamburger area instead of getting clipped/half-overlapping. Uses
     the design-file pattern (linear gradient + backdrop-filter blur).
     Z-index 50 sits above messages (which default to 1) but below
     the hamburger (z-index 100). pointer-events:none lets taps go
     through to scroll/select. */
  .aclaw-chat::after {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 48px;
    background: linear-gradient(
      to bottom,
      var(--lg-wp-1) 30%,
      color-mix(in oklch, var(--lg-wp-1) 60%, transparent) 70%,
      transparent 100%
    );
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: 50;
    pointer-events: none;
    /* Mask matches the fade so the blur transitions out cleanly */
    mask-image: linear-gradient(to bottom, black 50%, transparent);
    -webkit-mask-image: linear-gradient(to bottom, black 50%, transparent);
  }

  /* Welcome screen — tighter padding + smaller avatar + smaller headlines.
     The padding-top clears the hamburger (top:8 + 44px tap-target = 52px
     bottom) so the agent brief isn't hidden underneath. !important beats the
     Liquid-Glass able-claw .aclaw-welcome padding:32px rule (0,1,1) that
     appears later in source and would otherwise win on specificity.
     (No backticks in this CSS string — they close the JS template literal.) */
  .aclaw-welcome { padding: 60px 14px 14px !important; gap: 8px; }
  .aclaw-welcome-icon { width: 56px !important; height: 56px !important; }
  .aclaw-welcome-icon svg { width: 26px !important; height: 26px !important; }
  .aclaw-welcome-headline-h1 { font-size: 22px !important; }
  .aclaw-welcome-subtitle { font-size: 13px !important; line-height: 1.4; }
  .aclaw-welcome-categories {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
    margin-top: 8px;
  }
  /* Welcome shortcut cards: horizontal layout (icon-side-text instead of
     icon-above-text) saves vertical space on phone */
  .aclaw-welcome-category-items .aclaw-shortcut {
    flex-direction: row !important;
    align-items: center !important;
    padding: 10px 12px !important;
    gap: 10px !important;
    min-height: 0;
  }
  .aclaw-welcome-category-items .aclaw-shortcut .aclaw-shortcut-icon {
    width: 28px !important; height: 28px !important;
  }
  .aclaw-welcome-category-items .aclaw-shortcut .aclaw-shortcut-text {
    font-size: 13px !important;
  }
  /* Category header smaller on mobile */
  .aclaw-welcome-category-header { font-size: 10px !important; padding: 2px 0 6px !important; }
  .aclaw-welcome-category-icon { width: 20px !important; height: 20px !important; font-size: 11px; }

  /* Main chat — tighter padding + larger bubbles, smaller divider.
     padding-top clears the hamburger (52px bottom) so neither the first
     message NOR the agent greeting (the ONLINE status row, bug #6) renders
     underneath / "mixed with" the conversation-history menu button. */
  .aclaw-messages { padding: 60px 14px 12px !important; }
  .aclaw-message-bubble { max-width: 90%; padding: 9px 13px; font-size: 14px; }
  .aclaw-channel-divider { margin: 12px 0 8px; gap: 10px; }
  .aclaw-channel-divider-pill { padding: 2px 8px; font-size: 9px; }

  /* Input bar — edge-to-edge pill, smaller padding, hide footer shortcut hint */
  .aclaw-input-bar {
    margin: 8px 10px 0;
    padding: 8px 10px;
    border-radius: 16px;
  }
  .aclaw-input-footer { padding: 4px 12px 6px 12px; font-size: 10px; }
  .aclaw-input-footer-shortcut { display: none; }
  .aclaw-upload { width: 30px; height: 30px; }
  .aclaw-send { padding: 6px 12px; font-size: 12px; }
  .aclaw-send span { display: none; } /* show icon only on mobile to save room */
  .aclaw-stop span { display: none; }

  /* Drop zone — smaller card on mobile so it fits viewport */
  .aclaw-dropzone-card { padding: 24px 28px; }
  .aclaw-dropzone-icon { font-size: 28px; }
  .aclaw-dropzone-title { font-size: 14px; }
  .aclaw-dropzone-sub { font-size: 11px; }

  /* iOS anti-zoom — textarea below 16px triggers iPhone auto-zoom on focus.
     The base .aclaw-input is 14px and the Liquid-Glass override pins it to
     15px (able-claw .aclaw-input) — BOTH zoom-trigger. Re-pin to 16px with
     the able-claw prefix so we out-specify the Liquid-Glass rule and keep
     iOS at 1.0x while the user types. */
  /* The .aclaw-input-bar qualifier raises specificity to (0,2,1) so this
     beats the Liquid-Glass able-claw-.aclaw-input font-size:15px rule
     (0,1,1) that appears LATER in source: a bare able-claw .aclaw-input
     selector here would tie and lose on source order.
     NOTE: never put backticks in this CSS string — it lives inside a JS
     template literal and a stray backtick closes it, breaking the bundle. */
  able-claw .aclaw-input-bar .aclaw-input { font-size: 16px; }
  /* Bug-#2 — the typed text must stay 16px (anti-zoom) but the PLACEHOLDER
     ("Ask about a customer, proposal, or cat-class…") is too wide for the
     narrow mobile input and wraps to a clipped 2nd line. Shrinking ONLY the
     placeholder font keeps the typed text at 16px (no zoom) while letting
     the hint fit. ::placeholder font-size is independent of the input's. */
  able-claw .aclaw-input-bar .aclaw-input::placeholder { font-size: 10px; }

  /* Bug #5 — Agent Thinking panel on mobile in FULL mode.
     At <=720px the grid collapses to 1fr and .aclaw-artifact is display:none
     (above), so clicking the brain toggle (which DOES set data-thinking-open)
     produced no visible panel — the helper/launcher slide-in overlay rule
     only targets those two modes. Surface the artifact as a right-edge
     slide-in overlay in full mode too, sized to fit the phone and stacked
     above the sidebar drawer (z 200) + backdrop (z 150). The panel's own
     header X (.aclaw-artifact-close) is the close affordance since the
     overlay covers the brain toggle. */
  able-claw[data-mode="full"][data-thinking-open="true"] > .aclaw-grid > .aclaw-artifact {
    display: flex !important;
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: min(440px, 100%);
    z-index: 210;
    border-left: 1px solid var(--ableclaw-border-soft);
    box-shadow: -8px 0 28px rgba(15, 17, 23, 0.32);
    /* OPAQUE background — the panel sits ON TOP of the chat, so it must fully
       cover the greeting + message stream behind it. --ableclaw-artifact-bg is
       a translucent frosted material (correct as a 3rd grid COLUMN, but it
       bleeds the chat through when used as an overlay). --ableclaw-bg resolves
       to the solid wallpaper (--lg-wp-1) in both light + dark. */
    background: var(--ableclaw-bg, #141415);
    animation: aclaw-thinking-slide-in 200ms ease-out;
  }
  /* When that overlay is open it fully covers the brain toggle (top-right),
     so hide the toggle to avoid it sitting behind / peeking around the panel.
     The panel's own header X is the close affordance. Mobile full-mode only —
     on desktop the panel is a 3rd grid column and the brain stays a real
     toggle. */
  able-claw[data-mode="full"][data-thinking-open="true"] .aclaw-thinking-toggle {
    display: none;
  }

  /* Memories pane on mobile — full width, and stacked ABOVE the sidebar
     drawer (z 200) + its backdrop (z 150), same as the thinking overlay
     (z 210). Its own header X is the close affordance, so the gear hides
     while it is open (it would sit behind the pane otherwise). */
  able-claw[data-memories-open="true"] > .aclaw-grid > .aclaw-memories {
    width: min(440px, 100%);
    z-index: 214;
    box-shadow: -8px 0 28px rgba(15, 17, 23, 0.32);
  }
  able-claw[data-memories-open="true"] .aclaw-memories-toggle {
    display: none;
  }

  /* Safe-area inset — iPhone notch / home indicator clearance.
     env(safe-area-inset-bottom) resolves to non-zero ONLY on iOS notched
     devices (and Android edge-to-edge in PWA mode); 0px everywhere else,
     so this is a no-op on desktop / non-notched phones. Applied to the
     grid so the input bar doesn't sit under the home indicator. */
  able-claw[mode="full"] > .aclaw-grid,
  able-claw[data-mode="full"] > .aclaw-grid {
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
}

/* ── LIFELINE: the scroll column can NEVER break, whatever a host page does ──
   The internal layout uses percentage heights (grid height:100% → chat
   height:100% → minmax(0,1fr) message row). A percentage chain silently
   fails if any ancestor's height isn't "definite" — e.g. a host page sets
   .home-claw{height:100%} against a percentage-height parent. When it fails,
   the chat balloons to CONTENT height, shoving the composer below the fold
   and killing the message scrollbar.
   Defense: in full mode, give the grid a DEFINITE dvh height directly (not a
   percentage), so it — and everything under it — always resolves regardless
   of the host. --ableclaw-viewport-offset lets a page with chrome above the
   claw shrink it. This is a hard invariant; do not weaken it. */
able-claw[data-mode="full"] > .aclaw-grid,
able-claw[mode="full"] > .aclaw-grid {
  height: calc(100dvh - var(--ableclaw-viewport-offset, 0px));
  max-height: calc(100dvh - var(--ableclaw-viewport-offset, 0px));
}
/* And a belt-and-suspenders clamp on the chat column itself: even in helper/
   launcher modes it must never exceed its grid cell, so the message row keeps
   a bounded height and scrolls. */
.aclaw-chat { max-height: 100%; }

/* Very narrow viewports (<= 380px) — push to absolute minimal */
@media (max-width: 380px) {
  .aclaw-message-bubble { max-width: 92%; padding: 8px 11px; font-size: 13px; }
  .aclaw-input-bar { margin: 6px 6px 0; padding: 6px 8px; }
  .aclaw-messages { padding: 10px 10px; }
  .aclaw-welcome-headline-h1 { font-size: 20px; }
  .aclaw-channel-divider { margin: 10px 0 8px; }
}

/* Touch / coarse-pointer devices — iOS HIG + Android Material 44x44 minimum
   tap target on EVERY interactive chrome button. Desktop (fine pointer)
   stays dense; phones/tablets get the proper hit area. */
@media (pointer: coarse) {
  .aclaw-new-chat,
  .aclaw-sidebar-collapse,
  .aclaw-sidebar-expand,
  .aclaw-thinking-toggle,
  .aclaw-memories-toggle,
  .aclaw-mem-close,
  .aclaw-mem-act,
  .aclaw-mem-btn,
  .aclaw-active-conv-chip,
  .aclaw-send,
  .aclaw-stop,
  .aclaw-upload-btn,
  .aclaw-message-bubble .claw-chip,
  .aclaw-shortcut {
    min-width: 44px;
    min-height: 44px;
  }
  /* Shortcut cards already have ample padding — only enforce min-height. */
  .aclaw-shortcut { min-height: 56px; }
  /* The gear clears the brain's 44px hit area on touch (brain right:12 +
     44 wide → the gear starts at 60). */
  .aclaw-chat > .aclaw-memories-toggle { right: 64px; }
  /* Row actions are inline icon buttons — center their glyphs in the
     enlarged box rather than letting padding push the row taller. */
  .aclaw-mem-act, .aclaw-mem-close {
    display: inline-flex; align-items: center; justify-content: center;
  }
  /* Separate edit from FORGET once both are 44px wide — a 2px gap between a
     benign and a destructive target invites the wrong tap. */
  .aclaw-mem-row-actions { gap: 10px; }
  /* Chip buttons are inline; bump padding so 44px height is reached without
     forcing block layout. */
  .aclaw-message-bubble .claw-chip {
    padding-top: 11px;
    padding-bottom: 11px;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * HELPER MODE — <able-claw mode="helper">
 *
 * Embeds the chat as a compact sidebar/drawer inside admin pages.
 * Hides the conversation list + artifact pane (single chat column),
 * renders tool events INLINE in the message stream (instead of pushing
 * them to the artifact pane), and adds a compact agent header at the
 * top of the chat column with a "+ new chat" button.
 *
 * Host pages mount it like a right-rail and drive context + prompts via
 * the public API (setContext, sendPrompt, newConversation, focus).
 * ═══════════════════════════════════════════════════════════════════════ */

able-claw[data-mode="helper"] > .aclaw-grid {
  grid-template-columns: 1fr;
}
able-claw[data-mode="helper"] > .aclaw-grid > .aclaw-sidebar,
able-claw[data-mode="helper"] > .aclaw-grid > .aclaw-artifact {
  display: none;
}
able-claw[data-mode="helper"] .aclaw-chat {
  /* Re-arrange the row track: helper-header (auto) + stream (1fr) + attachments + input + footer */
  grid-template-rows: auto minmax(0, 1fr) auto auto auto;
  grid-template-areas:
    "helper"
    "stream"
    "attachments"
    "input"
    "footer";
}
able-claw[data-mode="helper"] .aclaw-helper-header {
  grid-area: helper;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--ableclaw-border-soft);
}
able-claw[data-mode="full"] .aclaw-helper-header,
able-claw:not([data-mode="helper"]) .aclaw-helper-header {
  display: none;
}
.aclaw-helper-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--ableclaw-accent); color: var(--ableclaw-accent-fg);
  font-weight: 700; font-size: 13px;
  flex-shrink: 0;
}
.aclaw-helper-meta {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.aclaw-helper-name {
  font-size: 13px; font-weight: 700; letter-spacing: 0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aclaw-helper-sub {
  font-size: 11px; opacity: 0.60;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aclaw-helper-actions {
  display: inline-flex; align-items: center; gap: 4px;
  flex-shrink: 0;
}
.aclaw-helper-action {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 999px;
  background: transparent; color: inherit; border: 0;
  cursor: pointer; opacity: 0.65;
  transition: opacity 120ms, background-color 120ms;
}
.aclaw-helper-action:hover {
  opacity: 1;
  background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10));
}
.aclaw-helper-action i { font-size: 12px; }

/* In helper mode, hide the big welcome screen — agent's greeting bubble
   replaces it (see _renderGreetingHtml). Conversation list is also hidden;
   the sidebar-expand chevron stays hidden since there's no sidebar to
   reopen. */
able-claw[data-mode="helper"] .aclaw-welcome { display: none !important; }
able-claw[data-mode="helper"] .aclaw-sidebar-expand { display: none !important; }
able-claw[data-mode="helper"] .aclaw-messages {
  padding: 14px 16px 8px;
}
able-claw[data-mode="helper"] .aclaw-input-bar {
  margin: 0 12px 8px;
}

/* Inline tool-call bubble — renders in the message stream when in helper
   mode. Looks like an editor diff: arrow + function name + monospace
   args. Distinct from the assistant chat bubble (no background tint,
   monospace font, condensed). */
.aclaw-message-tool {
  align-self: flex-start;
  max-width: 92%;
  padding: 6px 12px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--ableclaw-accent) 8%, transparent);
  color: var(--text-muted, var(--ableclaw-fg));
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12px; line-height: 1.5;
  word-wrap: break-word;
  overflow-wrap: break-word;
}
.aclaw-message-tool-head {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 600;
  color: var(--ableclaw-accent);
}
.aclaw-message-tool-head::before {
  content: '→';
  opacity: 0.7;
}
.aclaw-message-tool-args {
  color: inherit;
  word-break: break-all;
}
.aclaw-message-tool-result {
  margin-top: 4px;
  opacity: 0.65;
  font-style: italic;
}
.aclaw-message-reasoning {
  align-self: flex-start;
  max-width: 92%;
  padding: 4px 10px;
  font-size: 11px;
  font-style: italic;
  opacity: 0.55;
  color: var(--ableclaw-fg);
}

/* ═══════════════════════════════════════════════════════════════════════════
 * LAUNCHER MODE — <able-claw mode="launcher">
 *
 * Floating bottom-right pill (collapsed) that expands into a chat panel
 * (~380x580 by default) on click. The pill renders the agent's display
 * name + online dot; the expanded panel uses helper-mode internals
 * (compact header, single column, inline tool calls).
 *
 * Position knobs (override via CSS on host page if needed):
 *   --ableclaw-launcher-bottom: 20px;
 *   --ableclaw-launcher-right:  20px;
 *   --ableclaw-launcher-width:  380px;
 *   --ableclaw-launcher-height: 580px;
 * ═══════════════════════════════════════════════════════════════════════ */

able-claw[data-mode="launcher"] {
  --ableclaw-launcher-bottom: 20px;
  --ableclaw-launcher-right:  20px;
  --ableclaw-launcher-width:  380px;
  --ableclaw-launcher-height: 580px;
  /* Override the page-clamping height knob — launcher floats freely. */
  height: auto !important;
  min-height: 0 !important;
  /* The host element itself is invisible — only the FAB + panel render. */
  display: contents;
}

/* Floating pill (collapsed state) — always rendered, click-to-toggle.
   Colors are HARDCODED dark-on-white (intentional brand identity for the
   floating helper — Intercom/Drift style) so the pill stays legible
   regardless of the host tenant's theme. Themes that need a different
   pill color can override via --ableclaw-launcher-pill-bg / -text on
   the able-claw element. */
/* The floating launcher pill is for launcher mode (a FAB that opens the chat).
   On a full-page claw you're already IN the chat — it's redundant chrome. */
able-claw[data-mode="full"] .aclaw-launcher-pill,
able-claw[mode="full"] .aclaw-launcher-pill { display: none !important; }
/* A page can mount BOTH a full claw AND a shell launcher claw (the floating
   "Lucrux" FAB). When a full claw is present, the launcher FAB is redundant —
   hide the whole launcher-mode claw. :has() so it's global regardless of which
   instance's <style> this is. */
body:has(able-claw[data-mode="full"]) able-claw[data-mode="launcher"],
body:has(able-claw[mode="full"])      able-claw[mode="launcher"] { display: none !important; }
/* The footer strip ("Read-only · … · ⌘↩ to send") is low-value chrome that
   pushes the composer up. On a full-page claw, reclaim the space — the send
   button + streaming bubble already signal state, reasoning is a dock tab. */
able-claw[data-mode="full"] .aclaw-input-footer,
able-claw[mode="full"] .aclaw-input-footer { display: none !important; }
.aclaw-launcher-pill {
  position: fixed;
  bottom: var(--ableclaw-launcher-bottom, 20px);
  right:  var(--ableclaw-launcher-right, 20px);
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--ableclaw-launcher-pill-bg, #1a2236);
  color: var(--ableclaw-launcher-pill-text, #f8fafc);
  border: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.12);
  z-index: 9000;
  transition: transform 140ms, box-shadow 140ms, opacity 140ms;
}
.aclaw-launcher-pill:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.22), 0 3px 8px rgba(0, 0, 0, 0.14);
}
.aclaw-launcher-pill:active { transform: translateY(0); }
.aclaw-launcher-pill-icon {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ableclaw-accent, #f59e0b);
  font-size: 14px;
}
.aclaw-launcher-pill-text {
  white-space: nowrap;
}
.aclaw-launcher-pill-status {
  display: inline-block;
  width: 8px; height: 8px; border-radius: 50%;
  background: #10b981;
  box-shadow: 0 0 0 2px color-mix(in srgb, #10b981 30%, transparent);
  flex-shrink: 0;
}

/* Hide the grid (the chat surface) when launcher is collapsed; show it
   inside a fixed panel when expanded. */
able-claw[data-mode="launcher"] > .aclaw-grid {
  position: fixed;
  bottom: calc(var(--ableclaw-launcher-bottom, 20px) + 60px);
  right:  var(--ableclaw-launcher-right, 20px);
  width:  var(--ableclaw-launcher-width, 380px);
  height: var(--ableclaw-launcher-height, 580px);
  max-height: calc(100dvh - 100px);
  max-width:  calc(100vw - 40px);
  border-radius: 16px;
  border: 1px solid var(--ableclaw-border, rgba(127, 127, 127, 0.20));
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.25), 0 8px 20px rgba(0, 0, 0, 0.15);
  background: var(--ableclaw-bg);
  z-index: 8999;
  transform-origin: bottom right;
  transition: opacity 160ms, transform 160ms;
}
able-claw[data-mode="launcher"][data-launcher-open="false"] > .aclaw-grid {
  opacity: 0;
  transform: scale(0.92) translateY(8px);
  pointer-events: none;
}
able-claw[data-mode="launcher"][data-launcher-open="true"] > .aclaw-grid {
  opacity: 1;
  transform: scale(1) translateY(0);
}
/* PRE-HYDRATION GUARD — launcher mode.
 *
 * The host element is in the DOM as <able-claw mode="launcher"> before
 * able-claw.js hydrates. data-mode + data-launcher-open are added by JS
 * in connectedCallback. Without this rule, the .aclaw-grid would paint
 * in-flow (no fixed-position rule yet), then JS adds data-mode → panel
 * jumps to fixed-position visible, then data-launcher-open="false" →
 * 160ms opacity+scale transition kicks in and the user sees a flash of
 * "open then collapse" on every page reload.
 *
 * Matches the HTML attribute mode="launcher" (always present from the
 * source) AND the absence of data-launcher-open (added post-hydration).
 * Forces the closed state without a transition so first paint is silent.
 * After hydration, data-launcher-open exists and this rule stops matching;
 * the standard open/close rules above resume control.
 */
able-claw[mode="launcher"]:not([data-launcher-open]) > .aclaw-grid {
  opacity: 0 !important;
  pointer-events: none !important;
  transition: none !important;
}
/* In launcher mode the chat surface is always single-column (helper-like) */
able-claw[data-mode="launcher"] > .aclaw-grid {
  grid-template-columns: 1fr;
}
able-claw[data-mode="launcher"] > .aclaw-grid > .aclaw-sidebar,
able-claw[data-mode="launcher"] > .aclaw-grid > .aclaw-artifact {
  display: none;
}
able-claw[data-mode="launcher"] .aclaw-chat {
  grid-template-rows: auto minmax(0, 1fr) auto auto auto;
  grid-template-areas:
    "helper"
    "stream"
    "attachments"
    "input"
    "footer";
}
able-claw[data-mode="launcher"] .aclaw-welcome {
  display: none !important;
}
able-claw[data-mode="launcher"] .aclaw-input-bar {
  margin: 0 12px 8px;
}
able-claw[data-mode="launcher"] .aclaw-messages {
  padding: 12px 16px 8px;
}
able-claw[data-mode="launcher"] .aclaw-helper-header {
  grid-area: helper;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--ableclaw-border-soft);
}
/* Close button inside the panel header (launcher-only) */
.aclaw-launcher-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 999px;
  background: transparent; color: inherit; border: 0;
  cursor: pointer; opacity: 0.65;
  transition: opacity 120ms, background-color 120ms;
}
.aclaw-launcher-close:hover {
  opacity: 1;
  background: var(--ableclaw-sidebar-hover-bg, rgba(127, 127, 127, 0.10));
}
.aclaw-launcher-close i { font-size: 12px; }

/* Mobile launcher — full-screen panel instead of floating card */
@media (max-width: 640px) {
  .aclaw-launcher-pill {
    padding: 8px 12px;
    font-size: 12px;
    bottom: 16px; right: 16px;
  }
  .aclaw-launcher-pill-text { display: none; }  /* icon only on phone */
  able-claw[data-mode="launcher"] > .aclaw-grid {
    inset: 0 !important;
    width: 100% !important;
    height: 100% !important;
    max-width: 100% !important;
    max-height: 100% !important;
    border-radius: 0;
    border: 0;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * iOS 2026 LIQUID GLASS — design overlay (from Anthropic design file
 * AbleClaw Chat.html, rBaa5XHjVDHCyLdc1As3tw).
 *
 * Translucent materials with backdrop-filter, oklch color tokens, vibrant
 * blue/purple user gradient + frosted agent bubbles, big radii (22px chat
 * bubbles, 26px composer + sidebar), green online-dot, channel chips
 * with mini colored icon squares.
 *
 * This block LAYERS OVER the structural rules above — no existing rule
 * is removed. Layout/grid/dataflow stays the same; only colors, radii,
 * shadows, and surface materials change.
 * ═══════════════════════════════════════════════════════════════════════ */

able-claw {
  /* Liquid Glass tokens — LIGHT defaults */
  --lg-wp-1: oklch(97% 0.012 250);
  --lg-wp-2: oklch(94% 0.020 245);
  --lg-wp-3: oklch(95% 0.018 260);
  --lg-ink-1: oklch(20% 0.014 255);
  --lg-ink-2: oklch(38% 0.012 255);
  --lg-ink-3: oklch(56% 0.010 255);
  --lg-ink-4: oklch(72% 0.008 255);
  --lg-mat-thick:   color-mix(in oklch, white 75%, transparent);
  --lg-mat-regular: color-mix(in oklch, white 60%, transparent);
  --lg-mat-thin:    color-mix(in oklch, white 40%, transparent);
  --lg-mat-ultra:   color-mix(in oklch, white 22%, transparent);
  --lg-mat-hover:   color-mix(in oklch, white 85%, transparent);
  --lg-line:        color-mix(in oklch, var(--lg-ink-1) 9%, transparent);
  --lg-line-soft:   color-mix(in oklch, var(--lg-ink-1) 5%, transparent);
  --lg-line-strong: color-mix(in oklch, var(--lg-ink-1) 18%, transparent);
  --lg-sys-blue:   oklch(56% 0.16 255);
  --lg-sys-blue-2: oklch(50% 0.18 258);
  --lg-sys-green:  oklch(64% 0.16 145);
  --lg-sys-purple: oklch(58% 0.14 268);
  --lg-grad-user: linear-gradient(135deg, oklch(60% 0.17 255), oklch(52% 0.18 260));
  --lg-grad-agent-avatar: linear-gradient(135deg, var(--lg-sys-purple), var(--lg-sys-blue-2));
  --lg-user-ink: oklch(99% 0.01 255);
  --lg-shadow-sm: 0 1px 0 oklch(0% 0 0 / 0.04), 0 2px 8px -4px oklch(0% 0 0 / 0.10);
  --lg-shadow:    0 2px 4px -2px oklch(0% 0 0 / 0.08), 0 12px 32px -12px oklch(0% 0 0 / 0.18);
  --lg-shadow-lg: 0 8px 16px -8px oklch(0% 0 0 / 0.16), 0 32px 80px -16px oklch(0% 0 0 / 0.28);
  /* Radii */
  --lg-r-xs: 8px; --lg-r-sm: 12px; --lg-r: 16px; --lg-r-md: 20px;
  --lg-r-lg: 26px; --lg-r-xl: 32px; --lg-r-pill: 999px;

  /* Re-point existing --ableclaw-* surfaces to the new tokens so any
     descendant rule that reads them inherits the Liquid Glass look. */
  --ableclaw-bg:                 var(--lg-wp-1);
  --ableclaw-fg:                 var(--lg-ink-1);
  --ableclaw-sidebar-bg:         var(--lg-mat-regular);
  --ableclaw-sidebar-fg:         var(--lg-ink-1);
  --ableclaw-sidebar-active-bg:  var(--lg-mat-thick);
  --ableclaw-sidebar-hover-bg:   var(--lg-mat-thin);
  --ableclaw-artifact-bg:        var(--lg-mat-regular);
  --ableclaw-border:             var(--lg-line);
  --ableclaw-border-soft:        var(--lg-line-soft);
  --ableclaw-bubble-user-bg:     var(--lg-grad-user);
  --ableclaw-bubble-user-fg:     var(--lg-user-ink);
  --ableclaw-bubble-agent-bg:    var(--lg-mat-thick);
  --ableclaw-bubble-agent-fg:    var(--lg-ink-1);
  --ableclaw-input-bg:           var(--lg-mat-regular);
  --ableclaw-input-fg:           var(--lg-ink-1);
  --ableclaw-input-border:       var(--lg-line-soft);
  --ableclaw-input-bar-bg:       transparent;
  --ableclaw-accent:             var(--lg-sys-blue);
  --ableclaw-accent-fg:          var(--lg-user-ink);
}

[data-theme="dark"] able-claw {
  --lg-wp-1: oklch(18% 0.018 255);
  --lg-wp-2: oklch(22% 0.024 260);
  --lg-wp-3: oklch(20% 0.020 245);
  --lg-ink-1: oklch(97% 0.008 255);
  --lg-ink-2: oklch(82% 0.010 255);
  --lg-ink-3: oklch(60% 0.010 255);
  --lg-ink-4: oklch(46% 0.010 255);
  --lg-mat-thick:   color-mix(in oklch, oklch(28% 0.014 255) 75%, transparent);
  --lg-mat-regular: color-mix(in oklch, oklch(30% 0.014 255) 60%, transparent);
  --lg-mat-thin:    color-mix(in oklch, oklch(34% 0.014 255) 42%, transparent);
  --lg-mat-ultra:   color-mix(in oklch, oklch(38% 0.014 255) 24%, transparent);
  --lg-mat-hover:   color-mix(in oklch, oklch(36% 0.014 255) 75%, transparent);
  --lg-line:        color-mix(in oklch, white 10%, transparent);
  --lg-line-soft:   color-mix(in oklch, white 6%, transparent);
  --lg-line-strong: color-mix(in oklch, white 22%, transparent);
  --lg-sys-blue:   oklch(66% 0.16 255);
  --lg-sys-blue-2: oklch(60% 0.18 260);
  --lg-sys-green:  oklch(70% 0.16 145);
  --lg-sys-purple: oklch(66% 0.14 268);
  --lg-grad-user: linear-gradient(135deg, oklch(66% 0.16 255), oklch(58% 0.18 262));
  --lg-shadow-sm: 0 1px 0 oklch(0% 0 0 / 0.3), 0 2px 8px -4px oklch(0% 0 0 / 0.4);
  --lg-shadow:    0 2px 4px -2px oklch(0% 0 0 / 0.35), 0 12px 32px -12px oklch(0% 0 0 / 0.5);
  --lg-shadow-lg: 0 8px 16px -8px oklch(0% 0 0 / 0.5), 0 32px 80px -16px oklch(0% 0 0 / 0.7);

  /* Invert the system-base grey scale within able-claw in dark mode.
     The ABLEUI Chat Output Classes (.claw-h1 / .claw-body--editorial /
     .claw-sidebar / .claw-code / .claw-table / etc.) reference these
     primitives directly. Without this flip:
       .claw-h1 { color: var(--grey-900) }  →  #18191b on dark bg → invisible
       .claw-code { background: var(--grey-0) }  →  #fff on dark bg → white block
     We override INSIDE able-claw only, so other blueprints that use the
     greys as fixed primitives (icons, badges) are untouched. */
  --grey-0:    #0c0d0e;
  --grey-50:   #18191b;
  --grey-100:  #1d1c17;
  --grey-200:  #303236;
  --grey-300:  #3f3f46;
  --grey-400:  #505151;
  --grey-500:  #94a3b8;  /* muted body — slate-400, readable on dark bg */
  --grey-600:  #cbd5e1;
  --grey-700:  #e2e8f0;
  --grey-800:  #f0f1f2;
  --grey-900:  #f8fafc;  /* "darkest text" → flipped → near-white in dark */
  --grey-1000: #ffffff;
}

/* ─── Liquid Glass component overrides ─────────────────────────────── */

/* Grid container — wallpaper background + soft tinted border + bigger radius */
able-claw .aclaw-grid {
  background: var(--lg-wp-1);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r-md);
  box-shadow: var(--lg-shadow-sm);
}

/* Sidebar — frosted glass material */
able-claw .aclaw-sidebar {
  background: var(--lg-mat-regular);
  backdrop-filter: saturate(180%) blur(28px);
  -webkit-backdrop-filter: saturate(180%) blur(28px);
  border-right: 1px solid var(--lg-line-soft);
}

/* New conversation button — grad-user gradient with inner highlight */
able-claw .aclaw-new-chat {
  background: var(--lg-grad-user);
  color: var(--lg-user-ink);
  border-radius: var(--lg-r);
  font-weight: 600;
  box-shadow:
    inset 0 1px 0 oklch(100% 0 0 / 0.22),
    0 2px 6px -2px oklch(52% 0.18 260 / 0.4),
    0 8px 20px -8px oklch(52% 0.18 260 / 0.4);
  transition: transform 0.08s, filter 0.15s;
}
able-claw .aclaw-new-chat:hover { filter: brightness(1.05); }
able-claw .aclaw-new-chat:active { transform: scale(0.98); }

/* Sidebar collapse / expand chevron — sq glass btn */
able-claw .aclaw-sidebar-collapse,
able-claw .aclaw-sidebar-expand {
  background: var(--lg-mat-thin);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r);
  color: var(--lg-ink-2);
}
able-claw .aclaw-sidebar-collapse:hover,
able-claw .aclaw-sidebar-expand:hover {
  background: var(--lg-mat-hover);
  color: var(--lg-ink-1);
}

/* Search input — frosted */
able-claw .aclaw-search {
  background: var(--lg-mat-thin);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r);
  color: var(--lg-ink-1);
}
able-claw .aclaw-search:focus {
  background: var(--lg-mat-thick);
  border-color: color-mix(in oklch, var(--lg-sys-blue) 50%, transparent);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--lg-sys-blue) 16%, transparent);
}

/* Agent selector / TALKING TO card */
able-claw .aclaw-agent-selector {
  background: var(--lg-mat-thick);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r);
  box-shadow: var(--lg-shadow-sm);
}
able-claw .aclaw-agent-selector:hover { background: var(--lg-mat-hover); }
able-claw .aclaw-agent-selector .aclaw-agent-avatar {
  background: var(--lg-grad-agent-avatar);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.25), 0 2px 4px oklch(0% 0 0 / 0.12);
}

/* Conversation row in sidebar — active state is clearly distinct:
   accent-tinted background + 3px gradient left strip + accent ring +
   bold title color. Works in both light and dark because the accent
   (sys-blue → sys-purple) reads against both wallpapers.

   NOTE: NO outer box-shadow — the sidebar deliberately doesn't have
   overflow:hidden (agent popover needs to extend below the header),
   so an outer shadow would bleed past the sidebar border. We rely on
   bg tint + inset ring + left accent strip for visual distinction. */
able-claw .aclaw-conversation-row {
  border-radius: 12px;
  position: relative;
  transition: background 140ms, box-shadow 160ms;
}
able-claw .aclaw-conversation-row:hover { background: var(--lg-mat-thin); }
able-claw .aclaw-conversation-row.is-active {
  background: color-mix(in oklch, var(--lg-sys-blue) 14%, var(--lg-mat-thick));
  box-shadow:
    inset 0 0 0 1px color-mix(in oklch, var(--lg-sys-blue) 35%, transparent);
}
/* Left accent strip — subtle gradient bar that reads as the "selected
   indicator" without competing with the chat content. Contained within
   the row's bounds so no bleed past the sidebar edge. */
able-claw .aclaw-conversation-row.is-active::before {
  content: '';
  position: absolute;
  left: 4px; top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 60%;
  border-radius: 999px;
  background: var(--lg-grad-user);
}
able-claw .aclaw-conversation-row.is-active .aclaw-conversation-title {
  color: var(--lg-ink-1);
  font-weight: 600;
}
able-claw .aclaw-conversation-row.is-active .aclaw-conversation-meta {
  color: color-mix(in oklch, var(--lg-sys-blue) 60%, var(--lg-ink-3));
}

/* Conversation channel icons in sidebar */
able-claw .aclaw-conv-icon {
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.25), 0 2px 4px oklch(0% 0 0 / 0.10);
}

/* Welcome surface — frosted intro card */
able-claw .aclaw-welcome {
  background: transparent;
}

/* Message bubbles — modernized: 22px radius, user gradient with glow,
   agent frosted glass */
able-claw .aclaw-message-bubble {
  border-radius: 22px;
  padding: 10px 14px;
  font-size: 15px;
  line-height: 1.45;
  letter-spacing: -0.012em;
  box-shadow: var(--lg-shadow-sm);
}
able-claw .aclaw-message--assistant .aclaw-message-bubble {
  background: var(--lg-mat-thick);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: var(--lg-ink-1);
  border: 1px solid var(--lg-line-soft);
}
able-claw .aclaw-message--user .aclaw-message-bubble {
  background: var(--lg-grad-user);
  color: var(--lg-user-ink);
  font-weight: 500;
  border: 0;
  box-shadow:
    inset 0 1px 0 oklch(100% 0 0 / 0.18),
    0 2px 4px -2px oklch(52% 0.18 260 / 0.35),
    0 12px 28px -10px oklch(52% 0.18 260 / 0.3);
}

/* Channel divider — chip with mini colored icon square */
able-claw .aclaw-channel-divider {
  color: var(--lg-ink-3);
  margin: 16px 0 8px;
}
able-claw .aclaw-channel-divider::before,
able-claw .aclaw-channel-divider::after {
  background: linear-gradient(to right, transparent, var(--lg-line), transparent);
}
able-claw .aclaw-channel-divider-pill {
  background: var(--lg-mat-thick);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r-pill);
  padding: 5px 12px 5px 6px;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--lg-ink-2);
  gap: 7px;
}
able-claw .aclaw-channel-divider-pill i {
  color: white;
  font-size: 9px;
  width: 18px; height: 18px;
  display: inline-grid; place-items: center;
  border-radius: 6px;
  background: var(--ableclaw-channel-default);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.25);
}
able-claw .aclaw-channel-divider[data-channel="telegram"]  .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(74% 0.14 230), oklch(58% 0.18 240)); }
able-claw .aclaw-channel-divider[data-channel="slack"]     .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(70% 0.20 320), oklch(54% 0.22 330)); }
able-claw .aclaw-channel-divider[data-channel="email"]     .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(72% 0.06 250), oklch(50% 0.04 250)); }
able-claw .aclaw-channel-divider[data-channel="sms"]       .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(72% 0.18 145), oklch(54% 0.16 145)); }
able-claw .aclaw-channel-divider[data-channel="whatsapp"]  .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(72% 0.18 145), oklch(54% 0.16 145)); }
able-claw .aclaw-channel-divider[data-channel="web"]       .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(70% 0.04 230), oklch(48% 0.04 250)); }
able-claw .aclaw-channel-divider[data-channel="ableui"]    .aclaw-channel-divider-pill i { background: linear-gradient(135deg, oklch(40% 0.04 260), oklch(15% 0.02 260)); }

/* Composer — frosted glass, big radius, blue focus glow */
able-claw .aclaw-input-bar {
  margin: 8px 16px 12px;
  padding: 6px;
  background: var(--lg-mat-regular);
  backdrop-filter: saturate(180%) blur(28px);
  -webkit-backdrop-filter: saturate(180%) blur(28px);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r-lg);
  box-shadow: var(--lg-shadow);
  transition: border-color 0.18s, box-shadow 0.18s;
}
able-claw .aclaw-input-bar:focus-within {
  border-color: color-mix(in oklch, var(--lg-sys-blue) 50%, transparent);
  box-shadow: var(--lg-shadow), 0 0 0 4px color-mix(in oklch, var(--lg-sys-blue) 16%, transparent);
}
able-claw .aclaw-upload {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: transparent;
  color: var(--lg-ink-2);
}
able-claw .aclaw-upload:hover:not(:disabled) {
  background: var(--lg-mat-thin);
  color: var(--lg-ink-1);
}
able-claw .aclaw-input {
  background: transparent;
  color: var(--lg-ink-1);
  border: 0;
  padding: 10px 4px;
  font-size: 15px;
}
able-claw .aclaw-input::placeholder { color: var(--lg-ink-3); }
able-claw .aclaw-send {
  width: 38px; height: 38px; padding: 0;
  border-radius: 50%;
  background: var(--lg-grad-user);
  color: var(--lg-user-ink);
  display: grid; place-items: center;
  box-shadow:
    inset 0 1px 0 oklch(100% 0 0 / 0.22),
    0 2px 6px -2px oklch(52% 0.18 260 / 0.4);
}
able-claw .aclaw-send:hover:not(:disabled) {
  filter: brightness(1.05);
  box-shadow:
    inset 0 1px 0 oklch(100% 0 0 / 0.22),
    0 4px 10px -2px oklch(52% 0.18 260 / 0.5);
}
able-claw .aclaw-send:active:not(:disabled) { transform: scale(0.94); }
able-claw .aclaw-send span { display: none; }
able-claw .aclaw-send i { font-size: 14px; }
able-claw .aclaw-stop span { display: none; }
able-claw .aclaw-stop { width: 38px; height: 38px; padding: 0; border-radius: 50%; }

/* Bug #92 — global :focus-visible for every interactive control inside
   able-claw. Many of our specific button rules set outline:none or
   border:none for visual polish, which kills keyboard focus indication.
   This rule reintroduces a single consistent focus ring (only when
   keyboard navigation triggers it, not on mouse-click) so keyboard
   users can always see where they are. */
able-claw button:focus-visible,
able-claw [role="button"]:focus-visible,
able-claw a:focus-visible,
able-claw [data-conversation-id]:focus-visible {
  outline: 2px solid var(--ableclaw-accent, #6366f1);
  outline-offset: 2px;
  border-radius: 6px;
}
able-claw textarea:focus-visible,
able-claw input:focus-visible {
  /* Native inputs already get a focus ring; align with the same accent. */
  outline: 2px solid var(--ableclaw-accent, #6366f1);
  outline-offset: 1px;
}

/* Footer meta */
able-claw .aclaw-input-footer {
  color: var(--lg-ink-3);
  font-size: 11.5px;
}

/* Helper / launcher compact header */
able-claw[data-mode="helper"] .aclaw-helper-header,
able-claw[data-mode="launcher"] .aclaw-helper-header {
  border-bottom: 1px solid var(--lg-line-soft);
}
able-claw .aclaw-helper-avatar {
  background: var(--lg-grad-agent-avatar);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.25), 0 2px 4px oklch(0% 0 0 / 0.12);
}
able-claw .aclaw-helper-name { color: var(--lg-ink-1); }
able-claw .aclaw-helper-sub  { color: var(--lg-ink-3); }
able-claw .aclaw-helper-action:hover {
  background: var(--lg-mat-thin);
}

/* Online dot mimic in agent selector header (decorative) */
able-claw .aclaw-helper-avatar::after {
  content: '';
  position: relative;
  display: block;
  width: 0; height: 0;
}

/* Launcher pill — keep the dark pill from the previous design as it
   matches the user mock; only refine shadow + status dot color. */
able-claw[data-mode="launcher"] .aclaw-launcher-pill {
  box-shadow: var(--lg-shadow);
}
able-claw[data-mode="launcher"] .aclaw-launcher-pill-status {
  background: var(--lg-sys-green);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--lg-sys-green) 22%, transparent);
}
able-claw[data-mode="launcher"] > .aclaw-grid {
  border-radius: var(--lg-r-md);
  box-shadow: var(--lg-shadow-lg);
}

/* Sidebar conversation badge (legacy dot) — sized down */
able-claw .aclaw-conv-badge { width: 8px; height: 8px; }

/* Channel chip in main-chat divider — bigger spacing on top */
able-claw .aclaw-messages { padding: 20px 32px 16px; }
able-claw[data-mode="helper"] .aclaw-messages,
able-claw[data-mode="launcher"] .aclaw-messages { padding: 14px 18px 8px; }

/* ─── Welcome screen + shortcuts (Liquid Glass) ─────────────────────── */

able-claw .aclaw-welcome {
  padding: 32px 24px 16px;
}
able-claw .aclaw-welcome-icon {
  width: 84px; height: 84px;
  background: var(--lg-grad-agent-avatar);
  box-shadow:
    inset 0 1px 0 oklch(100% 0 0 / 0.25),
    0 12px 32px -8px color-mix(in oklch, var(--lg-sys-purple) 50%, transparent);
}
able-claw .aclaw-welcome-icon svg {
  width: 38px; height: 38px;
  filter: drop-shadow(0 2px 4px oklch(0% 0 0 / 0.18));
}
able-claw .aclaw-welcome-headline-h1 {
  font-size: 32px; font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--lg-ink-1);
}
able-claw .aclaw-welcome-subtitle {
  font-size: 14.5px;
  color: var(--lg-ink-3);
  letter-spacing: -0.008em;
  opacity: 1;
  margin-top: 4px;
}

/* Categorized shortcut grid */
able-claw .aclaw-welcome-categories {
  gap: 20px;
  margin-top: 16px;
}
able-claw .aclaw-welcome-category-header {
  font-size: 11px;
  letter-spacing: 0.10em;
  font-weight: 700;
  gap: 8px;
  padding: 4px 4px 10px;
}
able-claw .aclaw-welcome-category-icon {
  width: 24px; height: 24px;
  border-radius: 7px;
  font-size: 13px;
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.25), 0 2px 6px -2px oklch(0% 0 0 / 0.12);
}

/* The shortcut card — frosted glass, line-soft border, 14px radius,
   soft shadow, hover lift + category-colored accent ring. */
able-claw .aclaw-shortcut {
  background: var(--lg-mat-thick);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--lg-line-soft);
  border-radius: 14px;
  color: var(--lg-ink-1);
  padding: 14px;
  gap: 8px;
  box-shadow: var(--lg-shadow-sm);
  transition: transform 120ms, background 140ms, border-color 140ms, box-shadow 160ms;
  position: relative;
}
able-claw .aclaw-shortcut:hover {
  transform: translateY(-1px);
  background: var(--lg-mat-hover);
  border-color: var(--lg-line);
  box-shadow: var(--lg-shadow);
}
able-claw .aclaw-shortcut:active { transform: translateY(0); }
able-claw .aclaw-shortcut-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: 9px;
  background: var(--lg-mat-thin);
  border: 1px solid var(--lg-line-soft);
  font-size: 13px;
  opacity: 1;
  color: var(--lg-ink-2);
  flex-shrink: 0;
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.12);
}
able-claw .aclaw-shortcut-icon i { line-height: 1; }
able-claw .aclaw-shortcut-category {
  display: none;  /* category is in the column header already; redundant per card */
}
able-claw .aclaw-shortcut-text {
  font-size: 13.5px;
  line-height: 1.4;
  letter-spacing: -0.008em;
  color: var(--lg-ink-1);
}

/* Category accent palettes — color tints injected into card hover state +
   category header. Each category overrides its own --cat-accent so the
   shortcut icon backplate, header color, and hover shadow all align. */
able-claw .aclaw-welcome-category--analyze {
  --cat-accent: oklch(64% 0.16 145);            /* green */
  --cat-accent-tint: color-mix(in oklch, oklch(64% 0.16 145) 12%, transparent);
}
able-claw .aclaw-welcome-category--monitor {
  --cat-accent: oklch(60% 0.18 245);            /* blue */
  --cat-accent-tint: color-mix(in oklch, oklch(60% 0.18 245) 12%, transparent);
}
able-claw .aclaw-welcome-category--act {
  --cat-accent: oklch(72% 0.18 75);             /* amber */
  --cat-accent-tint: color-mix(in oklch, oklch(72% 0.18 75) 14%, transparent);
}
able-claw .aclaw-welcome-category--report {
  --cat-accent: oklch(64% 0.20 25);             /* red-orange */
  --cat-accent-tint: color-mix(in oklch, oklch(64% 0.20 25) 12%, transparent);
}

/* Apply per-category accent to header + shortcut icon + hover state */
able-claw .aclaw-welcome-category .aclaw-welcome-category-header {
  color: var(--cat-accent, var(--lg-ink-2));
}
able-claw .aclaw-welcome-category .aclaw-welcome-category-icon {
  background: var(--cat-accent-tint, var(--lg-mat-thin));
  color: var(--cat-accent, var(--lg-ink-2));
  border: 1px solid color-mix(in oklch, var(--cat-accent, var(--lg-ink-3)) 18%, transparent);
}
able-claw .aclaw-welcome-category .aclaw-shortcut .aclaw-shortcut-icon {
  background: var(--cat-accent-tint, var(--lg-mat-thin));
  color: var(--cat-accent, var(--lg-ink-2));
  border-color: color-mix(in oklch, var(--cat-accent, var(--lg-ink-3)) 14%, transparent);
}
able-claw .aclaw-welcome-category .aclaw-shortcut:hover {
  border-color: color-mix(in oklch, var(--cat-accent, var(--lg-line)) 40%, transparent);
  box-shadow: var(--lg-shadow-sm),
              0 0 0 3px color-mix(in oklch, var(--cat-accent, var(--lg-sys-blue)) 10%, transparent);
}

/* "or What can I help you with?" helper text */
able-claw .aclaw-welcome-helper {
  font-size: 13px;
  color: var(--lg-ink-3);
  margin-top: 12px;
  font-style: italic;
}

/* ─── Agent selector popover (dropdown) ─────────────────────────────── */
able-claw .aclaw-agent-popover {
  background: var(--lg-mat-thick);
  backdrop-filter: saturate(180%) blur(28px);
  -webkit-backdrop-filter: saturate(180%) blur(28px);
  border: 1px solid var(--lg-line-soft);
  border-radius: var(--lg-r);
  box-shadow: var(--lg-shadow);
  padding: 6px;
  z-index: 50;
  min-width: 240px;
}
able-claw .aclaw-agent-option {
  border-radius: 10px;
  padding: 8px 10px;
}
able-claw .aclaw-agent-option:hover {
  background: var(--lg-mat-hover);
}
able-claw .aclaw-agent-option.is-active {
  background: var(--lg-mat-thick);
  box-shadow: inset 0 0 0 1px var(--lg-line);
}
able-claw .aclaw-agent-option .aclaw-agent-avatar {
  background: var(--lg-grad-agent-avatar);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.20);
}
able-claw .aclaw-agent-option .aclaw-agent-name { color: var(--lg-ink-1); }
able-claw .aclaw-agent-option .aclaw-agent-tagline { color: var(--lg-ink-3); }

/* ─── Stop button — visible square icon on red circle ──────────────── */
able-claw .aclaw-stop {
  /* Center the icon explicitly — inline-flex inherits justify-content
     flex-start by default, which left-justified the FA glyph inside the
     38px circle. align-items already covers vertical centering. */
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 0;
  background: oklch(60% 0.20 25);  /* sys-red */
  color: white;
  box-shadow:
    inset 0 1px 0 oklch(100% 0 0 / 0.18),
    0 2px 6px -2px oklch(60% 0.20 25 / 0.4);
}
able-claw .aclaw-stop:hover {
  background: oklch(54% 0.22 25);
}
able-claw .aclaw-stop i {
  font-size: 12px;
  color: white;
  display: inline-block;
  line-height: 1;
}

/* ─── Typing indicator (3 animated dots + live phase/timer) for empty assistant bubble ── */
able-claw .aclaw-message-bubble--pending {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-width: 56px;
  padding: 12px 16px;
}
/* The live phase verb + elapsed clock beside the dots (iOS WorkingIndicator parity). */
able-claw .aclaw-typing-status {
  font-size: 13px;
  line-height: 1.3;
  color: var(--text-muted, #6b7280);
  animation: aclaw-status-blink 1.8s ease-in-out infinite;
}
able-claw .aclaw-typing-status .aclaw-status-clock { animation: none; }
@media (prefers-reduced-motion: reduce) { able-claw .aclaw-typing-status { animation: none; } }
able-claw .aclaw-typing {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  line-height: 1;
}
able-claw .aclaw-typing > span {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--lg-ink-3);
  opacity: 0.5;
  animation: aclaw-typing-bounce 1.2s infinite ease-in-out;
}
able-claw .aclaw-typing > span:nth-child(2) { animation-delay: 0.15s; }
able-claw .aclaw-typing > span:nth-child(3) { animation-delay: 0.30s; }
@keyframes aclaw-typing-bounce {
  0%, 80%, 100% { transform: translateY(0); opacity: 0.4; }
  40%           { transform: translateY(-3px); opacity: 0.95; }
}

/* Error bubble (stream / HTTP failure) — danger-tinted card with retry
   affordance. Replaces the failed assistant turn in-place. */
able-claw .aclaw-message-bubble--error {
  background: color-mix(in srgb, #b91c1c 8%, var(--lg-mat-thick));
  border: 1px solid color-mix(in srgb, #b91c1c 28%, transparent);
  color: var(--lg-ink-1);
}
able-claw .aclaw-error {
  display: flex; align-items: flex-start; gap: 10px;
}
able-claw .aclaw-error > .fa-circle-exclamation {
  color: #b91c1c;
  font-size: 16px;
  margin-top: 1px;
  flex-shrink: 0;
}
able-claw .aclaw-error-body { flex: 1; min-width: 0; }
able-claw .aclaw-error-title {
  font-weight: 600; font-size: 13px;
  color: #b91c1c;
  margin-bottom: 2px;
}
able-claw .aclaw-error-msg {
  font-size: 13px;
  color: var(--lg-ink-2);
  line-height: 1.45;
  margin-bottom: 8px;
  word-wrap: break-word;
}
able-claw .aclaw-error-retry {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--lg-grad-user);
  color: var(--lg-user-ink);
  border: 0;
  font-size: 12px; font-weight: 600;
  cursor: pointer;
  transition: filter 120ms, transform 120ms;
}
able-claw .aclaw-error-retry:hover { filter: brightness(1.05); }
able-claw .aclaw-error-retry:active { transform: scale(0.97); }
able-claw .aclaw-error-retry i { font-size: 11px; }

/* ═══════════════════════════════════════════════════════════════════════════
 * Browser compat fallbacks
 *
 * oklch() and color-mix() are Chrome 111+ / Safari 15.4+ / Firefox 113+
 * (May 2023). For older browsers, fall back to neutral hex tokens that
 * approximate the iOS Liquid Glass palette. Without these fallbacks the
 * page renders with "unset" values — flash of unstyled content + broken
 * layout colors.
 *
 * The @supports query reverses the logic: if the browser does NOT
 * understand oklch(), apply hex overrides. Modern browsers ignore the
 * block; older ones use the hex defaults.
 * ═══════════════════════════════════════════════════════════════════════ */

@supports not (color: oklch(0% 0 0)) {
  able-claw {
    /* Light defaults — hex approximations of the oklch tokens */
    --lg-wp-1: #f3f5f9;
    --lg-wp-2: #e6ebf3;
    --lg-wp-3: #ebeef5;
    --lg-ink-1: #1f2937;
    --lg-ink-2: #475569;
    --lg-ink-3: #6b7280;
    --lg-ink-4: #9ca3af;
    --lg-mat-thick:   rgba(255, 255, 255, 0.75);
    --lg-mat-regular: rgba(255, 255, 255, 0.60);
    --lg-mat-thin:    rgba(255, 255, 255, 0.40);
    --lg-mat-ultra:   rgba(255, 255, 255, 0.22);
    --lg-mat-hover:   rgba(255, 255, 255, 0.85);
    --lg-line:        rgba(31, 41, 55, 0.09);
    --lg-line-soft:   rgba(31, 41, 55, 0.05);
    --lg-line-strong: rgba(31, 41, 55, 0.18);
    --lg-sys-blue:    #3b82f6;
    --lg-sys-blue-2:  #2563eb;
    --lg-sys-green:   #10b981;
    --lg-sys-purple:  #8b5cf6;
    --lg-grad-user: linear-gradient(135deg, #3b82f6, #6366f1);
    --lg-grad-agent-avatar: linear-gradient(135deg, #8b5cf6, #2563eb);
    --lg-user-ink: #ffffff;
  }
  [data-theme="dark"] able-claw {
    --lg-wp-1: #1a202f;
    --lg-wp-2: #1f2937;
    --lg-wp-3: #1e293b;
    --lg-ink-1: #f8fafc;
    --lg-ink-2: #cbd5e1;
    --lg-ink-3: #94a3b8;
    --lg-ink-4: #64748b;
    --lg-mat-thick:   rgba(40, 48, 60, 0.75);
    --lg-mat-regular: rgba(43, 51, 65, 0.60);
    --lg-mat-thin:    rgba(49, 58, 73, 0.42);
    --lg-mat-ultra:   rgba(55, 65, 81, 0.24);
    --lg-mat-hover:   rgba(52, 61, 76, 0.75);
    --lg-line:        rgba(255, 255, 255, 0.10);
    --lg-line-soft:   rgba(255, 255, 255, 0.06);
    --lg-line-strong: rgba(255, 255, 255, 0.22);
    --lg-sys-blue:    #60a5fa;
    --lg-sys-blue-2:  #3b82f6;
    --lg-sys-green:   #34d399;
    --lg-sys-purple:  #a78bfa;
    --lg-grad-user: linear-gradient(135deg, #60a5fa, #6366f1);
  }
}

/* =================================================================
 * ABLEUI Chat Output Classes — Token-efficient HTML for chat bubbles.
 * Scoped under .aclaw-message-bubble so they only apply to LLM output.
 * Sanitizer strips inline style="..."; classes survive.
 * Wave-2 retokenization (C-spec §2.3): semantic accents ride the PLATFORM
 * tokens — s=var(--success) · i=var(--info) · w=var(--warning) ·
 * d=var(--danger) · b=var(--accent) — washes are color-mix over transparent,
 * gradient partners are color-mix toward white/black, and the deliberately
 * DARK editorial surfaces (hero / card--dark) derive from var(--info) over
 * black. Dark mode is BY CONSTRUCTION: tokens re-bind, greys invert via the
 * able-claw dark block; the only fixed hues left are the avatar identity
 * tones (oklch — decorative, mode-independent like badges) + true neutrals.
 * Tones via data-tone="s|i|w|d|b|n" — short attrs save tokens on
 * multiplied components (pills, cells).
 * ================================================================= */

.aclaw-message-bubble .claw-root {
  display: grid; gap: 14px;
  font-family: var(--font-sans, system-ui, sans-serif);
  color: var(--text-primary, inherit);
  line-height: 1.55; font-size: 14px;
  animation: claw-fade-in 0.3s ease-out;
}
.aclaw-message-bubble .claw-root--editorial {
  display: grid; gap: 24px;
  font-family: var(--font-serif, Georgia, serif);
  color: var(--text-primary, inherit);
  line-height: 1.7; font-size: 15px;
  animation: claw-fade-in 0.4s ease-out;
}
/* width-law-v1 companion (same disease as .aclaw-chat, one level deeper):
   these are single-column grids whose column track was IMPLICIT (auto-sized)
   — a wide table's min-content inflated the track past the bubble (measured:
   a 381px track inside a 315px root on a 375px phone → the grid card bled
   36px past the viewport). minmax(0,1fr) pins the track to the container so
   the card fills the bubble and the table scrolls inside its own
   overflow-x wrap instead of bleeding. */
.aclaw-message-bubble .claw-root,
.aclaw-message-bubble .claw-root--editorial,
.aclaw-message-bubble .claw-section { grid-template-columns: minmax(0, 1fr); }

.aclaw-message-bubble .claw-h1 {
  margin: 0;
  font-family: var(--font-serif, Georgia, serif);
  font-size: 36px; font-weight: 800;
  color: var(--grey-900, inherit);
  letter-spacing: -1px; line-height: 1.05;
}
.aclaw-message-bubble .claw-h2 {
  margin: 0;
  font-size: 22px; font-weight: 700;
  color: var(--grey-900, inherit);
  letter-spacing: -0.4px; line-height: 1.15;
}
.aclaw-message-bubble .claw-h3 {
  margin: 0;
  font-size: 16px; font-weight: 600;
  color: var(--grey-900, inherit);
  line-height: 1.3;
}
.aclaw-message-bubble .claw-h4 {
  margin: 0;
  font-size: 14px; font-weight: 600;
  color: var(--grey-900, inherit);
}

.aclaw-message-bubble .claw-eyebrow {
  margin: 0;
  font-size: 11px; font-weight: 700;
  letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--accent);
}
.aclaw-message-bubble .claw-eyebrow[data-tone="s"] { color: var(--success); }
.aclaw-message-bubble .claw-eyebrow[data-tone="i"] { color: var(--info); }
.aclaw-message-bubble .claw-eyebrow[data-tone="w"] { color: var(--warning); }
.aclaw-message-bubble .claw-eyebrow[data-tone="d"] { color: var(--danger); }
.aclaw-message-bubble .claw-eyebrow[data-tone="n"] { color: var(--grey-500, #66686b); }
.aclaw-message-bubble .claw-eyebrow--live::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  margin-right: 6px;
  vertical-align: 1px;
  animation: claw-pulse 2s infinite;
}

.aclaw-message-bubble .claw-body {
  margin: 0;
  color: var(--text-primary, inherit);
  line-height: 1.55;
}
.aclaw-message-bubble .claw-body--editorial {
  margin: 0;
  font-family: var(--font-serif, Georgia, serif);
  font-size: 15px; line-height: 1.7;
  color: var(--grey-800, inherit);
}
.aclaw-message-bubble .claw-body--muted {
  margin: 0;
  font-size: 13px;
  color: var(--grey-500, #66686b);
}

.aclaw-message-bubble .claw-dropcap {
  float: left;
  font-family: var(--font-serif, Georgia, serif);
  font-size: 56px; font-weight: 900;
  line-height: 0.9;
  padding: 6px 10px 0 0;
  color: var(--accent);
}

.aclaw-message-bubble .claw-pullquote {
  margin: 8px 0;
  padding: 16px 24px;
  border-left: 3px solid var(--accent);
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 6%, transparent), transparent);
  font-family: var(--font-serif, Georgia, serif);
  font-style: italic;
  font-size: 18px; line-height: 1.5;
  color: var(--grey-900, inherit);
}
.aclaw-message-bubble .claw-pullquote cite {
  display: block; margin-top: 8px;
  font-family: var(--font-sans, system-ui, sans-serif);
  font-style: normal;
  font-size: 12px;
  color: var(--grey-500, #66686b);
  letter-spacing: 0.5px;
}

.aclaw-message-bubble .claw-ul {
  margin: 0; padding-left: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.aclaw-message-bubble .claw-ul > li {
  position: relative;
  padding-left: 26px;
  line-height: 1.55;
}
.aclaw-message-bubble .claw-ul > li::before {
  content: "→";
  position: absolute;
  left: 0; top: 0;
  color: var(--accent);
  font-weight: 700;
  font-size: 16px;
  line-height: 1.55;
}
.aclaw-message-bubble .claw-ol {
  margin: 0; padding-left: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  counter-reset: step;
}
.aclaw-message-bubble .claw-ol > li {
  position: relative;
  padding-left: 40px;
  min-height: 26px;
  counter-increment: step;
  line-height: 1.55;
}
.aclaw-message-bubble .claw-ol > li::before {
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  display: grid; place-items: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 75%, white));
  color: var(--on-accent, #fff);
  font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.aclaw-message-bubble .claw-2col {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 24px;
  align-items: start;
}
.aclaw-message-bubble .claw-sidebar {
  display: grid; gap: 8px;
  padding: 16px;
  background: var(--grey-100, rgba(127,127,127,0.06));
  border-radius: 8px;
  border: 1px solid var(--grey-200, rgba(127,127,127,0.16));
}
.aclaw-message-bubble .claw-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.aclaw-message-bubble .claw-hr {
  border: 0;
  border-top: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  margin: 4px 0;
}
.aclaw-message-bubble .claw-hr--gradient {
  border: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--grey-300, rgba(127,127,127,0.32)) 20%, var(--grey-300, rgba(127,127,127,0.32)) 80%, transparent);
  margin: 16px 0;
}
.aclaw-message-bubble .claw-section { display: grid; gap: 14px; }

.aclaw-message-bubble .claw-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}
.aclaw-message-bubble .claw-kpi {
  display: grid; gap: 4px;
  padding: 16px 18px;
  background: var(--grey-0, #fff);
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  border-radius: 10px;
  border-top: 3px solid var(--accent);
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.aclaw-message-bubble .claw-kpi[data-tone="s"] { border-top-color: var(--success); }
.aclaw-message-bubble .claw-kpi[data-tone="i"] { border-top-color: var(--info); }
.aclaw-message-bubble .claw-kpi[data-tone="w"] { border-top-color: var(--warning); }
.aclaw-message-bubble .claw-kpi[data-tone="d"] { border-top-color: var(--danger); }
.aclaw-message-bubble .claw-kpi[data-tone="b"] { border-top-color: var(--accent); }
/* When the KPI itself is a danger/success metric, the VALUE inherits the tone color.
   The label stays muted (it's a label, not the metric).
   For neutral tone with semantic value coloring, use claw-kpi__value[data-tone=...] directly. */
.aclaw-message-bubble .claw-kpi[data-tone="d"] .claw-kpi__value { color: var(--danger); }
.aclaw-message-bubble .claw-kpi[data-tone="s"] .claw-kpi__value { color: var(--success); }
.aclaw-message-bubble .claw-kpi[data-tone="w"] .claw-kpi__value { color: var(--warning); }
.aclaw-message-bubble .claw-kpi__value[data-tone="d"] { color: var(--danger); }
.aclaw-message-bubble .claw-kpi__value[data-tone="s"] { color: var(--success); }
.aclaw-message-bubble .claw-kpi__value[data-tone="w"] { color: var(--warning); }
.aclaw-message-bubble .claw-kpi__label {
  font-size: 10px; font-weight: 700;
  letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--grey-500, #66686b);
}
.aclaw-message-bubble .claw-kpi__value {
  font-size: 26px; font-weight: 800;
  color: var(--grey-900, inherit);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.5px; line-height: 1.1;
}
.aclaw-message-bubble .claw-kpi__delta {
  font-size: 11px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--grey-500, #66686b);
}
.aclaw-message-bubble .claw-kpi__delta[data-dir="up"]   { color: var(--success); }
.aclaw-message-bubble .claw-kpi__delta[data-dir="down"] { color: var(--danger); }
.aclaw-message-bubble .claw-kpi__delta[data-dir="up"]::before   { content: "↑ "; font-size: 14px; line-height: 1; }
.aclaw-message-bubble .claw-kpi__delta[data-dir="down"]::before { content: "↓ "; font-size: 14px; line-height: 1; }

/* Hero — a DELIBERATELY dark editorial surface in both modes; the deep navy
   derives from the info token over black (no raw hex), white text stays. */
.aclaw-message-bubble .claw-hero {
  display: grid; gap: 6px;
  padding: 28px 32px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--info) 14%, black) 0%, color-mix(in srgb, var(--info) 60%, black) 100%);
  border-radius: 16px;
  color: #fff;
  position: relative; overflow: hidden;
}
.aclaw-message-bubble .claw-hero .claw-kpi__label { color: rgba(255,255,255,0.6); }
.aclaw-message-bubble .claw-hero__value {
  font-family: var(--font-serif, Georgia, serif);
  font-size: 48px; font-weight: 800;
  color: #fff;
  font-variant-numeric: tabular-nums;
  letter-spacing: -1.4px; line-height: 1;
}
.aclaw-message-bubble .claw-hero .claw-kpi__delta { color: rgba(255,255,255,0.75); }
.aclaw-message-bubble .claw-hero .claw-kpi__delta[data-dir="up"]   { color: color-mix(in srgb, var(--success) 55%, white); }
.aclaw-message-bubble .claw-hero .claw-kpi__delta[data-dir="down"] { color: color-mix(in srgb, var(--danger) 45%, white); }

.aclaw-message-bubble .claw-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px;
  font-size: 11px; font-weight: 600;
  line-height: 1.4;
  border-radius: 12px;
  background: var(--grey-200, rgba(127,127,127,0.12));
  color: var(--grey-700, inherit);
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
}
/* A pill INSIDE running prose must fit the line box (P2, 2026-08-03 — Recovr
   conv f88203cb, caught by the visual-review pass and confirmed by measurement).
   The standalone pill is 23.4px tall (11px x 1.4 line-height + 3px padding-block
   + 1px border, both sides) while body prose runs a 21.7px line box (14px x
   1.55). Inline in a sentence it therefore OUTGREW its line: the paragraph's
   line rects measured [17, 17, …, 23.4, 13, …, 23.4, 13, …] — every line
   carrying a pill jumped ~2px and fragmented, so the leading visibly stuttered
   mid-paragraph ("…it sits at [OK] today", "[TEMPORARILY ON HOLD] with a $0
   credit limit"). That is the same incoherence class as the callout measure:
   type furniture disturbing the reading rhythm.
   Only the padding-block shrinks (3px → 1px → 19.4px total, comfortably inside
   21.7px). Font-size, weight, radius, wash and border are untouched, so the pill
   still reads as a pill; baseline alignment is kept because the pill sits ON the
   text baseline. Scope is prose only (p / li) — a pill in a table cell, a card
   row or a standalone strip keeps its full 23.4px presence. */
.aclaw-message-bubble :is(p, li) .claw-pill { padding-block: 1px; }
/* Toned pills — token WASHES (not fixed pastels), so light and dark both
   derive from the semantic token; the hand-maintained dark twins are GONE. */
.aclaw-message-bubble .claw-pill[data-tone="s"] { background: color-mix(in srgb, var(--success) 10%, transparent); color: var(--success); border-color: color-mix(in srgb, var(--success) 34%, transparent); }
.aclaw-message-bubble .claw-pill[data-tone="i"] { background: color-mix(in srgb, var(--info) 10%, transparent); color: var(--info); border-color: color-mix(in srgb, var(--info) 34%, transparent); }
.aclaw-message-bubble .claw-pill[data-tone="w"] { background: color-mix(in srgb, var(--warning) 10%, transparent); color: var(--warning); border-color: color-mix(in srgb, var(--warning) 34%, transparent); }
.aclaw-message-bubble .claw-pill[data-tone="d"] { background: color-mix(in srgb, var(--danger) 10%, transparent); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 34%, transparent); }
.aclaw-message-bubble .claw-pill[data-tone="b"] { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 34%, transparent); }
.aclaw-message-bubble .claw-pill__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--grey-500, #66686b);
}
.aclaw-message-bubble .claw-pill[data-tone="s"] .claw-pill__dot { background: var(--success); }
.aclaw-message-bubble .claw-pill[data-tone="i"] .claw-pill__dot { background: var(--info); }
.aclaw-message-bubble .claw-pill[data-tone="w"] .claw-pill__dot { background: var(--warning); }
.aclaw-message-bubble .claw-pill[data-tone="d"] .claw-pill__dot { background: var(--danger); }
.aclaw-message-bubble .claw-pill[data-tone="b"] .claw-pill__dot { background: var(--accent); }
.aclaw-message-bubble .claw-pill[data-live] .claw-pill__dot { animation: claw-pulse 2s infinite; }

.aclaw-message-bubble .claw-tbl {
  overflow-x: auto;
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.aclaw-message-bubble .claw-tbl table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.aclaw-message-bubble .claw-tbl thead tr {
  background: var(--grey-100, rgba(127,127,127,0.06));
}
.aclaw-message-bubble .claw-th {
  padding: 11px 14px;
  text-align: left;
  font-size: 10px; font-weight: 700;
  letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--grey-700, inherit);
  border-bottom: 1px solid var(--grey-300, rgba(127,127,127,0.20));
}
.aclaw-message-bubble .claw-th[data-num] { text-align: right; font-variant-numeric: tabular-nums; }
.aclaw-message-bubble .claw-td {
  padding: 11px 14px;
  color: var(--grey-900, inherit);
  border-bottom: 1px solid var(--grey-200, rgba(127,127,127,0.12));
  vertical-align: middle;
}
.aclaw-message-bubble .claw-tbl tbody tr:last-child .claw-td { border-bottom: 0; }
.aclaw-message-bubble .claw-td[data-c="num"]     { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
.aclaw-message-bubble .claw-td[data-c="money"]   { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
.aclaw-message-bubble .claw-td[data-c="muted"]   { color: var(--grey-500, #66686b); }
.aclaw-message-bubble .claw-td[data-c="loss"]    { color: var(--danger); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.aclaw-message-bubble .claw-td[data-c="benefit"] { color: var(--success); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.aclaw-message-bubble .claw-td[data-c="id"] {
  font-family: var(--font-mono, Menlo, monospace);
  font-size: 11px;
  color: var(--grey-500, #66686b);
}

.aclaw-message-bubble .claw-card {
  display: grid; gap: 8px;
  padding: 16px;
  background: var(--grey-0, #fff);
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.aclaw-message-bubble .claw-card__head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 8px;
}
.aclaw-message-bubble .claw-card--accent {
  position: relative; overflow: hidden;
  padding-top: 19px;
  border-top: 3px solid var(--accent);
}
.aclaw-message-bubble .claw-card--accent[data-tone="s"] { border-top-color: var(--success); }
.aclaw-message-bubble .claw-card--accent[data-tone="i"] { border-top-color: var(--info); }
.aclaw-message-bubble .claw-card--accent[data-tone="w"] { border-top-color: var(--warning); }
.aclaw-message-bubble .claw-card--accent[data-tone="d"] { border-top-color: var(--danger); }
.aclaw-message-bubble .claw-card--accent[data-tone="b"] { border-top-color: var(--accent); }
/* card--dark — a DELIBERATELY dark editorial surface in both modes; the deep
   navy derives from the info token over black (no raw hex). */
.aclaw-message-bubble .claw-card--dark {
  display: grid; gap: 12px;
  padding: 24px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--info) 8%, black) 0%, color-mix(in srgb, var(--info) 60%, black) 100%);
  border-radius: 14px;
  color: #fff;
  position: relative; overflow: hidden;
}
.aclaw-message-bubble .claw-card--dark .claw-eyebrow { color: rgba(255,255,255,0.6); }
.aclaw-message-bubble .claw-card--dark .claw-h3,
.aclaw-message-bubble .claw-card--dark .claw-h4 { color: #fff; }
.aclaw-message-bubble .claw-card--dark .claw-kpi__label { color: rgba(255,255,255,0.5); }
.aclaw-message-bubble .claw-card--dark .claw-kpi__value { color: #fff; font-size: 18px; }
.aclaw-message-bubble .claw-card--dark .claw-body,
.aclaw-message-bubble .claw-card--dark .claw-body--muted { color: rgba(255,255,255,0.85); }

.aclaw-message-bubble .claw-ring {
  position: relative;
  width: 140px; height: 140px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) 0% calc(var(--p, 0) * 1%), var(--grey-200, rgba(127,127,127,0.16)) calc(var(--p, 0) * 1%) 100%);
  display: grid; place-items: center;
}
.aclaw-message-bubble .claw-ring[data-tone="s"] { background: conic-gradient(var(--success) 0% calc(var(--p, 0) * 1%), var(--grey-200, rgba(127,127,127,0.16)) calc(var(--p, 0) * 1%) 100%); }
.aclaw-message-bubble .claw-ring[data-tone="w"] { background: conic-gradient(var(--warning) 0% calc(var(--p, 0) * 1%), var(--grey-200, rgba(127,127,127,0.16)) calc(var(--p, 0) * 1%) 100%); }
.aclaw-message-bubble .claw-ring[data-tone="d"] { background: conic-gradient(var(--danger) 0% calc(var(--p, 0) * 1%), var(--grey-200, rgba(127,127,127,0.16)) calc(var(--p, 0) * 1%) 100%); }
.aclaw-message-bubble .claw-ring__c {
  position: absolute;
  inset: 12px;
  background: var(--grey-0, #fff);
  border-radius: 50%;
  display: grid; place-items: center;
  text-align: center;
}

.aclaw-message-bubble .claw-bar {
  height: 8px;
  background: var(--grey-200, rgba(127,127,127,0.16));
  border-radius: 4px;
  overflow: hidden;
}
.aclaw-message-bubble .claw-bar__fill {
  height: 100%;
  background: linear-gradient(90deg, var(--success), color-mix(in srgb, var(--success) 55%, white));
  border-radius: 4px;
}
.aclaw-message-bubble .claw-bar__fill[data-tone="i"] { background: linear-gradient(90deg, var(--info), color-mix(in srgb, var(--info) 50%, white)); }
.aclaw-message-bubble .claw-bar__fill[data-tone="w"] { background: linear-gradient(90deg, var(--warning), color-mix(in srgb, var(--warning) 60%, white)); }
.aclaw-message-bubble .claw-bar__fill[data-tone="d"] { background: linear-gradient(90deg, var(--danger), color-mix(in srgb, var(--danger) 50%, white)); }
.aclaw-message-bubble .claw-bar__fill[data-tone="b"] { background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 70%, white)); }

.aclaw-message-bubble .claw-stages {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 4px;
}
.aclaw-message-bubble .claw-stage {
  height: 6px;
  border-radius: 3px;
  background: var(--grey-200, rgba(127,127,127,0.16));
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  font-size: 0;
}
.aclaw-message-bubble .claw-stage[data-state="done"]    { background: var(--success); border-color: transparent; }
.aclaw-message-bubble .claw-stage[data-state="active"]  { background: linear-gradient(90deg, var(--warning), color-mix(in srgb, var(--warning) 60%, white)); border-color: transparent; animation: claw-shimmer 2s infinite; }
.aclaw-message-bubble .claw-stage[data-state="pending"] { background: var(--grey-200, rgba(127,127,127,0.16)); }

.aclaw-message-bubble .claw-spark { width: 100%; height: 32px; display: block; }
.aclaw-message-bubble .claw-donut { width: 120px; height: 120px; display: block; }

.aclaw-message-bubble .claw-tl {
  position: relative;
  padding-left: 32px;
  display: grid;
  gap: 18px;
}
.aclaw-message-bubble .claw-tl__line {
  position: absolute;
  left: 9px; top: 8px; bottom: 8px;
  width: 2px;
  background: linear-gradient(180deg, var(--success) 0%, var(--accent) 50%, var(--grey-300, rgba(127,127,127,0.32)) 100%);
  border-radius: 1px;
}
.aclaw-message-bubble .claw-tl > div { position: relative; display: grid; gap: 4px; }
.aclaw-message-bubble .claw-tl__dot {
  position: absolute;
  left: -29px; top: 4px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--grey-0, #fff);
  border: 3px solid var(--grey-400, #bbbec3);
}
.aclaw-message-bubble .claw-tl__dot[data-state="done"]   { border-color: var(--success); box-shadow: 0 0 0 4px color-mix(in srgb, var(--success) 12%, transparent); }
.aclaw-message-bubble .claw-tl__dot[data-state="next"]   { border-color: var(--warning); box-shadow: 0 0 0 4px color-mix(in srgb, var(--warning) 12%, transparent); animation: claw-pulse 2s infinite; }
.aclaw-message-bubble .claw-tl__dot[data-state="active"] { border-color: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 12%, transparent); }

/* w10/C10 — the callout family on SEMANTIC tokens (dark mode by construction:
   the tokens re-bind, the washes are color-mix over transparent, so no
   hand-maintained dark twin exists for callouts anymore). */
.aclaw-message-bubble .claw-callout {
  padding: 14px 18px;
  border-left: 3px solid var(--info);
  border-radius: 6px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--info) 8%, transparent), transparent);
}
.aclaw-message-bubble .claw-callout > p { margin: 0; font-size: 13px; line-height: 1.55; color: var(--info); }
.aclaw-message-bubble .claw-callout[data-tone="s"]      { border-left-color: var(--success); background: linear-gradient(90deg, color-mix(in srgb, var(--success) 8%, transparent), transparent); }
.aclaw-message-bubble .claw-callout[data-tone="s"] > p  { color: var(--success); }
.aclaw-message-bubble .claw-callout[data-tone="w"]      { border-left-color: var(--warning); background: linear-gradient(90deg, color-mix(in srgb, var(--warning) 8%, transparent), transparent); }
.aclaw-message-bubble .claw-callout[data-tone="w"] > p  { color: var(--warning); }
.aclaw-message-bubble .claw-callout[data-tone="d"]      { border-left-color: var(--danger); background: linear-gradient(90deg, color-mix(in srgb, var(--danger) 8%, transparent), transparent); }
.aclaw-message-bubble .claw-callout[data-tone="d"] > p  { color: var(--danger); }

/* ─── Dark-theme catalog overrides ──────────────────────────────────────
 * EMPTY by construction (Wave 2, C-spec §2.3): every toned family above rides
 * the semantic tokens (which re-bind in dark) + color-mix washes over
 * transparent, and the neutral greys invert via the able-claw dark block —
 * so no hand-maintained dark twin remains. Add one back ONLY for deliberate
 * dark-tuning, never for parity. */

.aclaw-message-bubble .claw-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}
.aclaw-message-bubble .claw-chip {
  padding: 7px 14px;
  font-size: 12px; font-weight: 600;
  color: var(--grey-900, inherit);
  background: var(--grey-0, #fff);
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  border-radius: 18px;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  font-family: inherit;
}
.aclaw-message-bubble .claw-chip:hover {
  background: var(--grey-100, rgba(127,127,127,0.06));
}

.aclaw-message-bubble .claw-person {
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 14px;
  align-items: center;
  padding: 14px;
  background: var(--grey-0, #fff);
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  border-radius: 10px;
}
/* Avatars — the default rides the brand accent; the five NAMED tones are
   decorative IDENTITY hues (a person keeps their color in both modes), so
   they are fixed oklch — mode-independent by design, like badges. */
.aclaw-message-bubble .claw-avatar {
  width: 48px; height: 48px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: #fff;
  font-size: 16px; font-weight: 700;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 72%, white));
}
.aclaw-message-bubble .claw-avatar[data-tone="teal"]  { background: linear-gradient(135deg, oklch(70% 0.12 215), oklch(61% 0.11 220)); }
.aclaw-message-bubble .claw-avatar[data-tone="pink"]  { background: linear-gradient(135deg, oklch(66% 0.21 356), oklch(64% 0.21 16)); }
.aclaw-message-bubble .claw-avatar[data-tone="amber"] { background: linear-gradient(135deg, oklch(76% 0.16 70), oklch(70% 0.19 48)); }
.aclaw-message-bubble .claw-avatar[data-tone="green"] { background: linear-gradient(135deg, oklch(70% 0.15 163), oklch(60% 0.13 164)); }
.aclaw-message-bubble .claw-avatar[data-tone="slate"] { background: linear-gradient(135deg, oklch(55% 0.03 255), oklch(68% 0.03 255)); }

.aclaw-message-bubble .claw-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.aclaw-message-bubble .claw-link {
  color: var(--info);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 1px solid color-mix(in srgb, var(--info) 30%, transparent);
}
.aclaw-message-bubble .claw-link:hover { border-bottom-color: var(--info); }
.aclaw-message-bubble .claw-btn {
  display: inline-block;
  padding: 10px 20px;
  font-size: 13px; font-weight: 600;
  border-radius: 8px;
  text-decoration: none;
  font-family: inherit;
  color: var(--on-accent, #fff);
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 85%, black));
  box-shadow: 0 2px 4px color-mix(in srgb, var(--accent) 25%, transparent);
  border: 0;
}
.aclaw-message-bubble .claw-btn--sec {
  color: var(--grey-900, inherit);
  background: var(--grey-0, #fff);
  border: 1px solid var(--grey-300, rgba(127,127,127,0.20));
  box-shadow: none;
}

.aclaw-message-bubble .claw-code {
  font-family: var(--font-mono, Menlo, monospace);
  font-size: 12px;
  padding: 2px 7px;
  background: var(--grey-200, rgba(127,127,127,0.16));
  border-radius: 4px;
  color: var(--grey-800, inherit);
  font-variant-numeric: tabular-nums;
}

/* Universal inline tone — paint any <strong>/<em>/<span>/<code> with semantic color
   by setting data-tone="s|i|w|d|b". Use for in-prose loss/gain values, callout-able
   inline text, anywhere the agent used to inline-style color hex. The blueprint
   sanitizer strips inline style="color:...", so this attribute is the supported path. */
.aclaw-message-bubble strong[data-tone="s"],
.aclaw-message-bubble em[data-tone="s"],
.aclaw-message-bubble span[data-tone="s"],
.aclaw-message-bubble code[data-tone="s"] { color: var(--success); }
.aclaw-message-bubble strong[data-tone="i"],
.aclaw-message-bubble em[data-tone="i"],
.aclaw-message-bubble span[data-tone="i"],
.aclaw-message-bubble code[data-tone="i"] { color: var(--info); }
.aclaw-message-bubble strong[data-tone="w"],
.aclaw-message-bubble em[data-tone="w"],
.aclaw-message-bubble span[data-tone="w"],
.aclaw-message-bubble code[data-tone="w"] { color: var(--warning); }
.aclaw-message-bubble strong[data-tone="d"],
.aclaw-message-bubble em[data-tone="d"],
.aclaw-message-bubble span[data-tone="d"],
.aclaw-message-bubble code[data-tone="d"] { color: var(--danger); }
.aclaw-message-bubble strong[data-tone="b"],
.aclaw-message-bubble em[data-tone="b"],
.aclaw-message-bubble span[data-tone="b"],
.aclaw-message-bubble code[data-tone="b"] { color: var(--accent); }
.aclaw-message-bubble strong[data-tone="n"],
.aclaw-message-bubble em[data-tone="n"],
.aclaw-message-bubble span[data-tone="n"],
.aclaw-message-bubble code[data-tone="n"] { color: var(--grey-500, #66686b); }

/* Tone modifier on body paragraphs — same shape as KPI/pill */
.aclaw-message-bubble .claw-body[data-tone="d"],
.aclaw-message-bubble .claw-body--muted[data-tone="d"] { color: var(--danger); }
.aclaw-message-bubble .claw-body[data-tone="s"],
.aclaw-message-bubble .claw-body--muted[data-tone="s"] { color: var(--success); }
.aclaw-message-bubble .claw-body[data-tone="w"],
.aclaw-message-bubble .claw-body--muted[data-tone="w"] { color: var(--warning); }


/* able-connections */

able-connections { display: block; }
able-connections .acn {
  position: relative;
  max-width: 960px; margin: 0 auto;
  padding: var(--space-6, 24px) var(--space-4, 16px) var(--space-10, 40px);
  padding-left: max(var(--space-4, 16px), var(--safe-left, 0px));
  padding-right: max(var(--space-4, 16px), var(--safe-right, 0px));
  font-family: var(--font-sans, system-ui, -apple-system, sans-serif);
  color: var(--text-primary, #1d1c17);
}
able-connections .acn-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
able-connections .acn-head { margin-bottom: var(--space-6, 24px); }
able-connections .acn-title {
  margin: 0; font-size: var(--font-2xl, 24px); font-weight: 700; letter-spacing: -0.01em;
  color: var(--text-primary, #1d1c17);
}
able-connections .acn-lede {
  margin: var(--space-2, 8px) 0 0; font-size: var(--font-base, 15px); line-height: 1.55;
  color: var(--text-secondary, #3f3f46); max-width: 60ch;
}

/* ── sections ── */
able-connections .acn-section { margin-bottom: var(--space-8, 32px); }
able-connections .acn-section-head {
  display: flex; align-items: center; gap: var(--space-3, 12px);
}
able-connections .acn-section-title {
  margin: 0; font-size: var(--font-lg, 17px); font-weight: 650;
  color: var(--text-primary, #1d1c17);
}
able-connections .acn-count {
  display: inline-flex; align-items: center; min-height: 22px; padding: 0 9px;
  border-radius: var(--radius-full, 999px); font-size: var(--font-xs, 12px); font-weight: 600;
  background: var(--surface-subtle, #f1f5f9); color: var(--text-muted, #6b7280);
}
able-connections .acn-count--bad {
  background: var(--danger-soft, #fee2e2); color: var(--danger, #b91c1c);
}
able-connections .acn-section-note {
  margin: var(--space-1, 4px) 0 var(--space-4, 16px);
  font-size: var(--font-sm, 13.5px); line-height: 1.5;
  color: var(--text-muted, #6b7280); max-width: 62ch;
}

/* ── cards ── */
able-connections .acn-grid { display: grid; gap: var(--space-3, 12px); grid-template-columns: 1fr; }
@media (min-width: 768px) {
  able-connections .acn-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
able-connections .acn-card {
  display: flex; flex-direction: column; min-width: 0;
  border: 1px solid var(--border-default, #e5e7eb);
  border-radius: var(--radius-lg, 12px);
  background: var(--surface-card, #fff);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
@media (hover: hover) and (pointer: fine) {
  able-connections .acn-card:hover {
    border-color: var(--border-strong, #d6d8db);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, .06));
  }
}
able-connections .acn-card[data-busy] { opacity: .6; pointer-events: none; }
able-connections .acn-card-main {
  display: flex; flex-direction: column; gap: var(--space-2, 8px);
  width: 100%; min-height: 44px; text-align: left; cursor: pointer;
  padding: var(--space-4, 16px); border: 0; border-radius: var(--radius-lg, 12px);
  background: transparent; font: inherit; color: inherit;
}
able-connections .acn-card-main:focus-visible {
  outline: 2px solid var(--accent, #1b2a4a); outline-offset: -2px;
}
able-connections .acn-card-top {
  display: flex; align-items: center; gap: var(--space-2, 8px); min-width: 0;
}
able-connections .acn-card-name {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--font-base, 15px); font-weight: 640; color: var(--text-primary, #1d1c17);
}
able-connections .acn-chevron { flex: 0 0 auto; width: 16px; height: 16px; color: var(--text-subtle, #9ca3af); }
able-connections .acn-chevron svg { width: 16px; height: 16px; display: block; }
able-connections .acn-meta {
  display: flex; flex-wrap: wrap; gap: 4px 8px; min-width: 0;
  font-size: var(--font-sm, 13px); color: var(--text-muted, #6b7280);
}
able-connections .acn-meta-item {
  display: inline-flex; align-items: center; gap: 8px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
/* Separate the facts. Without it "Google" + "Workspace" run together and read as
   the single product name "Google Workspace" — but they are two different facts:
   the service, and what this particular grant covers.
   NOTE the LITERAL middot, never a unicode escape: this CSS ships two ways — the
   JS template literal injected at runtime (which would unescape it) and the raw
   source text lifted into able-runtime.css by the bundle extractor (which would
   not). An escape makes those two paths disagree; a literal character cannot. */
able-connections .acn-meta-item + .acn-meta-item::before {
  content: "·"; color: var(--text-subtle, #9ca3af); flex: none;
}

/* ── status ── */
able-connections .acn-status {
  display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
  font-size: var(--font-sm, 13px); font-weight: 600;
}
able-connections .acn-dot { width: 8px; height: 8px; border-radius: var(--radius-full, 999px); background: currentColor; }
able-connections .acn-status[data-tone="good"]    { color: var(--success, #15803d); }
able-connections .acn-status[data-tone="bad"]     { color: var(--danger, #b91c1c); }
able-connections .acn-status[data-tone="neutral"] { color: var(--text-muted, #6b7280); }

/* ── buttons ── */
able-connections .acn-card-actions,
able-connections .acn-detail-actions {
  display: flex; flex-wrap: wrap; gap: var(--space-2, 8px);
  padding: 0 var(--space-4, 16px) var(--space-4, 16px);
}
able-connections .acn-detail-actions { padding: var(--space-5, 20px) 0 0; }
able-connections .acn-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 44px; padding: 0 var(--space-4, 16px); cursor: pointer;
  border: 1px solid var(--border-default, #e5e7eb); border-radius: var(--radius-md, 8px);
  background: var(--surface-card, #fff); color: var(--text-primary, #1d1c17);
  font-family: inherit; font-size: var(--font-sm, 13.5px); font-weight: 600;
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
}
able-connections .acn-btn svg { width: 15px; height: 15px; }
able-connections .acn-btn:disabled { opacity: .55; cursor: default; }
able-connections .acn-btn:focus-visible { outline: 2px solid var(--accent, #1b2a4a); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  able-connections .acn-btn:not(:disabled):hover {
    background: var(--surface-hover, #f8f8f9); border-color: var(--border-strong, #d6d8db);
  }
}
able-connections .acn-btn--primary {
  background: var(--accent, #1b2a4a); border-color: var(--accent, #1b2a4a);
  color: var(--on-accent, #fff);
}
@media (hover: hover) and (pointer: fine) {
  able-connections .acn-btn--primary:not(:disabled):hover {
    background: var(--accent-hover, #16223d); border-color: var(--accent-hover, #16223d);
  }
}
/* Secondary, but still visibly a BUTTON. It used to be borderless + transparent,
   which read as inert grey text sitting next to a real control — nobody should
   have to guess whether "Turn off" is clickable. Muted text keeps the hierarchy
   under Reconnect without giving up the affordance. */
able-connections .acn-btn--quiet { color: var(--text-secondary, #3f3f46); }
@media (hover: hover) and (pointer: fine) {
  able-connections .acn-btn--quiet:not(:disabled):hover {
    background: var(--surface-hover, #f8f8f9); color: var(--text-primary, #1d1c17);
  }
}

/* ── detail ── */
able-connections .acn-back {
  display: inline-flex; align-items: center; gap: 7px; min-height: 44px;
  margin-bottom: var(--space-2, 8px); padding: 0 var(--space-2, 8px) 0 0;
  border: 0; background: transparent; cursor: pointer; font-family: inherit;
  font-size: var(--font-sm, 13.5px); font-weight: 600; color: var(--text-secondary, #3f3f46);
}
able-connections .acn-back svg { width: 16px; height: 16px; }
able-connections .acn-back:focus-visible { outline: 2px solid var(--accent, #1b2a4a); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  able-connections .acn-back:hover { color: var(--text-primary, #1d1c17); }
}
able-connections .acn-detail {
  border: 1px solid var(--border-default, #e5e7eb); border-radius: var(--radius-lg, 12px);
  background: var(--surface-card, #fff); padding: var(--space-5, 20px);
}
able-connections .acn-detail-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3, 12px);
}
able-connections .acn-detail-title {
  margin: 0; font-size: var(--font-xl, 20px); font-weight: 680; min-width: 0;
  color: var(--text-primary, #1d1c17);
}
able-connections .acn-detail-note {
  margin: var(--space-2, 8px) 0 0; font-size: var(--font-sm, 13.5px); line-height: 1.55;
  color: var(--text-muted, #6b7280);
}
able-connections .acn-banner {
  display: flex; gap: var(--space-3, 12px); align-items: flex-start;
  margin-top: var(--space-4, 16px); padding: var(--space-3, 12px) var(--space-4, 16px);
  border-radius: var(--radius-md, 8px); font-size: var(--font-sm, 13.5px); line-height: 1.55;
}
able-connections .acn-banner[data-tone="bad"] {
  background: var(--danger-soft, #fee2e2); color: var(--danger, #b91c1c);
}
able-connections .acn-banner-ico { flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px; }
able-connections .acn-banner-ico svg { width: 18px; height: 18px; display: block; }
able-connections .acn-banner-detail { opacity: .85; }
able-connections .acn-facts {
  display: grid; gap: var(--space-3, 12px); margin: var(--space-5, 20px) 0 0;
  grid-template-columns: 1fr;
}
@media (min-width: 600px) { able-connections .acn-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
able-connections .acn-fact { min-width: 0; }
able-connections .acn-fact dt {
  font-size: var(--font-xs, 11.5px); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-subtle, #9ca3af);
}
able-connections .acn-fact dd {
  margin: 3px 0 0; font-size: var(--font-sm, 14px); line-height: 1.5; min-width: 0;
  overflow-wrap: anywhere; color: var(--text-primary, #1d1c17);
}

/* ── empty + error ── */
able-connections .acn-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-4, 16px); padding: var(--space-10, 40px) var(--space-4, 16px);
  border: 1px dashed var(--border-default, #e5e7eb); border-radius: var(--radius-lg, 12px);
  background: var(--surface-subtle, #f1f5f9);
}
able-connections .acn-empty h3 {
  margin: 0; font-size: var(--font-lg, 17px); font-weight: 650; color: var(--text-primary, #1d1c17);
}
able-connections .acn-empty p {
  margin: 0; max-width: 46ch; font-size: var(--font-sm, 14px); line-height: 1.6;
  color: var(--text-muted, #6b7280);
}
able-connections .acn-empty-ico { width: 40px; height: 40px; color: var(--text-subtle, #9ca3af); }
able-connections .acn-empty-ico svg { width: 40px; height: 40px; display: block; }
able-connections .acn-empty--bad { border-style: solid; border-color: var(--border-default, #e5e7eb); }
able-connections .acn-empty--bad .acn-empty-ico { color: var(--danger, #b91c1c); }

/* ── skeleton ── */
able-connections .acn-skel { padding: var(--space-4, 16px); gap: var(--space-2, 8px); }
able-connections .acn-skel-line {
  height: 12px; border-radius: var(--radius-sm, 4px);
  background: var(--surface-hover, #f0f1f2); animation: acn-pulse 1.4s ease-in-out infinite;
}
able-connections .acn-skel-line--title { width: 45%; height: 15px; }
able-connections .acn-skel-line--meta  { width: 70%; }
able-connections .acn-skel-line--pill  { width: 28%; }
@keyframes acn-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  able-connections .acn-skel-line { animation: none; }
  able-connections .acn-card, able-connections .acn-btn { transition: none; }
}


/* able-login */

able-login {
  display: block;
  width: 100%;
  justify-self: stretch;
  min-height: 100vh;
  background: var(--login-bg, var(--surface-base, #f5f7fa));
  color: var(--text-primary, #0f172a);
}
.alogin-shell {
  width: 100%;            /* explicit; was implicit-inherited */
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  box-sizing: border-box;
}
.alogin-card {
  width: 100%;
  /* clamp to keep mobile gap + cap desktop width; was 420px fixed */
  max-width: var(--login-card-max-width, min(440px, calc(100vw - 32px)));
  padding: var(--login-card-padding, clamp(20px, 4vw, 32px));
  background: var(--login-card-bg, var(--surface-card, #ffffff));
  border-radius: var(--login-card-radius, 12px);
  box-shadow: var(--login-card-shadow, 0 10px 40px rgba(0, 0, 0, 0.08));
  box-sizing: border-box;
}
.alogin-brand {
  display: flex;
  justify-content: center;
  margin-bottom: 16px;
}
.alogin-brand-img {
  /* viewport-aware logo sizing — was fixed 56px */
  max-height: clamp(48px, 8vw, 72px);
  max-width: 240px;
  height: auto;
  width: auto;
  display: block;
  object-fit: contain;
}
.alogin-title {
  margin: 0 0 24px 0;
  font-size: 20px;
  font-weight: 700;
  text-align: center;
  letter-spacing: 0.04em;
  color: var(--text-primary, #0f172a);
}
.alogin-form { display: flex; flex-direction: column; gap: 14px; }
.alogin-form.is-hidden { display: none; }
.alogin-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
}
.alogin-label-text {
  font-weight: 600;
  color: var(--text-primary, #0f172a);
  opacity: 0.85;
}
.alogin-input {
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px;
  min-height: 44px;       /* WCAG 2.2 AA touch target — was 39px */
  border: 1px solid var(--login-input-border, var(--border-default, #cbd5e1));
  border-radius: var(--login-input-radius, 8px);
  /* 16px MINIMUM — anything smaller triggers iOS Safari's auto-zoom on focus,
   * which causes a jarring viewport jump on every login. */
  font-size: 16px;
  line-height: 1.4;
  background: var(--surface-card, #ffffff);
  color: var(--text-primary, #0f172a);
  transition: border-color 120ms, box-shadow 120ms;
}
.alogin-input:focus {
  outline: none;
  border-color: var(--login-button-bg, var(--accent, #2563eb));
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
.alogin-input-otp {
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 24px;
  letter-spacing: 8px;
  text-align: center;
}
.alogin-passkey-prompt {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  margin-top: 8px;
  background: var(--surface-card, #ffffff);
  border: 1px solid var(--border-default, #e2e8f0);
  border-radius: var(--login-input-radius, 8px);
}
.alogin-passkey-prompt.is-hidden { display: none; }
.alogin-passkey-prompt-title {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary, #0f172a);
}
.alogin-passkey-prompt-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-primary, #0f172a);
  opacity: 0.75;
}
.alogin-passkey-prompt-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}
.alogin-passkey-prompt-actions .alogin-submit { flex: 1; margin: 0; }
.alogin-passkey-prompt-actions .alogin-back { flex: 1; margin: 0; min-height: 44px; }
.alogin-passkey {
  margin-top: 4px;
  padding: 12px 16px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--border-default, #cbd5e1);
  border-radius: var(--login-input-radius, 8px);
  background: var(--surface-card, #ffffff);
  color: var(--text-primary, #0f172a);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms;
}
.alogin-passkey:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.03);
  border-color: var(--text-primary, #94a3b8);
}
.alogin-passkey:disabled { opacity: 0.6; cursor: not-allowed; }
.alogin-passkey.is-primary {
  background: var(--login-button-bg, var(--accent, #2563eb));
  color: var(--login-button-color, #ffffff);
  border-color: transparent;
}
.alogin-passkey.is-primary:hover:not(:disabled) {
  background: var(--login-button-bg-hover, var(--accent-hover, #1d4ed8));
  border-color: transparent;
}
.alogin-passkey-fallback {
  display: block;
  margin-top: 6px;
  font-size: 12px;
  text-align: center;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--login-link-color, var(--accent, #2563eb));
}
.alogin-passkey-fallback:hover { text-decoration: underline; }
.alogin-remember {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  user-select: none;
  cursor: pointer;
}
.alogin-remember input[type="checkbox"] {
  margin: 0;
  cursor: pointer;
}
.alogin-submit {
  margin-top: 4px;
  padding: 12px 16px;
  min-height: 48px;       /* 48px on mobile feels right for thumb taps */
  border: 0;
  border-radius: var(--login-input-radius, 8px);
  background: var(--login-button-bg, var(--accent, #2563eb));
  color: var(--login-button-color, #ffffff);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 120ms, transform 80ms;
}
.alogin-submit:hover:not(:disabled) {
  background: var(--login-button-bg-hover, var(--accent-hover, #1d4ed8));
}
.alogin-submit:active:not(:disabled) { transform: translateY(1px); }
.alogin-submit:disabled { opacity: 0.6; cursor: not-allowed; }
.alogin-back {
  margin-top: 4px;
  padding: 8px 12px;
  background: transparent;
  color: var(--login-link-color, var(--accent, #2563eb));
  border: 0;
  font-size: 13px;
  cursor: pointer;
  text-align: center;
}
.alogin-back:hover { text-decoration: underline; }
.alogin-hint {
  margin: 0 0 6px 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-primary, #0f172a);
  opacity: 0.8;
}
.alogin-hint.is-hidden { display: none; }
.alogin-qr {
  display: flex;
  justify-content: center;
  padding: 12px;
  background: #ffffff;
  border-radius: 8px;
  border: 1px solid var(--border-default, #e2e8f0);
}
.alogin-qr.is-hidden { display: none; }
.alogin-qr-img { width: 200px; height: 200px; display: block; }
.alogin-error {
  margin: 12px 0 0 0;
  padding: 8px 12px;
  font-size: 13px;
  border-radius: 6px;
  background: rgba(220, 38, 38, 0.08);
  color: var(--login-error-color, #dc2626);
  border: 1px solid rgba(220, 38, 38, 0.2);
  display: none;
}
.alogin-error.is-visible { display: block; }
.alogin-forgot {
  display: block;
  margin-top: 14px;
  font-size: 13px;
  text-align: center;
  color: var(--login-link-color, var(--accent, #2563eb));
  text-decoration: none;
}
.alogin-forgot:hover { text-decoration: underline; }
.alogin-divider {
  display: flex;
  align-items: center;
  margin: 20px 0 16px 0;
  font-size: 12px;
  color: var(--text-primary, #0f172a);
  opacity: 0.6;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.alogin-divider::before, .alogin-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border-default, #e2e8f0);
}
.alogin-divider::before { margin-right: 12px; }
.alogin-divider::after  { margin-left: 12px; }
.alogin-alternatives { display: flex; flex-direction: column; gap: 8px; }
.alogin-alt-button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 14px;
  min-height: 44px;       /* WCAG 2.2 AA touch target */
  border: 1px solid var(--border-default, #cbd5e1);
  border-radius: var(--login-input-radius, 8px);
  background: var(--surface-card, #ffffff);
  color: var(--text-primary, #0f172a);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms;
  text-decoration: none;
}
.alogin-alt-button:hover {
  background: rgba(0, 0, 0, 0.03);
  border-color: var(--text-primary, #94a3b8);
}
.alogin-alt-icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
  align-items: center;
  justify-content: center;
  font-size: 16px;
}
.alogin-footer {
  margin-top: 20px;
  text-align: center;
  font-size: 12px;
  color: var(--text-primary, #64748b);
  opacity: 0.75;
}
.alogin-footer a {
  color: var(--login-link-color, var(--accent, #2563eb));
  text-decoration: none;
}
.alogin-footer a:hover { text-decoration: underline; }

/* Theme variant: dark */
able-login[theme-variant="dark"] {
  background: var(--login-bg, #0f172a);
  color: #e2e8f0;
}
able-login[theme-variant="dark"] .alogin-card {
  background: var(--login-card-bg, #1e293b);
}
able-login[theme-variant="dark"] .alogin-input {
  background: #0f172a;
  color: #e2e8f0;
  border-color: var(--login-input-border, #334155);
}
able-login[theme-variant="dark"] .alogin-alt-button {
  background: #1e293b;
  color: #e2e8f0;
  border-color: #334155;
}
able-login[theme-variant="dark"] .alogin-alt-button:hover {
  background: #283549;
}

/* Theme variant: brand-purple */
able-login[theme-variant="brand-purple"] {
  --login-button-bg: #7c3aed;
  --login-button-bg-hover: #6d28d9;
  --login-link-color: #7c3aed;
}

@media (max-width: 480px) {
  /* Mobile shell: hug the top with a comfortable gutter, let the card take
   * the available width minus 16px each side. */
  .alogin-shell { padding: 16px; align-items: flex-start; padding-top: 32px; }
  .alogin-card  {
    padding: 28px 20px;
    /* Override the desktop clamp so we always size to viewport-minus-gutter
     * on small phones (overrides the min(440px, calc(100vw - 32px)) above). */
    max-width: var(--login-card-max-width, calc(100vw - 32px));
  }
  .alogin-title { font-size: 18px; margin-bottom: 20px; }
}


/* able-notification-bell */

/* ── Colour contract (read before changing any colour here) ───────────────────
   FOREGROUND / GRAPHIC roles (text, icon stroke, link, the unread dot, a focus
   ring) MUST stay legible in BOTH themes. --accent (#1b2a4a) and
   --accent-secondary (#1d4ed8) do NOT re-bind in the dark theme, so either of
   them BARE on a dark surface lands around 2.4:1 — a WCAG failure. The
   theme-sanctioned chain for a brand-tinted foreground is
   var(--login-link-color, var(--accent, ...)): --login-link-color exists only
   in the dark block (#93c5fd) and falls through to --accent in light, exactly
   so a blueprint gets a visible-on-dark colour without every tenant having to
   redefine its brand. Informational graphics use --info (which DOES re-bind).
   SOLID FILL roles (the badge pill) keep the brand token and pair it with the
   matching --on-* token: the COUNT is what has to be readable, and white on
   #1d4ed8 is 6.70:1 in both themes. The pill's own edge against a dark shell is
   low-contrast by nature — that is what --anb-badge-ring is for (a host sets it
   to its chrome colour to halo the pill). Never a bare hex outside a var()
   fallback. */
able-notification-bell { display: inline-flex; }

/* The trigger — deliberately minimal. Host shells own the button chrome
   (background, size, colour) via their own scoped CSS; this only guarantees
   the badge has a positioning context and the icon is centred. */
.anb-btn {
  position: relative;
  display: inline-grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: 9px;
  background: transparent; color: currentColor;
  cursor: pointer;
}
.anb-btn svg { width: 18px; height: 18px; }

.anb-badge {
  position: absolute;
  top: var(--anb-badge-top, 2px); right: var(--anb-badge-right, 2px); z-index: 1;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  /* SOLID FILL — the brand token stays; the label rides its on-token. */
  background: var(--accent-secondary, var(--danger, #b91c1c));
  color: var(--on-accent-secondary, #fff);
  font-size: 9.5px; font-weight: 800; line-height: 16px; text-align: center;
  box-shadow: 0 0 0 2px var(--anb-badge-ring, transparent);
  pointer-events: none;
}
.anb-badge[hidden] { display: none; }

/* ── The panel (singleton, appended to <body>) ─────────────────────────── */
.anb-panel[hidden] { display: none; }
.anb-panel {
  /* The bell IS a popover, so it rides the popover tier of the platform scale
     rather than a raw 900 (which is --z-tooltip, the top of the scale, and
     would let the panel paint over anything a shell layers above it). A shell
     with genuine fleet stacking needs sets --anb-z. */
  position: fixed; z-index: var(--anb-z, var(--z-popover, 800));
  width: var(--anb-panel-width, 400px); max-height: min(74dvh, 660px);
  display: flex; flex-direction: column;
  background: var(--surface-card, #fff);
  border: 1px solid var(--border-default, #e5e7eb);
  border-radius: 12px; overflow: hidden;
  box-shadow: var(--shadow-xl, 0 16px 48px rgba(15, 23, 42, .22));
}
.anb-h {
  display: flex; align-items: center; gap: 8px; padding: 11px 14px;
  border-bottom: 1px solid var(--border-subtle, #f1f5f9);
}
.anb-h b { font-size: 13.5px; font-weight: 700; color: var(--text-primary, #1d1c17); }
.anb-count {
  font-size: 10px; font-weight: 700; padding: 1px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--login-link-color, var(--accent, #1b2a4a)) 14%, var(--surface-card, #fff));
  color: var(--login-link-color, var(--accent, #1b2a4a));
}
.anb-count[hidden] { display: none; }
.anb-close {
  margin-left: auto; background: none; border: 0; cursor: pointer; padding: 4px;
  color: var(--text-muted, #6b7280); border-radius: 6px;
  display: grid; place-items: center;
}
.anb-list { overflow-y: auto; flex: 1 1 auto; }

.anb-item {
  display: grid; grid-template-columns: 32px 1fr auto; gap: 10px; align-items: start;
  padding: 10px 12px 10px 14px; cursor: pointer; position: relative;
  border-bottom: 1px solid var(--border-subtle, #f1f5f9);
}
.anb-item:last-child { border-bottom: 0; }

/* ── Visited state (Facebook rows) ────────────────────────────────────────
   NOT-VISITED keeps a subtle brand tint until the user CLICKS it (persisted
   across opens + reloads by the localStorage ledger). NEW-since-seen adds the
   transient .anb-dot ON TOP (state 2 — the pre-open seenAt logic, independent of
   visited). VISITED (clicked) drops the tint and DIMS the parts — never a
   whole-row opacity, the timestamp must stay readable. The tint rides the
   dark-safe brand chain + color-mix against --surface-card, so it adapts to the
   dark theme automatically; --anb-unread-bg is the shell knob (see Styling hooks). */
.anb-item--unread {
  background: var(--anb-unread-bg, color-mix(in srgb, var(--login-link-color, var(--accent, #1d4ed8)) 7%, var(--surface-card, #fff)));
}
.anb-item--visited .anb-t { color: var(--text-secondary, #3f3f46); font-weight: 600; }
.anb-item--visited .anb-k { opacity: .7; }
.anb-item--visited .anb-s { color: var(--text-muted, #6b7280); }
.anb-item--visited .anb-ic { opacity: .55; }
.anb-ic {
  width: 30px; height: 30px; border-radius: 999px;
  display: grid; place-items: center; margin-top: 1px;
  background: color-mix(in srgb, var(--info, #1d4ed8) 12%, var(--surface-card, #fff));
  color: var(--info, #1d4ed8);
}
.anb-ic svg { width: 15px; height: 15px; }
.anb-ic--accent {
  /* --anb-accent is the shell knob: unset it falls through to the dark-safe
     brand chain (byte-identical render), set it recovers a brand accent tone.
     It MUST be dark-safe in the app's own theme (see the Styling hooks doc), and
     it deliberately does NOT reach .anb-count / .anb-f a — those are 10px TEXT
     kept on the always-dark-safe chain (a brand tint there re-fails AA). */
  background: color-mix(in srgb, var(--anb-accent, var(--login-link-color, var(--accent, #1b2a4a))) 14%, var(--surface-card, #fff));
  color: var(--anb-accent, var(--login-link-color, var(--accent, #1b2a4a)));
}
.anb-ic--info {
  background: color-mix(in srgb, var(--info, #1d4ed8) 12%, var(--surface-card, #fff));
  color: var(--info, #1d4ed8);
}
.anb-ic--warn {
  background: color-mix(in srgb, var(--warning, #b45309) 14%, var(--surface-card, #fff));
  color: var(--warning, #b45309);
}
.anb-ic--bad {
  background: color-mix(in srgb, var(--danger, #b91c1c) 12%, var(--surface-card, #fff));
  color: var(--danger, #b91c1c);
}
.anb-ic--good {
  background: color-mix(in srgb, var(--success, #15803d) 14%, var(--surface-card, #fff));
  color: var(--success, #15803d);
}
.anb-b { min-width: 0; }
.anb-t {
  font-size: 11px; font-weight: 700; color: var(--text-primary, #1d1c17);
  display: flex; align-items: center; gap: 6px;
}
/* The kind EYEBROW — the category word ("Past due") above the event's own headline.
   Rendered only when the tenant configured a label for the kind AND it says something the
   headline doesn't (see rowText); dm / agent rows never grow one. */
.anb-k {
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted, #6b7280); display: block; margin-bottom: 1px;
}
.anb-dot {
  /* The unread dot is a GRAPHIC, not a fill — it carries meaning on its own, so
     it follows the dark-safe foreground chain (recolourable via --anb-accent,
     which must itself stay dark-safe). */
  width: 7px; height: 7px; border-radius: 999px; flex: none;
  background: var(--anb-accent, var(--login-link-color, var(--accent, #1b2a4a)));
}
.anb-s {
  font-size: 11.5px; color: var(--text-secondary, #3f3f46); margin-top: 1px; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.anb-time { font-size: 10px; color: var(--text-muted, #6b7280); white-space: nowrap; margin-top: 2px; }
.anb-x {
  position: absolute; right: 8px; bottom: 8px;
  background: none; border: 0; cursor: pointer;
  padding: 3px; border-radius: 6px; color: var(--text-muted, #6b7280); display: none;
}
/* Keyboard parity: pointer users get the X on :hover (below), but a
   keyboard-only user never generates a hover — without this rule a row could
   be focused and read out yet never dismissed. Unconditional (NOT inside the
   hover media query) precisely because it serves the no-hover case. */
.anb-item:focus-within .anb-x { display: grid; }
.anb-item:focus-visible,
.anb-x:focus-visible,
.anb-close:focus-visible {
  outline: 2px solid var(--login-link-color, var(--accent, #1b2a4a));
  outline-offset: -2px;
}
@media (hover: hover) and (pointer: fine) {
  .anb-item:hover { background: var(--surface-hover, #f8f8f9); }
  /* An unread row brightens its own tint on hover (11% instead of 7%) rather
     than flipping to the neutral surface-hover — more specific, so it wins. */
  .anb-item--unread:hover {
    background: var(--anb-unread-bg, color-mix(in srgb, var(--login-link-color, var(--accent, #1d4ed8)) 11%, var(--surface-card, #fff)));
  }
  .anb-item:hover .anb-x { display: grid; }
  .anb-x:hover {
    color: var(--danger, #b91c1c);
    background: color-mix(in srgb, var(--danger, #b91c1c) 10%, transparent);
  }
  .anb-close:hover { color: var(--text-primary, #1d1c17); background: var(--surface-hover, #f8f8f9); }
}
@media (hover: none) { .anb-x { display: grid; } }

.anb-empty { padding: 26px 16px; text-align: center; font-size: 12px; color: var(--text-muted, #6b7280); }
.anb-f {
  padding: 9px 14px; border-top: 1px solid var(--border-subtle, #f1f5f9);
  display: flex; justify-content: center;
}
.anb-f[hidden] { display: none; }
.anb-f a {
  font-size: 11.5px; font-weight: 600; text-decoration: none;
  color: var(--login-link-color, var(--accent, #1b2a4a));
}

/* Below 820px the CSS owns the geometry (the JS bails out of positioning) —
   !important beats the inline left/top a previous desktop open left behind. */
@media (max-width: 820px) {
  .anb-panel {
    left: 8px !important; right: 8px; width: auto;
    top: var(--anb-mobile-top, 62px) !important;
    max-height: calc(100dvh - var(--anb-mobile-top, 62px) - 16px);
  }
}


/* able-offcanvas */

able-offcanvas {
  position: fixed; top: 0; bottom: 0;
  z-index: 201;
  background: var(--surface-card, #141415);
  color: var(--text-primary, #e2e8f0);
  box-shadow: -10px 0 30px rgba(0, 0, 0, 0.4);
  transform: translateX(100%);
  transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
  overflow: hidden;
  flex-direction: column;
}
able-offcanvas[data-position="right"] { right: 0; transform: translateX(100%); }
able-offcanvas[data-position="left"]  { left: 0;  transform: translateX(-100%); }
able-offcanvas[data-position="top"] {
  top: 0; left: 0; right: 0; bottom: auto;
  transform: translateY(-100%);
  height: auto; max-height: 80vh;
}
able-offcanvas[data-position="bottom"] {
  top: auto; left: 0; right: 0; bottom: 0;
  transform: translateY(100%);
  height: auto; max-height: 80vh;
}
able-offcanvas.aoff--open[data-position="right"],
able-offcanvas.aoff--open[data-position="left"]   { transform: translateX(0); }
able-offcanvas.aoff--open[data-position="top"],
able-offcanvas.aoff--open[data-position="bottom"] { transform: translateY(0); }
.aoff-backdrop {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(11, 15, 26, 0.55);
  opacity: 0; pointer-events: none;
  transition: opacity 220ms ease;
}
.aoff-backdrop--open { opacity: 1; pointer-events: auto; }
/* Close: red rounded-square with a bold white X, top-LEFT (restyled
   2026-06-10 to match the app's modal close buttons — was a Mac-style
   traffic-light dot). */
.aoff-close {
  position: absolute; top: 14px; left: 14px;
  width: 30px; height: 30px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: #ef4444; color: #ffffff;
  border: none;
  box-shadow: 0 2px 8px rgba(239, 68, 68, 0.35); cursor: pointer; padding: 0;
  font-size: 14px; font-weight: 700; line-height: 1;
  z-index: 10;
  transition: background 120ms ease, transform 120ms ease;
}
.aoff-close:hover { background: #dc2626; transform: scale(1.05); }
.aoff-close:active { background: #b91c1c; transform: scale(0.95); }
.aoff-close:focus-visible { outline: 2px solid #ef4444; outline-offset: 2px; }
/* Touch: expand the hit area to 44px (30 + 7 + 7) without enlarging the button. */
@media (pointer: coarse) {
  .aoff-close::after { content: ''; position: absolute; inset: -7px; }
}
/* Breadcrumb bar — visible ONLY when the panel holds stacked levels. Flow
   child above the content slot (the host flexes column when open). The
   left padding clears the absolute close button. */
.aoff-crumbs {
  display: none;
  flex: 0 0 auto;
  align-items: center;
  gap: 2px;
  padding: 13px 16px 11px 56px;
  border-bottom: 1px solid var(--border-default, rgba(127, 127, 127, 0.25));
  background: var(--surface-raised, rgba(127, 127, 127, 0.06));
  font-size: 12.5px;
  line-height: 1.2;
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: thin;
}
.aoff-crumbs--visible { display: flex; }
.aoff-crumb {
  flex: 0 0 auto;
  background: none; border: none;
  padding: 4px 6px; border-radius: 6px;
  font: inherit; color: var(--text-muted, #94a3b8);
  cursor: pointer;
  max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: background 120ms ease, color 120ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .aoff-crumb:hover {
    color: var(--text-primary, #e2e8f0);
    background: var(--surface-hover, rgba(127, 127, 127, 0.15));
  }
}
.aoff-crumb:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: 1px; }
.aoff-crumb--current {
  color: var(--text-primary, #e2e8f0);
  font-weight: 600;
  cursor: default;
  max-width: 280px;
}
.aoff-crumb-sep { flex: 0 0 auto; color: var(--text-subtle, #64748b); opacity: 0.65; padding: 0 2px; }
@media (pointer: coarse) {
  .aoff-crumb { min-height: 44px; display: inline-flex; align-items: center; }
}
.aoff-content {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  padding: 16px;
  box-sizing: border-box;
}
/* Stashed layers stay in the document (so reactive bindings + SSR state
   survive) but are fully hidden and inert. */
.aoff-layer[data-aoff-stashed] { display: none !important; }
/* Responsive: mobile bottom-sheet flip (responsive="auto" opt-in) */
able-offcanvas[data-position="bottom"].aoff-responsive-flipped {
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
  max-height: 90dvh;
  padding-bottom: max(0px, env(safe-area-inset-bottom));
}
able-offcanvas[data-position="bottom"].aoff-responsive-flipped .aoff-close {
  width: 44px;
  height: 44px;
  font-size: 22px;
}
/* Bottom-sheet: the enlarged 44px close button + the grab handle need more
   clearance than the desktop 56px. */
able-offcanvas[data-position="bottom"].aoff-responsive-flipped .aoff-crumbs {
  padding-left: 72px;
  padding-top: 16px;
}
able-offcanvas[data-position="bottom"].aoff-responsive-flipped::before {
  content: '';
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 40px;
  height: 4px;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 2px;
}
able-offcanvas[data-position="bottom"].aoff-responsive-flipped .aoff-content {
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}


/* able-payment-method */

able-payment-method { display: block; }
.apm {
  border: 0; padding: 0; margin: 0;
  display: flex; flex-direction: column;
  gap: 10px;
}
.apm-legend {
  padding: 0; margin: 0 0 12px;
  font-size: 13px; font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary, #3f3f46);
}
.apm-option {
  display: grid;
  grid-template-columns: auto 48px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1.5px solid var(--border-default, #e5e7eb);
  border-radius: 10px;
  cursor: pointer;
  background: var(--surface-base, #ffffff);
  transition: border-color 160ms ease, background 160ms ease;
  min-height: 64px;
}
.apm-option:hover {
  border-color: var(--accent, #1b2a4a);
  background: var(--surface-hover, #f8f8f9);
}
.apm-option[data-selected="true"] {
  border-color: var(--accent, #1b2a4a);
  background: var(--accent-soft, #dbeafe);
}
.apm-radio {
  appearance: none;
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 2px solid var(--border-strong, #d6d8db);
  background: var(--surface-base, #ffffff);
  margin: 0;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
}
.apm-radio:checked {
  border-color: var(--accent, #1b2a4a);
}
.apm-radio:checked::after {
  content: '';
  position: absolute;
  inset: 3px;
  background: var(--accent, #1b2a4a);
  border-radius: 50%;
}
.apm-logo {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 48px; height: 32px;
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.04em;
  background: var(--surface-subtle, #f1f5f9);
  color: var(--text-secondary, #3f3f46);
  border-radius: 6px;
  text-transform: uppercase;
  overflow: hidden;
}
.apm-logo--img { background: transparent; padding: 0; }
.apm-logo--img img, .apm-logo.apm-logo--img {
  object-fit: contain;
  max-width: 100%; max-height: 100%;
}
.apm-logo--mp { background: #009ee3; color: #fff; }
.apm-logo--oxxo { background: #e30613; color: #fff; }
.apm-logo--spei { background: #006341; color: #fff; }
.apm-logo--stripe { background: #635bff; color: #fff; }
.apm-logo--cc { background: #1d1d1f; color: #fff; }
.apm-logo--bank { background: #475569; color: #fff; }
.apm-logo--cash { background: #15803d; color: #fff; }
.apm-logo--apartado { background: #b45309; color: #fff; }
.apm-text {
  display: flex; flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.apm-label {
  font-size: 14px; font-weight: 600;
  color: var(--text-primary, #1d1c17);
}
.apm-desc {
  font-size: 12px;
  color: var(--text-muted, #6b7280);
  overflow: hidden; text-overflow: ellipsis;
}
.apm-badge {
  display: inline-flex;
  align-items: center;
  background: var(--success-soft, #dcfce7);
  color: var(--success, #15803d);
  font-size: 11px; font-weight: 600;
  padding: 2px 8px;
  border-radius: 10px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}
@media (max-width: 479px) {
  .apm-option {
    grid-template-columns: auto 40px 1fr;
    grid-template-areas:
      "radio logo text"
      ".     .    badge";
    padding: 12px;
    min-height: 56px;
  }
  .apm-radio { grid-area: radio; }
  .apm-logo { grid-area: logo; width: 40px; height: 28px; }
  .apm-text { grid-area: text; }
  .apm-badge {
    grid-area: badge;
    justify-self: end;
    margin-top: 4px;
  }
}


/* able-shipping-rate */

able-shipping-rate { display: block; }
.ashr {
  border: 0; padding: 0; margin: 0;
  display: flex; flex-direction: column;
  gap: 10px;
}
.ashr-legend {
  padding: 0; margin: 0 0 12px;
  font-size: 13px; font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary, #3f3f46);
}
.ashr-option {
  display: grid;
  grid-template-columns: auto 48px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1.5px solid var(--border-default, #e5e7eb);
  border-radius: 10px;
  cursor: pointer;
  background: var(--surface-base, #ffffff);
  transition: border-color 160ms ease, background 160ms ease;
  min-height: 64px;
}
.ashr-option:hover {
  border-color: var(--accent, #1b2a4a);
  background: var(--surface-hover, #f8f8f9);
}
.ashr-option[data-selected="true"] {
  border-color: var(--accent, #1b2a4a);
  background: var(--accent-soft, #dbeafe);
}
.ashr-radio {
  appearance: none;
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 2px solid var(--border-strong, #d6d8db);
  background: var(--surface-base, #ffffff);
  margin: 0;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
}
.ashr-radio:checked { border-color: var(--accent, #1b2a4a); }
.ashr-radio:checked::after {
  content: '';
  position: absolute; inset: 3px;
  background: var(--accent, #1b2a4a);
  border-radius: 50%;
}
.ashr-logo {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 48px; height: 32px;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.04em;
  background: var(--surface-subtle, #f1f5f9);
  color: var(--text-secondary, #3f3f46);
  border-radius: 6px;
  text-transform: uppercase;
}
.ashr-logo--img { background: transparent; padding: 0; }
.ashr-logo--estafeta { background: #ea0029; color: #fff; }
.ashr-logo--dhl { background: #fc0; color: #d40511; }
.ashr-logo--fedex { background: #4d148c; color: #ff6200; }
.ashr-logo--paquetexpress { background: #003e7e; color: #fff; }
.ashr-logo--99min { background: #ff5e2a; color: #fff; }
.ashr-logo--ups { background: #351c15; color: #ffb500; }
.ashr-logo--redpack { background: #c8102e; color: #fff; }
.ashr-logo--sendex { background: #173f5f; color: #fff; }
.ashr-logo--pickup { background: #15803d; color: #fff; }
.ashr-logo--correos { background: #006847; color: #fff; }
.ashr-text {
  display: flex; flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.ashr-carrier {
  font-size: 14px; font-weight: 600;
  color: var(--text-primary, #1d1c17);
}
.ashr-eta {
  font-size: 12px;
  color: var(--text-muted, #6b7280);
}
.ashr-badge {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  margin-top: 2px;
  background: var(--info-soft, #dbeafe);
  color: var(--info, #1d4ed8);
  font-size: 11px; font-weight: 600;
  padding: 2px 8px;
  border-radius: 10px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.ashr-price {
  font-size: 15px; font-weight: 600;
  color: var(--text-primary, #1d1c17);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ashr-price--free {
  color: var(--success, #15803d);
  text-transform: none;
  font-weight: 700;
}
.ashr-empty {
  padding: 16px;
  text-align: center;
  color: var(--text-muted, #6b7280);
  font-size: 14px;
  margin: 0;
}
@media (max-width: 479px) {
  .ashr-option {
    grid-template-columns: auto 40px 1fr;
    grid-template-areas:
      "radio logo text"
      ".     .    price";
    padding: 12px;
    min-height: 56px;
  }
  .ashr-radio { grid-area: radio; }
  .ashr-logo { grid-area: logo; width: 40px; height: 28px; }
  .ashr-text { grid-area: text; }
  .ashr-price {
    grid-area: price;
    justify-self: end;
    margin-top: 4px;
  }
}


/* able-spinner */

able-spinner { display: contents; }
.asp-bar {
  position: fixed; top: 0; left: 0; right: 0; height: 3px;
  z-index: 1000; pointer-events: none;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.asp-bar[hidden] { display: none !important; }
.asp-bar-fill {
  height: 100%; width: 30%;
  background: linear-gradient(90deg, transparent 0%, var(--accent-secondary, #3b82f6) 50%, transparent 100%);
  transform: translateX(-100%);
  animation: asp-slide 1.2s linear infinite;
}
@keyframes asp-slide {
  from { transform: translateX(-100%); }
  to   { transform: translateX(400%); }
}
.asp-overlay {
  position: fixed; inset: 0;
  background: rgba(11, 15, 26, 0.45);
  display: flex; align-items: center; justify-content: center;
  z-index: 999;
}
.asp-overlay[hidden] { display: none !important; }
.asp-spinner {
  width: 36px; height: 36px;
  border: 3px solid rgba(255, 255, 255, 0.16);
  border-top-color: var(--accent-secondary, #3b82f6);
  border-radius: 50%;
  animation: asp-spin 800ms linear infinite;
}
@keyframes asp-spin { to { transform: rotate(360deg); } }


/* able-tabs */

able-tabs { display: block; }
.atabs[data-orientation="horizontal"] {
  display: block;
}
.atabs-bar {
  display: flex;
  gap: 8px;
  padding: 0 16px;
  border-bottom: 1px solid var(--border-default, #e5e7eb);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}
.atabs-bar[data-orientation="vertical"] {
  flex-direction: column;
  border-bottom: 0;
  border-right: 1px solid var(--border-default, #e5e7eb);
  overflow-x: visible;
  scroll-snap-type: none;
}
.atabs-tab {
  flex: 0 0 auto;
  padding: 12px 16px;
  min-height: 44px;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  scroll-snap-align: start;
  font-size: 14px;
  font-weight: 500;
  transition: border-color 200ms, color 200ms, background-color 120ms;
}
.atabs-tab:focus-visible {
  outline: 2px solid var(--accent-secondary, #1d4ed8);
  outline-offset: -2px;
}
.atabs-tab.is-active {
  border-bottom-color: var(--accent-secondary, #1d4ed8);
  color: var(--accent-secondary, #1d4ed8);
}
.atabs-bar[data-orientation="vertical"] .atabs-tab {
  border-bottom: 0;
  border-right: 2px solid transparent;
  text-align: left;
}
.atabs-bar[data-orientation="vertical"] .atabs-tab.is-active {
  border-right-color: var(--accent-secondary, #1d4ed8);
  border-bottom-color: transparent;
}
.atabs-panel { padding: 16px; }
@media (hover: hover) {
  .atabs-tab:hover {
    background: rgba(0, 0, 0, 0.04);
  }
}
@media (max-width: 479px) {
  .atabs-bar { gap: 4px; padding: 0 12px; }
  .atabs-tab { padding: 10px 14px; font-size: 13px; }
}


/* able-toast-stack */

able-toast-stack { display: contents; }
.atst-stack {
  position: fixed; z-index: 500;
  display: flex; flex-direction: column; gap: 8px;
  padding: 16px;
  pointer-events: none;
  max-width: 360px;
}
.atst-stack[data-corner="top-right"]    { top: 0;    right: 0; }
.atst-stack[data-corner="top-left"]     { top: 0;    left: 0; }
.atst-stack[data-corner="bottom-right"] { bottom: 0; right: 0; }
.atst-stack[data-corner="bottom-left"]  { bottom: 0; left: 0; }
.atst-toast {
  pointer-events: auto;
  display: flex; gap: 8px; align-items: flex-start;
  padding: 10px 14px;
  /* Bug — toast must own its own contrast pair. Previously we read
     --text-primary which in light-themed tenants resolves to a dark
     ink colour (correct for body text on light backgrounds) but rendered
     dark-on-dark inside this toast's deliberately dark surface. Use
     dedicated --theme_toast_* tokens with explicit dark/light fallbacks
     so the toast is always readable regardless of the tenant theme,
     and themes can still rebrand via the dedicated tokens. */
  background: var(--surface-inverse, #1f2937);
  color: var(--text-inverse, #f8fafc);
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.12));
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  font-size: 13px;
  max-width: 360px;
  transition: opacity 180ms ease-out, transform 180ms ease-out;
}
.atst-toast[data-kind="success"] { border-left: 3px solid var(--success, #267e3d); }
.atst-toast[data-kind="warning"] { border-left: 3px solid var(--warning, #f9a006); }
.atst-toast[data-kind="error"]   { border-left: 3px solid var(--danger,  #BF3C00); }
.atst-toast[data-kind="info"]    { border-left: 3px solid var(--info,    #4B6D7A); }
.atst-toast.atst-enter { opacity: 0; transform: translateX(20px); }
.atst-toast.atst-exit  { opacity: 0; transform: translateX(20px); }
.atst-body { flex: 1; min-width: 0; line-height: 1.4; }
.atst-close {
  background: transparent; color: inherit; border: 0; cursor: pointer;
  font-size: 16px; line-height: 1; opacity: 0.7;
  padding: 0 4px;
}
.atst-close:hover { opacity: 1; }

