/* ============================================================================
   AIRY — the Luminair Studio skin (John, 2026-09-20).

   The desktop studies in website/mockups/desktop-airy.html, applied to the REAL app as
   CSS only: study 06 for a working session, study 05 for a fresh one. Every selector is
   prefixed with html[data-skin="airy"], which only the Studio variant sets, so the
   installed app never matches a rule in this file. No element is created, hidden or
   moved; only surfaces, ink, type, spacing and borders change.

   Rules of the style, measured on the studies: warm paper, hairlines instead of boxes,
   one accent used only for "running", mono eyebrows for labels and counts, a 720px
   reading column with real air around it, the composer as a floating card.
   ============================================================================ */

/* ---- palette + type: overrides every theme, accent and preset ------------------ */
html[data-skin="airy"] body,
html[data-skin="airy"] body[data-theme],
html[data-skin="airy"] body[data-theme]:not([data-preset]),
html[data-skin="airy"] body[data-preset],
html[data-skin="airy"] body[data-accent] {
  --bg: #f4f4f5;
  --panel: #f4f4f5;
  --panel-2: #fafafb;
  --sidebar: #f4f4f5;
  --tool: #fafafb;
  --tool-line: rgba(var(--ink-rgb),.12);
  --line: rgba(var(--ink-rgb),.12);
  --text: #111214;
  --muted: #4a4b4e;
  --faint: #8f9094;
  --accent-rgb: 255, 107, 68;
  --on-accent: #ffffff;
  --hover: rgba(var(--ink-rgb),.04);
  --active: rgba(var(--ink-rgb),.06);
  --head-fade: rgba(244,244,245,.3);
  --bo-txt: #6f4a00;
  --bo-lt: #8a5f00;
  --fx-txt: #24499b;
  --fx-lt: #2a52ad;
  --ui-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --chat-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --airy-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --airy-serif: 'Instrument Serif', 'Iowan Old Style', 'Palatino', Georgia, serif;
  --chat-scale: 1.1;
  --sh40: .08; --sh55: .1; --shEdge: .06;
  /* INK AND ITS CONTRAST. Every solid dark button in this skin is painted with
     var(--text) — the same dark gray the Luminair logo is masked in, never 100%
     black (John, 2026-09-23). --on-ink is whatever reads on top of it, so the pair
     flips together in dark mode instead of leaving white text on a white button. */
  --ink-rgb: 17, 18, 20;
  --on-ink: #f4f4f5;
  color-scheme: light;
}
html[data-skin="airy"] body { background: var(--bg); color: var(--text); -webkit-font-smoothing: antialiased; }

/* ---- DARK MODE: the same palette inverted (John, 2026-09-23) -------------------
   Two modes only, Light and Dark. Dark is not a new design: it is this exact token
   set with paper and ink swapped, so every rule below keeps working untouched. The
   darkest surface is #111214 — the logo's dark gray — never 100% black.

   SPECIFICITY, not colour, was the bug (John, 2026-09-23: "default still gives me a
   FULL FREAKING LIGHT MODE THEME"). The light block above ends in :not([data-preset]),
   which counts as a third attribute selector, so it scores (0,3,2). Plain
   body[data-theme="dark"] only scores (0,2,2) and LOST to it. The two longer dark
   selectors tie at (0,3,2) and win on order, which is why Dark looked correct as long
   as an accent was picked: data-accent supplied the missing third attribute. Choosing
   Default removes data-accent, presets are purged on every launch, so neither applied
   and the whole app fell back to the light palette. The :not([data-preset]) variant
   below restores the tie in the one case that was uncovered. */
html[data-skin="airy"] body[data-theme="dark"],
html[data-skin="airy"] body[data-theme="dark"]:not([data-preset]),
html[data-skin="airy"] body[data-theme="dark"][data-preset],
html[data-skin="airy"] body[data-theme="dark"][data-accent] {
  --bg: #111214;
  --panel: #111214;
  --panel-2: #1b1c1f;
  --sidebar: #111214;
  --tool: #1b1c1f;
  --tool-line: rgba(244,244,245,.14);
  --line: rgba(244,244,245,.14);
  --text: #f4f4f5;
  --muted: #b3b4b8;
  --faint: #8a8b8f;
  --on-accent: #111214;
  --ink-rgb: 244, 244, 245;
  --on-ink: #111214;
  --hover: rgba(244,244,245,.06);
  --active: rgba(244,244,245,.1);
  --head-fade: rgba(var(--ink-rgb),.3);
  --bo-txt: #e3b35a;
  --bo-lt: #f0c877;
  --fx-txt: #9db6ff;
  --fx-lt: #b3c6ff;
  --sh40: .45; --sh55: .55; --shEdge: .35;
  color-scheme: dark;
}


/* ---- the frame: no boxes, hairlines only ------------------------------------- */
html[data-skin="airy"] {
  --sidebar-w: 262px;
}
html[data-skin="airy"] aside {
  font-family: var(--ui-font);
  background: var(--sidebar);
  border-right: 1px solid var(--line);
}
html[data-skin="airy"] .side-top { height: 56px; padding: 0 14px; }
html[data-skin="airy"] header {
  height: 56px; background: transparent; border-bottom: 1px solid var(--line);
  padding-left: 22px; padding-right: 26px; gap: 18px;
}
html[data-skin="airy"] .icon-btn,
html[data-skin="airy"] .collapse-btn,
html[data-skin="airy"] .claude-status,
html[data-skin="airy"] .layouts-btn,
html[data-skin="airy"] .mc-chip,
html[data-skin="airy"] .layout-tab,
html[data-skin="airy"] .layout-tab-add {
  border-color: transparent; background: transparent; color: var(--muted); border-radius: 999px;
}
html[data-skin="airy"] .icon-btn:hover,
html[data-skin="airy"] .collapse-btn:hover,
html[data-skin="airy"] .layouts-btn:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .layout-tab { font-size: 14px; height: 32px; padding: 0 12px; color: var(--muted); }
/* The strip sits on the header's own left edge, and the first tab's 12px padding is the
   breathing room before the first name (John, 2026-09-22: "not enough padding to the
   left of the first layout" — the earlier -12px pull put the label flush against it). */
html[data-skin="airy"] #layoutTabs { margin-left: 0; }
/* The + belongs immediately after the last tab (John, 2026-09-23: "the + should align
   with the last item on the list"). The strip is flex: 1 1 auto in the base sheet, so it
   grew to fill the whole header while the + sits in the sibling .layouts-ctl after it —
   stranding the + far to the right of the final tab. Sizing the strip to its content puts
   them together; flex-shrink stays 1 and min-width stays 0, so the strip still shrinks and
   scrolls, with its fade masks intact, once the tabs outgrow the space. */
/* 2026-09-23: sizing the strip to its content is what HID layouts. A scroll container
   (overflow-x: auto) resolves flex-basis: auto to a width far under its content here, so
   the strip measured 168px with 526px of tabs inside and only the first two names were
   ever on screen (John: "what happened to my layouts? I only see two"). The strip grows
   again, exactly as the base sheet intends, and the "+" now lives INSIDE the strip as its
   last child, so it still sits immediately after the last tab. */
html[data-skin="airy"] .layout-tab.active { color: var(--text); font-weight: 500; background: transparent; border-color: transparent; }
html[data-skin="airy"] .mc-chip { padding: 4px 10px; gap: 12px; }
html[data-skin="airy"] .mc-chip .mc-lbl { color: var(--text); font-size: 14px; }
html[data-skin="airy"] .mc-jobs-badge { background: transparent; color: var(--faint); font: 11px var(--airy-mono); letter-spacing: .08em; text-transform: uppercase; padding: 0; }

/* ---- the wordmark: REAL TEXT, exactly like the Journal mark (2026-09-23) -----
   John: "make it really text if you want, if this helps." It does, and it is the only
   way this glows reliably.

   It used to be a masked box: transparent letters, an ink background, and logo.svg as
   a mask. CSS applies filter BEFORE mask, so any drop-shadow was painted around the
   90x12 rectangle and then clipped off by the glyph mask — which is why four separate
   attempts at a halo showed nothing at all.

   applyGlitchWordmark() already writes the name into the DOM as one span per letter
   (renderer.js:194), so the text was always there, just hidden under the mask. Now the
   letters simply render, in the same Brunea face the logo artwork is drawn in, and the
   glow is an ordinary drop-shadow on real glyph alpha — the same thing brain.css does
   for /JOURNAL. The leading slash comes from ::before so no JS string changes. */
html[data-skin="airy"] .appname {
  display: inline-block; width: auto; height: auto; overflow: visible;
  font-family: "Brunea", "Bitcount", ui-monospace, monospace;
  font-size: 15px; font-weight: 700; letter-spacing: .5px; line-height: 1;
  color: var(--text); background: transparent;
  -webkit-mask: none; mask: none;
  user-select: none; white-space: nowrap;
  /* Lowercase, matching the logo artwork this replaced (John, 2026-09-23: "no caps").
     The base sheet sets text-transform: uppercase on .appname, which this overrides. */
  text-transform: lowercase;
}
/* The per-letter spans were forced transparent for the masked version. Let them paint. */
html[data-skin="airy"] .appname .gl-neutral, html[data-skin="airy"] .appname .gl-accent { color: inherit; }
html[data-skin="airy"] .appname .gl { position: relative; display: inline-block; }
/* The slash of the lockup, drawn rather than stored, so BRAND_WORDMARK stays "Luminair". */
html[data-skin="airy"] .appname::before { content: "/"; }
/* Collapsed rail: the short mark is just the letter, no slash and no fixed width. */
html[data-skin="airy"] .appname-short { width: auto; }
html[data-skin="airy"] .appname-short::before { content: none; }

/* ---- sidebar sections: eyebrows, dots, no row fills --------------------------- */
html[data-skin="airy"] .sec-head,
html[data-skin="airy"] .side-branches .sb-head,
html[data-skin="airy"] .folder-subhead {
  padding: 10px 24px 8px; color: var(--faint);
  font: 11px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase;
}
/* THE TITLE MUST NOT MOVE WHEN THE SECTION CLOSES (John, 2026-09-22). The old rule cut
   the collapsed head's padding from 10px/8px to 6px/6px, so folding a section jumped its
   eyebrow up 4px — and the caret, pinned to the head box's centre line, jumped with it.
   The head keeps ONE padding in both states; the collapsed block gets its even top/bottom
   air from the dots strip's own padding instead (app.css, .active-dots-mini).
   Only the BOTTOM padding may differ when collapsed — it never moves the text above it —
   and it goes to 10px so a section with nothing under it (Open Branches, Folders) is
   exactly centred: 10px over the eyebrow, 10px under it. */
html[data-skin="airy"] .sec-head.collapsed,
html[data-skin="airy"] .side-branches .sb-head.collapsed { padding-bottom: 10px; }
/* Collapsed ACTIVE SESSIONS block: the head gives 10px above the eyebrow, so the dots
   strip gives 10px below the dots — equal air top and bottom — and starts at the head's
   own 24px left padding so the dots line up under the title's first letter. */
html[data-skin="airy"] #activeWrap .active-dots-mini { padding: 0 14px 10px 24px; }
html[data-skin="airy"] .sec-head .sec-title, html[data-skin="airy"] .side-branches .sb-title { color: var(--faint); }
html[data-skin="airy"] .sec-head button, html[data-skin="airy"] .add-plus { color: var(--faint); font-size: 14px; }
html[data-skin="airy"] .proj-filter { background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; color: var(--text); font: 12px var(--ui-font); padding: 2px 0; }
html[data-skin="airy"] .side-branches .sb-count, html[data-skin="airy"] .folder-subcount { color: var(--faint); font: 11px var(--airy-mono); }

html[data-skin="airy"] .row,
html[data-skin="airy"] .active-row,
html[data-skin="airy"] .side-branches .sb-row {
  margin: 0 16px; padding: 7px 8px; border-radius: 0;
  background: transparent; box-shadow: none;
  color: var(--muted); font: 14px/1.3 var(--ui-font);
}
html[data-skin="airy"] .row:hover, html[data-skin="airy"] .active-row:hover, html[data-skin="airy"] .side-branches .sb-row:hover { background: transparent; color: var(--text); }
html[data-skin="airy"] .row.active, html[data-skin="airy"] .active-row.active { background: transparent; color: var(--text); font-weight: 500; }
html[data-skin="airy"] .row.folder { color: var(--text); font-weight: 500; }
html[data-skin="airy"] .tree .row.session { color: var(--muted); font-weight: 400; }
html[data-skin="airy"] .active-row .sname { color: inherit; }
html[data-skin="airy"] .active-row .astatus, html[data-skin="airy"] .row .cnt, html[data-skin="airy"] .active-row .asub {
  font: 11px var(--airy-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .row .x { color: var(--faint); background: transparent; }
html[data-skin="airy"] .row .dots { color: var(--muted); background: transparent; font-weight: 600; }
/* No bottom margin: collapsed, the section is just its head, and an 8px margin under it
   put 18px below the eyebrow against 10px above — the "way too much space when closed,
   not centred" block (John, 2026-09-22). Open, the row list carries its own 6px bottom
   padding, so nothing needs this margin in either state. */
html[data-skin="airy"] .side-branches { margin: 0; }
html[data-skin="airy"] .side-branches .sb-row { color: var(--text); }
/* MERGE IS A TEXT ACTION, NOT A BUTTON (John, 2026-09-23: "I like better the text action
   than button. Change the button. BUT make the text smaller"). It was the only filled pill
   left in the branch rows, sitting beside DIFF and COMMIT which are already plain text, and
   it squeezed the branch name. Same treatment as .sb-bo-commit, one step smaller at 10px so
   it reads as the lightest of the three, and in accent so merge still stands apart. */
html[data-skin="airy"] .side-branches .sb-bo-take {
  background: transparent; border: 0; border-radius: 999px; padding: 4px 8px;
  font: 10px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent); font-weight: 400;
}
html[data-skin="airy"] .side-branches .sb-bo-take:hover { background: var(--hover); filter: none; }
/* The primary variant loses its accent FILL here too — same text action, ink-weighted. */
html[data-skin="airy"] .side-branches .sb-bo-take.primary {
  background: transparent; border: 0; color: var(--accent); font-weight: 700;
}
html[data-skin="airy"] .side-branches .sb-bo-take.primary:hover { background: var(--hover); filter: none; }

/* ---- the staged-build card (rebuilt 2026-09-23) ------------------------------
   It was drawing border:0 with a single border-top plus border-radius:10px, so only
   the top edge painted and the radius curled both of its ends into nothing. That is
   the broken half-outline it showed: it read as a rendering fault, not a card.
   It is a real card now. Full hairline on all four sides, a proper radius, and a
   chevron that says it is clickable, because "Click to relaunch" was carrying the
   whole affordance in words. Title and meta split the two lines: what it is, then
   which version. Hover firms the border to ink and lifts the fill, the same hover
   language the rest of the rail uses. */
html[data-skin="airy"] .sb-update, html[data-skin="airy"] .sb-staged {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  margin: auto 16px 18px; padding: 13px 34px 13px 16px;
  border: 1px solid var(--line); border-radius: 12px;
  background: transparent; color: var(--text);
  transition: border-color .14s ease, background-color .14s ease;
}
/* THE HIDDEN ATTRIBUTE STILL WINS (John, 2026-09-23). The rule above sets display:flex at
   specificity 0,2,1, which outranks the base sheet's `.sb-update[hidden] { display: none }`
   at 0,2,0 — so both cards stayed on screen permanently, showing the placeholder markup from
   index.html ("Download Update / Version 1.0.1") whether or not an update existed. Restated
   here at 0,3,1 so the skin cannot resurrect a card the renderer has hidden. */
html[data-skin="airy"] .sb-update[hidden], html[data-skin="airy"] .sb-staged[hidden] { display: none; }
html[data-skin="airy"] .sb-update:hover, html[data-skin="airy"] .sb-staged:hover {
  border-color: rgba(var(--ink-rgb), .34); background: var(--hover); filter: none;
}
/* app.css fills every pale-theme `.sb-update` with the accent and paints all nested copy
   with `--on-accent`. The staged card is the neutral-outline exception: keep its paper
   surface and ink on both rest and hover, even when the selected accent is white. */
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sb-staged {
  background: transparent; border-color: var(--line); color: var(--text);
}
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sb-staged:hover {
  background: var(--hover); border-color: rgba(var(--ink-rgb), .34); color: var(--text);
}
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sb-staged .sb-update-title { color: var(--text); }
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sb-staged .sb-update-sub { color: var(--faint); }
html[data-skin="airy"] .sb-staged:hover .sb-update-title { color: var(--text); }
html[data-skin="airy"] .sb-staged:hover .sb-update-sub { color: var(--faint); }
html[data-skin="airy"] .sb-update-txt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
html[data-skin="airy"] .sb-update-title { font: 500 13.5px/1.25 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .sb-update-sub {
  font: 10.5px/1 var(--airy-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html[data-skin="airy"] .sb-update-ic { display: none; }
/* the affordance: a chevron on the right edge, ink on hover */
html[data-skin="airy"] .sb-update::after, html[data-skin="airy"] .sb-staged::after {
  content: ""; position: absolute; right: 16px; top: 50%;
  width: 6px; height: 6px; margin-top: -3px;
  border-right: 1.5px solid var(--faint); border-top: 1.5px solid var(--faint);
  transform: rotate(45deg); transition: border-color .14s ease;
}
html[data-skin="airy"] .sb-update:hover::after, html[data-skin="airy"] .sb-staged:hover::after {
  border-right-color: var(--text); border-top-color: var(--text);
}
/* collapsed rail: the card shrinks to the chevron alone, no clipped text */
/* THE STAGED CARD IS CLICKABLE AGAIN (John, 2026-09-23), so it keeps the chevron, the
   pointer and the hover it shares with the update card. What changed is what the click
   DOES: it copies the install command instead of quitting the app into a swap. Only the
   sub line is special-cased — it wraps rather than ellipsing, so "copy install command"
   is never cut to "COPY INSTALL COMM…". */
html[data-skin="airy"] .sb-staged .sb-update-sub { white-space: normal; overflow: visible; text-overflow: clip; }
html[data-skin="airy"] body.collapsed .sb-update-txt { display: none; }
html[data-skin="airy"] body.collapsed .sb-update, html[data-skin="airy"] body.collapsed .sb-staged {
  padding: 13px 0; justify-content: center;
}
html[data-skin="airy"] body.collapsed .sb-update::after, html[data-skin="airy"] body.collapsed .sb-staged::after {
  position: static; margin: 0;
}

/* ---- panes: reading column, hairline chrome ------------------------------------ */
html[data-skin="airy"] .pane { background: var(--bg); }
html[data-skin="airy"] .tab-strip { padding: 14px 40px 0; }
html[data-skin="airy"] .tab-chip {
  padding: 6px 0 12px; margin: 0 24px 0 0; border: 0; border-radius: 0;
  background: transparent; color: var(--faint); font: 13.5px var(--ui-font);
}
html[data-skin="airy"] .tab-chip:hover { background: transparent; color: var(--text); }
html[data-skin="airy"] .tab-chip.active { background: transparent; color: var(--text); border-bottom: 1px solid var(--text); }
html[data-skin="airy"] .tab-chip.tinted:not(.active) { background: transparent; }
html[data-skin="airy"] .pane-head {
  height: auto; padding: 22px 40px 0; border-bottom: 0; background: transparent;
  color: var(--faint); font: 11px var(--airy-mono); letter-spacing: .1em; text-transform: uppercase;
}
html[data-skin="airy"] .pane-head .ptitle { color: var(--text); font: 500 17px/1.3 var(--ui-font); letter-spacing: 0; text-transform: none; }
html[data-skin="airy"] .pane-head button { border-color: transparent; background: transparent; }
html[data-skin="airy"] .pane-body { padding: 34px 48px 24px; }
html[data-skin="airy"] .msg { max-width: 720px; }
html[data-skin="airy"] .msg.user { font: 15.5px/1.6 var(--ui-font); letter-spacing: 0; color: var(--muted); padding: 4px 0; }
html[data-skin="airy"] .msg.assistant { font-size: 16px; line-height: 1.7; letter-spacing: 0; padding: 4px 0; }
html[data-skin="airy"] .msg.assistant h1, html[data-skin="airy"] .msg.assistant h2, html[data-skin="airy"] .msg.assistant h3 { font-weight: 500; letter-spacing: -.01em; }
html[data-skin="airy"] .msg.assistant pre, html[data-skin="airy"] .msg.assistant code { font-family: var(--airy-mono); }
html[data-skin="airy"] .msg.assistant pre { background: var(--panel-2); border: 1px solid var(--line); border-radius: 12px; }

/* ---- composer: a floating card, ink send button, pills for model + chips -------- */
html[data-skin="airy"] .pane-composer { padding: 14px 16px 16px;   /* left, right and bottom margins equal at 16px (John, 2026-09-24: "same amount all around"); sides were 40, then 24, bottom was 26 */ }
html[data-skin="airy"] .composer {
  padding: 12px 12px 12px 22px; border-radius: 18px; gap: 14px;
  background: var(--panel-2);
  box-shadow: 0 1px 0 rgba(17,18,20,.05), 0 14px 40px rgba(17,18,20,.08);
}
html[data-skin="airy"] .composer textarea { font: 15px/1.5 var(--ui-font); caret-color: var(--text); }
html[data-skin="airy"] .composer textarea::placeholder { color: var(--faint); }
html[data-skin="airy"] .psend, html[data-skin="airy"] .pstop {
  width: 34px; height: 34px; border-radius: 50%; border: 0;
  background: var(--text); color: var(--on-ink);
}
html[data-skin="airy"] .pvoice { border: 0; background: transparent; color: var(--faint); }
html[data-skin="airy"] .q-bar { gap: 10px; margin-bottom: 10px; }
/* The model chip wears its model's colour, set inline by the app (renderer.js, applyModel
   tint) — that is information, so the skin only reshapes it into a pill. */
html[data-skin="airy"] .q-model-def {
  height: 30px; padding: 0 14px 0 10px; border-radius: 999px; font: 500 12.5px var(--ui-font);
}
html[data-skin="airy"] .q-model-def:hover { filter: none; opacity: .9; }
html[data-skin="airy"] .q-attach { border: 0; background: transparent; color: var(--faint); font-size: 18px; }
html[data-skin="airy"] .q-chip { height: 30px; border-radius: 999px; border: 1px solid var(--line); background: transparent; }
/* "Latest" pill in the airy language (John, 2026-09-24: "redesign this so it's with our
   new UI"). Base app.css draws it as the dark Context Card: panel fill, accent hairline,
   white 13px text, drop shadow, 3px corners. Airy makes it the same component as the
   composer chips and the voice pill: a 30px hairline pill on --panel-2, muted 12.5px
   medium label, no shadow. Hover lifts the ink to --text and the border to --muted,
   the same hover the model chip uses. The arrow glyph is set slightly smaller so it
   reads as an icon next to the word instead of a second character of the label. */
html[data-skin="airy"] .jump-latest {
  height: 30px; padding: 0 14px 0 12px; gap: 6px;
  border-radius: 999px; border: 1px solid var(--line);
  background: var(--panel-2); color: var(--muted);
  font: 500 12.5px/1 var(--ui-font); letter-spacing: 0;
  box-shadow: none;
  transition: bottom .12s ease, color .12s ease, border-color .12s ease;
}
html[data-skin="airy"] .jump-latest:hover { color: var(--text); border-color: var(--muted); background: var(--panel-2); }

/* ---- a fresh pane: study 05 ------------------------------------------------------ */
html[data-skin="airy"] .pane-body .empty { display: flex; align-items: center; justify-content: center; height: 100%; padding: 0 40px; }
/* ...but as a COLUMN, and not inside a 400px box (John, 2026-09-23: the Quick Ask home
   view came out as a squeezed three-column strip overlapping the headline). The rule
   above only set display:flex, so the default row direction put the 40px headline and
   the .home-starts grid SIDE BY SIDE, inside the base sheet's .empty max-width of 400px
   which airy never overrode. The grid already asks for max-width:900px and margin-top:64px
   — i.e. it was always meant to sit UNDER the headline — and could never get either.
   The first-run screen keeps its own column layout and 760px cap. */
html[data-skin="airy"] .pane-body .empty:not(.ftu-empty) {
  flex-direction: column; max-width: 980px; margin: auto;
}
html[data-skin="airy"] .pane-body .empty h2 {
  font: 500 40px/1.15 var(--ui-font) !important; letter-spacing: -.03em; color: var(--text);
  text-align: center; gap: 14px !important; max-width: 720px;
}
html[data-skin="airy"] .pane-body .empty h2 svg { display: none; }
html[data-skin="airy"] .pane-body .empty h2 { display: block !important; text-align: center; font: 500 40px/1.15 var(--ui-font) !important; letter-spacing: -.03em; }
/* New-session line (John, 2026-09-22): "How are you gonna better the world today?"
   replaces the old marketing lockup. Serif italic carries "better the world". */
html[data-skin="airy"] .pane-body .empty h2::before { content: 'How are you gonna '; }
html[data-skin="airy"] .pane-body .empty h2 span { font-size: 0 !important; letter-spacing: 0; }
html[data-skin="airy"] .pane-body .empty h2 span::before { content: 'better the world'; font: italic 44px/1 var(--airy-serif); }
html[data-skin="airy"] .pane-body .empty h2 span::after { content: ' today?'; font: 500 40px/1.15 var(--ui-font); letter-spacing: -.03em; }
html[data-skin="airy"] .pane-body .empty h2::after { content: none; }

/* first-time user: same 05 layout, the bottom row is the setup path */
html[data-skin="airy"] .pane-body .empty.ftu-empty { flex-direction: column; gap: 44px; }
html[data-skin="airy"] .ftu-actions { display: grid; grid-template-columns: repeat(3, 200px); gap: 40px; }
html[data-skin="airy"] .ftu-act { display: block; text-align: left; border: 0; background: transparent; padding: 0; cursor: pointer; }
html[data-skin="airy"] .ftu-act small { display: block; font: 11px/1 var(--airy-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--faint); margin-bottom: 8px; }
html[data-skin="airy"] .ftu-act span { font-size: 15px; color: var(--muted); transition: color .12s; }
html[data-skin="airy"] .ftu-act:hover span, html[data-skin="airy"] .ftu-act.done span { color: var(--text); }
html[data-skin="airy"] .ftu-act.done small { color: var(--accent); }

/* ---- popups, menus, cards: same paper, rounder, no hard borders ------------------ */
html[data-skin="airy"] .mc-pop, html[data-skin="airy"] .bg-pop, html[data-skin="airy"] .row-menu, html[data-skin="airy"] .mc-log-pop, html[data-skin="airy"] .layouts-menu {
  background: var(--panel-2); border: 0; border-radius: 14px;
  box-shadow: 0 1px 0 rgba(17,18,20,.05), 0 20px 50px rgba(17,18,20,.14);
}
html[data-skin="airy"] .q-bo, html[data-skin="airy"] .bo-super, html[data-skin="airy"] .bo-hero { border-radius: 14px; }
html[data-skin="airy"] ::-webkit-scrollbar-thumb { background: rgba(var(--ink-rgb),.14); border-radius: 999px; }

/* ---- boot cover and sign-in: the same paper, the logo as artwork -------------------- */
html[data-skin="airy"] #boot-cover { background: var(--bg) !important; }
html[data-skin="airy"] #boot-cover > div[style*="radial-gradient"] { opacity: 0; }
html[data-skin="airy"] .boot-bar { background: rgba(var(--ink-rgb),.1); }
html[data-skin="airy"] .boot-bar-fill { background: var(--text); box-shadow: none; }
html[data-skin="airy"] .boot-meta, html[data-skin="airy"] #boot-label, html[data-skin="airy"] #boot-pct { color: var(--faint); }
html[data-skin="airy"] .pw-wordmark, html[data-skin="airy"] .boot-wordmark {
  display: inline-block; width: 176px; height: 21px; overflow: hidden;
  font-size: 0 !important; letter-spacing: 0; text-shadow: none; color: transparent;
  background: var(--text);
  -webkit-mask: url('../assets/logo.svg') no-repeat center / contain; mask: url('../assets/logo.svg') no-repeat center / contain;
}
html[data-skin="airy"] .boot-wordmark { width: 141px; height: 17px; }
html[data-skin="airy"] .pw-wordmark .gl, html[data-skin="airy"] .boot-wordmark .gl { color: transparent; text-shadow: none; animation: none; }
html[data-skin="airy"] .pw-overlay, html[data-skin="airy"] .pw-overlay.brand { background: var(--bg); }
html[data-skin="airy"] .pw-overlay::before, html[data-skin="airy"] .pw-overlay::after { display: none; }
html[data-skin="airy"] .pw-brand-bg, html[data-skin="airy"] .pw-overlay video { opacity: 1; }
html[data-skin="airy"] .cc-video-scrim { background: rgba(8,7,6,.28); }
html[data-skin="airy"] .pw-card { color: var(--text); }
html[data-skin="airy"] .pw-brand-head { color: var(--text); font: 500 34px/1.15 var(--ui-font); letter-spacing: -.02em; }
html[data-skin="airy"] .pw-brand-head b { color: var(--text); font-weight: 500; }
html[data-skin="airy"] .pw-brand-head .o { color: var(--text); font: italic 38px/1 var(--airy-serif); letter-spacing: 0; }
html[data-skin="airy"] .pw-brand-lede, html[data-skin="airy"] .pw-lede, html[data-skin="airy"] .pw-sub, html[data-skin="airy"] .pw-note { color: var(--muted); }
html[data-skin="airy"] .pw-brand-note, html[data-skin="airy"] .pw-brand-altlink { color: var(--faint); }
html[data-skin="airy"] .pw-brand-altlink a { color: var(--text); }
html[data-skin="airy"] .pw-brand-cta { background: var(--text); color: var(--on-ink); border: 0; border-radius: 999px; box-shadow: none; font-weight: 500; }
html[data-skin="airy"] .pw-brand-cta.google { background: var(--text); color: var(--on-ink); border: 0; }
html[data-skin="airy"] .pw-brand-cta.google:hover { background: var(--text); opacity: .9; }
html[data-skin="airy"] .pw-err { color: #a53a2a; }
html[data-skin="airy"] .pw-title, html[data-skin="airy"] .pw-hero { color: var(--text); }
html[data-skin="airy"] .pw-hero em { color: var(--text); font: italic 1em var(--airy-serif); }

/* The overlay used to pin its own ink and paper so it read on pale themes. With two
   modes it just inherits them, so it is correct in Light and Dark alike; only the
   hairline and accent tint are restated, and #cc-overlay rules need id-level weight. */
html[data-skin="airy"] .pw-overlay, html[data-skin="airy"] #cc-overlay {
  --line: rgba(var(--ink-rgb),.12); --accent-soft: rgba(var(--ink-rgb),.06);
  background: var(--bg);
}
html[data-skin="airy"] #cc-overlay .cc-video-bg, html[data-skin="airy"] .pw-overlay .cc-video-bg { opacity: 1; }
html[data-skin="airy"] #cc-overlay .cc-bird-bg { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; }
html[data-skin="airy"] #cc-overlay .cc-bird-source { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; left: -9999px; }
html[data-skin="airy"] body[data-theme="dark"] #cc-overlay .cc-video-bg { filter: invert(1); }
html[data-skin="airy"] #cc-overlay .cc-video-scrim { z-index: 0; background: transparent; }
html[data-skin="airy"] #cc-overlay {
  --bg: #f7f7f8; --text: #242421; --muted: #777772; --faint: #777772;
  --on-ink: #f7f7f8; background: #f7f7f8;
}
html[data-skin="airy"] #cc-overlay .pw-wordmark.pw-brand-logo { width: 176px; height: 21px; font-size: 0; letter-spacing: 0; margin-bottom: 6px; }
html[data-skin="airy"] #cc-overlay .pw-brand-head { color: var(--text); font: 500 34px/1.15 var(--ui-font); letter-spacing: -.02em; }
html[data-skin="airy"] #cc-overlay .pw-brand-head .o { color: var(--text); font: italic 38px/1 var(--airy-serif); }
html[data-skin="airy"] #cc-overlay .pw-brand-cta.cc-cta, html[data-skin="airy"] #cc-overlay .pw-brand-cta.cc-cta:hover {
  background: var(--text); color: var(--on-ink); border: 0; border-radius: 999px; box-shadow: none; filter: none;
}
html[data-skin="airy"] #cc-overlay .pw-brand-input {
  background: #ffffff; color: #242421; border: 1px solid rgba(36,36,33,.2);
}
html[data-skin="airy"] #cc-overlay .pw-brand-input::placeholder { color: #777772; }
/* Premium login treatment: editorial paper, a quiet glass surface, and the bird as
   a large piece of background art instead of a competing full-screen panel. */
html[data-skin="airy"] #cc-overlay .cc-bird-bg {
  /* Shown exactly as the site renders the bird: no extra contrast or blend. */
  opacity: 1; filter: none; mix-blend-mode: normal;
}
html[data-skin="airy"] #cc-overlay .cc-video-scrim {
  background: transparent;
}
html[data-skin="airy"] #cc-overlay .pw-card {
  max-width: 540px; padding: 54px 52px 48px; gap: 18px;
  background: transparent; border: 0;
  border-radius: 0; box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
html[data-skin="airy"] #cc-overlay .pw-wordmark.pw-brand-logo { margin-bottom: 4px; }
html[data-skin="airy"] #cc-overlay .pw-brand-head { font-size: 38px; line-height: 1.08; }
html[data-skin="airy"] #cc-overlay .pw-brand-cta.cc-cta { max-width: 380px; min-height: 56px; font-size: 16px; }
html[data-skin="airy"] #cc-overlay .cc-email-block {
  max-width: 380px; margin-top: 12px; padding-top: 22px;
  border-top: 1px solid rgba(36,36,33,.12);
}
html[data-skin="airy"] #cc-overlay .cc-email-block::before {
  content: 'OR CONTINUE WITH EMAIL'; display: block; margin-bottom: 14px;
  color: #777772; font: 10px/1 var(--airy-mono); letter-spacing: .14em;
}
html[data-skin="airy"] #cc-overlay .pw-brand-input {
  min-height: 54px; border-radius: 10px; border-color: rgba(36,36,33,.16);
  box-shadow: 0 2px 8px rgba(36,36,33,.035);
}
html[data-skin="airy"] #cc-overlay .pw-brand-cta.ghost { min-height: 54px; border-radius: 10px; }
@media (max-width: 640px) {
  html[data-skin="airy"] #cc-overlay .pw-card { max-width: calc(100vw - 32px); padding: 38px 24px 32px; border-radius: 18px; }
  html[data-skin="airy"] #cc-overlay .pw-brand-head { font-size: 30px; }
}

/* ---- folders: the pixel face was the wordmark's, not a heading face ------------------- */
html[data-skin="airy"] .folder .fname { font: 500 14px/1.3 var(--ui-font); letter-spacing: 0; color: var(--text); }
html[data-skin="airy"] .folder .fcount { font: 11px var(--airy-mono); font-weight: 400; letter-spacing: .06em; color: var(--faint); }
html[data-skin="airy"] .folder .ficon { display: none; }

/* ---- every remaining boxed control becomes an ink glyph or a mono word ---------------- */
html[data-skin="airy"] header button, html[data-skin="airy"] header .icon-btn,
html[data-skin="airy"] .collapse-btn, html[data-skin="airy"] .claude-status {
  border: 0; background: transparent; color: var(--faint); border-radius: 999px; width: 32px; height: 32px;
}
html[data-skin="airy"] header button:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .shortcuts-btn, html[data-skin="airy"] .term-toggle { font: 12px var(--airy-mono); letter-spacing: .04em; }
html[data-skin="airy"] .layouts-btn { width: auto; padding: 0 12px; font: 14px var(--ui-font); color: var(--muted); }
html[data-skin="airy"] .layouts-btn .ly-lbl { color: inherit; }
html[data-skin="airy"] .mc-chip { border: 0; background: transparent; }
html[data-skin="airy"] .mc-chip .mc-lbl { font: 14px var(--ui-font); color: var(--text); }
html[data-skin="airy"] .mc-switch .mc-track { background: rgba(var(--ink-rgb),.16); }
html[data-skin="airy"] .mc-chip.on .mc-switch .mc-track { background: var(--text); }
html[data-skin="airy"] .mc-caret { border: 0; color: var(--faint); }

/* the compact rail mark only exists for the collapsed rail; the skin's display rule on
   .appname was letting it draw on top of the full wordmark */
html[data-skin="airy"] body:not(.collapsed) .appname-short { display: none; }
html[data-skin="airy"] .win-ctrls { opacity: .55; }
html[data-skin="airy"] .win-ctrl { border: 0; background: transparent; color: var(--faint); }

/* active session rows: the connection glyph goes quiet, the dot goes round */
html[data-skin="airy"] .active-row .aconn { color: var(--faint); opacity: .6; }
html[data-skin="airy"] .adot, html[data-skin="airy"] .phdot { border-radius: 50%; }
html[data-skin="airy"] .folder .dots { color: var(--muted); background: transparent; border: 0; font-weight: 600; }
html[data-skin="airy"] .folder .fnew { color: var(--faint); background: transparent; border: 0; }

/* pane head tools: no bordered squares, mono words and faint glyphs */
html[data-skin="airy"] .pane-head button, html[data-skin="airy"] .pane-head .pbtn, html[data-skin="airy"] .pane-head .pmodesel {
  border: 0 !important; background: transparent !important; color: var(--faint); border-radius: 999px;
  font: 11px var(--airy-mono); letter-spacing: .1em; text-transform: uppercase;
}
html[data-skin="airy"] .pane-head button:hover, html[data-skin="airy"] .pane-head .pbtn:hover { color: var(--text); background: var(--hover) !important; }
html[data-skin="airy"] .pane-head .pclose { font-size: 13px; letter-spacing: 0; }

/* dialogs and settings sheets: paper cards, rounded, no hard border */
html[data-skin="airy"] .modal, html[data-skin="airy"] .modal.set-modal {
  background: var(--panel-2); border: 0; border-radius: 16px; padding: 28px;
  box-shadow: 0 1px 0 rgba(17,18,20,.05), 0 30px 80px rgba(17,18,20,.18);
}
html[data-skin="airy"] .modal h3 { font: 500 20px/1.2 var(--ui-font); letter-spacing: -.01em; }
html[data-skin="airy"] .overlay { background: rgba(var(--ink-rgb),.28); }
html[data-skin="airy"] .modal button, html[data-skin="airy"] .modal .btn-primary, html[data-skin="airy"] .modal .btn-ghost { border-radius: 999px; }
html[data-skin="airy"] .modal .btn-primary, html[data-skin="airy"] .modal button.save { background: var(--text); color: var(--on-ink); border: 0; }

/* ---------- transcript surfaces rebuilt to the 06 language (John, 2026-09-20: "do not use any
   UI element we have today from a design perspective"): no tints, no accent fences, no bordered
   chips, no count pills. Hairlines, mono eyebrows, ink. Placement of every element is unchanged. */

/* session title bars: one paper surface, hairline under it, never a colour wash */
html[data-skin="airy"] .pane.tinted .pane-head, html[data-skin="airy"] .pane.tinted.focused .pane-head,
html[data-skin="airy"] .pane .pane-head { background: var(--panel-2) !important; border-bottom: 1px solid var(--line); }

/* context card: a quiet pinned line, not a floating accent-bordered box */
html[data-skin="airy"] .ctx-pop, html[data-skin="airy"] .ctx-pop:hover, html[data-skin="airy"] .ctx-pop:active {
  margin: 0; padding: 10px 24px; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  background: var(--panel-2); box-shadow: none; color: var(--muted); transform: none;
  font: 13px/1.5 var(--ui-font);
}
html[data-skin="airy"] .ctx-pop::before { content: "context"; font: 10px var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint); margin-right: 12px; align-self: center; }
html[data-skin="airy"] .pane-pin { background: var(--panel-2); color: var(--muted); border-bottom: 1px solid var(--line); }
html[data-skin="airy"] .pane-pin::before { color: var(--faint); font-weight: 400; }

/* queries: ink words, no arrow colour, no mono */
html[data-skin="airy"] .msg.user { font: 15px/1.55 var(--ui-font); letter-spacing: 0; color: var(--text); padding-left: 0; }
html[data-skin="airy"] .msg.user::before { color: var(--faint) !important; }

/* recap / action / note / memory cards: same block, hairline on the left, mono eyebrow, ink body */
html[data-skin="airy"] .recap-card, html[data-skin="airy"] .action-card, html[data-skin="airy"] .note-card, html[data-skin="airy"] .memory-card {
  --accent: var(--text); --accent-rgb: var(--ink-rgb); --accent-soft: rgba(var(--ink-rgb),.06); --accent-ink: var(--on-ink); --nc: var(--text);
  border: 0 !important; border-left: 1px solid var(--line-2, var(--line)) !important; border-radius: 0;
  background: transparent !important; box-shadow: none; padding: 4px 0 4px 20px; margin: 28px 0;
}
html[data-skin="airy"] :is(.recap-card, .action-card, .note-card, .memory-card) .card-label {
  font: 10px var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint) !important; opacity: 1; margin: 0 0 12px;
}
html[data-skin="airy"] :is(.recap-card, .action-card, .note-card, .memory-card) :is(.md-h, .md-h1, .md-h2, .md-h3) { color: var(--text) !important; font: 500 15px/1.4 var(--ui-font); }
html[data-skin="airy"] :is(.recap-card, .action-card, .note-card, .memory-card) strong { color: var(--text) !important; font-weight: 500; }
html[data-skin="airy"] :is(.recap-card, .action-card, .note-card, .memory-card) .a-link { color: var(--text) !important; font-weight: 400; text-decoration: underline; text-decoration-color: rgba(var(--ink-rgb),.3); text-underline-offset: 3px; filter: none; }
html[data-skin="airy"] .action-card .ctl-nudge { border-top: 1px solid var(--line); }

/* lists: a faint dash, never a bold coloured dot */
html[data-skin="airy"] .msg.assistant .md-bullet { color: var(--faint); font-weight: 400; }
html[data-skin="airy"] .msg.assistant .md-list { gap: 6px; }

/* tool calls: a mono line, no chip, no border, no sweep */
html[data-skin="airy"] .tool, html[data-skin="airy"] .tool.note {
  background: transparent; border: 0; border-radius: 0; padding: 2px 0; clip-path: none; animation: none; opacity: 1; transform: none;
  font: 12px/1.6 var(--airy-mono); color: var(--faint);
}
html[data-skin="airy"] .tool::before { display: none; }
html[data-skin="airy"] .tool b, html[data-skin="airy"] .tool .tc-name { color: var(--text); font-weight: 500; animation: none; }
html[data-skin="airy"] .tool .tc-dot { display: none; }
html[data-skin="airy"] .tool .tool-x { color: var(--faint); font-weight: 400; }
html[data-skin="airy"] .tool.note.bo-lesson { --bo-lt: var(--text); border: 0; background: transparent; }

/* sidebar counts: mono numerals, no pill */
html[data-skin="airy"] .side-branches .sb-count, html[data-skin="airy"] .side-branches .sb-bo-diff, html[data-skin="airy"] .side-branches .sb-bo-discard {
  background: transparent !important; border: 0; padding: 0; font: 11px var(--airy-mono); color: var(--faint); border-radius: 0;
}
html[data-skin="airy"] .side-branches .sb-bo-diff:hover { color: var(--text); }

/* session rows: 14px ink names, mono status word, hover as a soft rounded bar */
/* Tightened a step (John, 2026-09-22: "active sessions are a little too big, too big
   fonts, too much spacing"): 8px→6px vertical padding, 14px→13px name. */
html[data-skin="airy"] .active-row { border-radius: 8px; padding: 6px 10px; margin: 0 8px 1px; }
html[data-skin="airy"] .active-row .sname, html[data-skin="airy"] .active-row.sub .sname { font: 13px/1.3 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .active-row.bg .sname { color: var(--muted); font-style: normal; }
html[data-skin="airy"] .active-row.active { background: var(--hover); }
html[data-skin="airy"] .active-row .astatus, html[data-skin="airy"] .active-row.sub .astatus { font: 9.5px var(--airy-mono); letter-spacing: .1em; text-transform: uppercase; opacity: 1; }
html[data-skin="airy"] .astatus.thinking { color: var(--text); }
html[data-skin="airy"] .astatus.waiting { color: #2b7a5b; }
html[data-skin="airy"] .astatus.error { color: #b3261e; }
html[data-skin="airy"] .active-row .asub { font: 11px var(--airy-mono); color: var(--faint); }
html[data-skin="airy"] .active-row.grouped::before, html[data-skin="airy"] .active-row.sub::before { display: none; }
/* Team icon in active rows: grey, not orange, and tighter to the name (John, 2026-09-20). */
html[data-skin="airy"] .active-row .steam { color: var(--faint); opacity: 1; margin-right: 2px; }
html[data-skin="airy"] .active-row .arow-x:hover, html[data-skin="airy"] .active-row .asub-caret:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .active-row.foreign .adevice { color: var(--faint); }

/* Queue takes over the whole session view: opaque paper, full width, no slide-in drawer,
   no resizer, no shadow. Nothing behind it may show through (John, 2026-09-20). */
html[data-skin="airy"] .pane-queue { inset: 0; width: auto; max-width: none; background: var(--bg); border: 0; box-shadow: none !important; transform: none; transition: opacity .12s ease; opacity: 0; pointer-events: none; z-index: 30; }
html[data-skin="airy"] .pane.queue-open .pane-queue { opacity: 1; pointer-events: auto; }
html[data-skin="airy"] .pane.queue-open .pane-head .pclose { display: none !important; }
/* Queue overlay keeps the session title (John, 2026-09-20): the pane header stays
   above the overlay and the queue content starts below it. */
/* Geometry is UNCONDITIONAL, only opacity is toggled (John, 2026-09-22: "a little visual
   glitch when I come out of the queue"). These three used to be scoped to .queue-open, so
   closing stripped the class instantly: the panel jumped from top:54px to top:0 and the
   header lost its stacking order while the panel was still fading out. */
html[data-skin="airy"] .pane .pane-head { position: relative; z-index: 31; }
/* The drop highlight must paint OVER the title bar too, not stop below it (John,
   2026-09-23: "when I drag a window over another one, the highlight should also cover
   the session title"). pane-head sits at z:31, so the indicator sat behind it; lift it
   above so a combine/split highlight covers the whole pane, title included. */
html[data-skin="airy"] .drop-ind { z-index: 32; }
/* The overlay covers the pane from the very TOP and offsets its own content instead of
   starting at a guessed y (John, 2026-09-22: "there is a tiny space when queue is open
   that shows the session behind"). top: 54px was a hardcoded stand-in for the head's
   height; the airy head is auto-height (22px padding + whatever the title row needs), so
   whenever it measured taller than 54px that difference was a strip of live transcript
   showing above the queue. The head paints over the overlay (z-index 31 vs 30), so
   covering the full pane is safe and no gap can exist at any head height. */
html[data-skin="airy"] .pane-queue { top: 0; padding-top: 54px; }
html[data-skin="airy"] .pane-queue .q-head { padding-top: 10px; }
html[data-skin="airy"] .q-resizer { display: none; }
html[data-skin="airy"] .q-head { border-bottom: 0; padding: 14px 20px 8px; }
html[data-skin="airy"] .q-body { padding: 8px 20px 20px; max-width: none; width: 100%; margin: 0; }

/* panes sit flat on the canvas: no focus ring, no tint wash, hairline between them */
html[data-skin="airy"] .pane, html[data-skin="airy"] .pane.tinted, html[data-skin="airy"] .pane.focused { background: var(--bg) !important; box-shadow: none !important; border-color: var(--line) !important; }
html[data-skin="airy"] .pane.focused .pane-head { background: var(--panel-2) !important; }

/* queued-count on a session row: a mono numeral, not a red pill */
html[data-skin="airy"] .active-row .row-q { background: transparent; color: var(--faint); font: 11px var(--airy-mono); border-radius: 0; padding: 0; }

/* time tooltip and inline code: paper, hairline, mono */
html[data-skin="airy"] .ts-tip { font: 11px var(--airy-mono); letter-spacing: .04em; border-radius: 6px; box-shadow: none; }
html[data-skin="airy"] .msg.assistant code { background: rgba(var(--ink-rgb),.05); border: 0; border-radius: 4px; padding: 1px 5px; color: var(--text); }
html[data-skin="airy"] .msg.assistant pre code { background: transparent; padding: 0; }

/* open folder: no tree rail, no ticks (John, 2026-09-20: "remove that line and the dashes") */
html[data-skin="airy"] .folder-item.open > .kids::before, html[data-skin="airy"] .subgroup:not(.collapsed):not(.empty)::before, html[data-skin="airy"] .folder-item.open .row.session::before, html[data-skin="airy"] .subgroup .row.session::before { display: none; }
/* No engraved hairline anywhere in the sidebar (John, 2026-09-22: "I did not have the
   blocky style"). The default skin lifts every row with an inset top highlight, white on
   the pale themes; in airy that reads as a stack of blocks instead of a flat list. */
html[data-skin="airy"] :is(.row, .active-row, #activeWrap, #projectsHead, .tree .row.session) { box-shadow: none !important; }

/* folder rows, mockup 06: activity dots flush right in accent, airier pitch, tools only on hover */
html[data-skin="airy"] .row.folder { padding: 6px 8px; }
html[data-skin="airy"] .row.folder .fname { font-size: 15px; }
html[data-skin="airy"] .row.folder .factive { margin-left: auto; display: flex; align-items: center; gap: 4px; padding-left: 16px; padding-right: 6px; }
html[data-skin="airy"] .factive .fdot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
html[data-skin="airy"] .factive .fdot.waiting { background: var(--accent); opacity: .8; }
html[data-skin="airy"] .factive .fmore { font: 10px var(--airy-mono); color: var(--faint); margin-left: 2px; }
html[data-skin="airy"] .row.folder .dots, html[data-skin="airy"] .row.folder .fnew { display: none; opacity: 1; }
html[data-skin="airy"] .row.folder:hover .dots, html[data-skin="airy"] .row.folder:hover .fnew { display: block; }
/* Folder filter stays discoverable, then gains full contrast on intent. */
html[data-skin="airy"] .proj-filter { opacity: .38; transition: opacity .12s, border-color .12s; }
html[data-skin="airy"] #projectsHead:hover .proj-filter,
html[data-skin="airy"] .proj-filter:focus { opacity: 1; }

/* subfolder headers (Apps/Features/Marketing): old design drew these as a filled grey
   block; flatten to match the plain .row.folder row (John, 2026-09-22: "left over blocks
   from the old design"). */
/* Caret ink lines up with the session-title text column (John, 2026-09-22). A session
   row sits at margin 16px + padding-left 14px = 30px inside the tree; the caret is a 12px
   box whose glyph is centred, so its ink starts 3px in. margin-left 19px + padding-left
   8px + 3px of centring puts that ink on the same column as the titles. */
html[data-skin="airy"] .subfolder-head { background: transparent; margin: 0 16px 2px 19px; padding: 6px 8px; border-radius: 0; }
html[data-skin="airy"] .subfolder-head:hover { background: var(--hover); }
html[data-skin="airy"] .subfolder-head .sf-name { color: var(--text); font: 500 14px/1.3 var(--ui-font); letter-spacing: 0; opacity: 1; }
html[data-skin="airy"] .subfolder-head .sf-count { color: var(--faint); font: 11px var(--airy-mono); font-weight: 400; opacity: 1; }
html[data-skin="airy"] .subfolder-head .sf-caret, html[data-skin="airy"] .subfolder-head .sf-ficon { color: var(--faint); }
/* The subfolder's active-session dot belongs on the row's RIGHT EDGE (John, 2026-09-23:
   "dot right aligned here"). It already carries margin-left:auto, but the renderer
   inserts it BEFORE .sf-dots and .sf-new, and those two hover controls still take flex
   space at the end of the row — so the auto margin pushed the dot against them instead
   of to the edge. Ordering it last on the flex line pins it to the edge and leaves the
   ⋯ and + to appear inboard of it on hover. Rounded to match every other status dot. */
html[data-skin="airy"] .subfolder-head .sf-active { order: 9; margin-left: auto; }
html[data-skin="airy"] .sf-active .fdot { border-radius: 50%; }

/* section carets stay: a small faint chevron says the block folds (John, 2026-09-20) */
html[data-skin="airy"] .sec-head .sec-caret, html[data-skin="airy"] .active-subhead .sec-caret, html[data-skin="airy"] .folder-subhead .sec-caret { display: inline-flex; width: 12px; height: 12px; margin: 0 4px 0 -2px; color: var(--faint); opacity: .8; background: transparent; }
html[data-skin="airy"] .sec-head .sec-caret svg, html[data-skin="airy"] .active-subhead .sec-caret svg { width: 8px; height: 8px; }
html[data-skin="airy"] .sec-head .sec-caret:hover, html[data-skin="airy"] .active-subhead:hover .sec-caret { color: var(--text); background: transparent; }
/* Same border triangle as the section carets — see the note on .sec-caret::before: a text
   chevron shifts vertically when the open state rotates it. */
html[data-skin="airy"] .side-branches .sb-head::before { content: ""; display: inline-block; width: 0; height: 0; border-style: solid; border-width: 3.5px 0 3.5px 5px; border-color: transparent transparent transparent var(--faint); margin-right: 6px; transform: rotate(90deg); transition: transform .12s; }
html[data-skin="airy"] .side-branches .sb-head.collapsed::before { transform: none; }

html[data-skin="airy"] #projectsHead .sec-title { flex: 0 0 auto; overflow: visible; text-overflow: clip; white-space: nowrap; }
/* flex-grow:1 made the input eat all the free space in the head, which killed its
   `margin-left: auto` and parked it hard against the title — hovering FOLDERS read as
   "FOLDERSFilter" (John, 2026-09-22). No grow: the auto margin pushes it to the right,
   just left of the +, and it shrinks instead of crowding the title in a narrow sidebar. */
html[data-skin="airy"] .proj-filter {
  flex: 0 1 120px; min-width: 72px; width: auto;
  margin-left: auto; margin-right: 10px; padding: 5px 8px;
}

/* ---- reading column, mockup 06 (John, 2026-09-20: "space, font, so much lighter") ---- */
html[data-skin="airy"] .msg.assistant { font-size: 15.5px; line-height: 1.65; }
html[data-skin="airy"] .msg.assistant .md-gap { height: 16px; }
html[data-skin="airy"] .msg.assistant .md-list { gap: 10px; margin: 4px 0 16px; }
html[data-skin="airy"] .msg.assistant .md-bullet { color: var(--faint); font-size: .75em; }
/* THE ACTION CARD KEEPS ITS CHECKBOX AND NOTHING ELSE (John, 2026-09-23: "remove the •
   next to the check mark"). The base sheet hides the bullet GLYPH with font-size:0 and
   draws the tick box as a ::before, but the two .msg.assistant .md-bullet rules above
   outscore it and put the dot back, so every to-do rendered as a dot next to a box.
   Re-zeroed here, for the numbered case too, and the box is re-stated at its own size
   because ::before inherits the zeroed font-size. */
html[data-skin="airy"] .action-card .md-li .md-bullet:not(.md-num) { font-size: 0; color: transparent; }
html[data-skin="airy"] .action-card .md-li .md-bullet:not(.md-num)::before { font-size: 0; }
html[data-skin="airy"] .msg.user { font: 15.5px/1.6 var(--ui-font); color: var(--muted); margin: 6px 0 10px; }
html[data-skin="airy"] .msg { margin: 0 0 12px; }
html[data-skin="airy"] .tool, html[data-skin="airy"] .tool.note { font-size: 11.5px; line-height: 1.6; color: var(--faint); margin: 0 0 6px; }
html[data-skin="airy"] .tool b, html[data-skin="airy"] .tool .tc-name { color: var(--muted); font-weight: 500; }
html[data-skin="airy"] .msg.assistant code { background: rgba(var(--ink-rgb),.04); font-size: .88em; }
html[data-skin="airy"] .composer { padding: 14px 14px 14px 22px; gap: 12px; }
html[data-skin="airy"] .composer textarea { font: 14.5px/1.5 var(--ui-font); caret-shape: auto; }
html[data-skin="airy"] .ta-caret-mirror { background: var(--text); opacity: .35; }
html[data-skin="airy"] .ta-wrap::before, html[data-skin="airy"] .composer::before { color: var(--faint); font-weight: 400; }
/* 32 → 28px (John, 2026-09-22: send and stop read a little too big). */
html[data-skin="airy"] .psend, html[data-skin="airy"] .pstop { width: 28px; height: 28px; }
html[data-skin="airy"] .q-model-def { background: var(--text) !important; border-color: transparent !important; -webkit-text-fill-color: var(--on-ink); font: 500 12.5px var(--ui-font); height: 30px; padding: 0 14px 0 12px; gap: 8px; }
html[data-skin="airy"] .q-model-def::before { content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; margin-right: 8px; }
html[data-skin="airy"] .q-model-def:hover { opacity: .85; }

html[data-skin="airy"] .composer::before { background: var(--faint); }
html[data-skin="airy"] .composer .ta-caret-mirror { background: var(--text); opacity: .3; }

html[data-skin="airy"] .composer .ta-wrap::after { background: var(--text); opacity: .3; }

/* ---- pane head as a tab (mockup 06 tabs row): dot, name, ink underline on the focused pane ---- */
/* The session title row is closed on BOTH edges now (John, 2026-09-23: "I want a line
   at the top of the session title, the same that we have at the bottom"). Same hairline
   token as the existing bottom rule, so the head reads as one banded strip. box-sizing
   is border-box here, so the extra 1px comes out of the 54px rather than growing it. */
html[data-skin="airy"] .pane .pane-head { height: 46px; padding: 0 22px 0 40px; gap: 14px; box-sizing: border-box; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
html[data-skin="airy"] .pane-head .phdot { width: 5px; height: 5px; border-radius: 50%; background: var(--faint); box-shadow: none; }
html[data-skin="airy"] .pane.focused .pane-head .phdot { background: var(--accent); }
html[data-skin="airy"] .pane-head .ptitle { font: 400 14.5px/1 var(--ui-font); color: var(--faint); padding: 16px 0 14px; border-bottom: 1px solid transparent; margin-bottom: -1px; }
html[data-skin="airy"] .pane.focused .pane-head .ptitle { color: var(--text); border-bottom-color: var(--text); }
html[data-skin="airy"] .pane-head .pscrap, html[data-skin="airy"] .pane-head .ppins, html[data-skin="airy"] .pane-head .pfork { opacity: 0; transition: opacity .12s; }
html[data-skin="airy"] .pane-head:hover .pscrap, html[data-skin="airy"] .pane-head:hover .ppins, html[data-skin="airy"] .pane-head:hover .pfork { opacity: 1; }
html[data-skin="airy"] .pane-head .pmodesel { font: 11px var(--airy-mono); letter-spacing: .1em; color: var(--faint); }
html[data-skin="airy"] .pane-head .pmore, html[data-skin="airy"] .pane-head .pclose { color: var(--muted); opacity: 1; }
html[data-skin="airy"] .pane.focused .pane-head .pmore, html[data-skin="airy"] .pane.focused .pane-head .pclose { color: var(--text); opacity: .85; }
html[data-skin="airy"] .pane-head .pmore:hover, html[data-skin="airy"] .pane-head .pclose:hover { color: var(--text); opacity: 1; background: var(--hover) !important; }
html[data-skin="airy"] .pane-head .q-auto .mc-track, html[data-skin="airy"] .pane-head .q-auto { transform: scale(.85); transform-origin: right center; }

/* the header tidy button is gone; Cmd+Shift+A tidies (John, 2026-09-20). Hidden here too for builds and snapshots that still carry it. */
html[data-skin="airy"] #tidyBtn { display: none; }

/* header: terminal and shortcuts buttons removed (John, 2026-09-20); shortcuts live in the account menu, the terminal on its shortcut */
html[data-skin="airy"] #shortcutsBtn, html[data-skin="airy"] #termToggle { display: none; }

/* context row: no drop shadow (John, 2026-09-20); the light-theme rule outranked the skin */
html[data-skin="airy"] body .ctx-pop, html[data-skin="airy"] body .ctx-pop:hover { box-shadow: none !important; }

/* ---- tabs + title bar, mockup 06 second pass (John, 2026-09-20: "tabs are super buggy") ----
   The base strip is a fixed 30px box with an edge-fade mask; the taller airy chips overflowed
   and the mask read as a black bar. Strip grows with its chips, no mask, no fill. */
/* The tab label starts where a normal session title ENDS (John, 2026-09-22: "the top of
   the session title when in tabs [must] align with the bottom when not in tabs"). A
   non-tabbed pane head is 22px of padding plus a 17px/1.3 title = 22.1px, so its title's
   bottom edge sits 39.5px below the pane top — measured in a headless Chromium against
   these two stylesheets, not estimated — so the strip's top padding is 40px. Change the
   head padding or the title size and this has to move with them.
   NOTE: this aligns the TAB LABEL with the neighbouring title's bottom. The tabbed pane's
   own head bar necessarily sits BELOW the tab row, so that second bar can never line up
   with a non-tabbed pane's head. */
/* The tab strip and a non-tabbed pane head must END on the same line (John, 2026-09-23:
   "Remove space above the tabs so the two red lines align"). Measured in headless Chromium
   against these two stylesheets, not derived on paper: at 25px top padding the strip's
   bottom edge and a non-tabbed pane head's bottom edge both land on y=53. Change the head
   padding, the title size or the chip padding and this has to be re-measured. */
/* Strip trimmed 5% (John, 2026-09-23). The 13.5px label line cannot shrink, so the
   whole 5% comes out of the padding: 25 + 13.5 + 14 = 52.5 becomes 23.4 + 13.5 + 13
   = 49.9. The chip and the active tab keep their 13px total so the underline still
   lands on the strip bottom. */
/* EQUAL SPACE ABOVE AND BELOW THE TAB LABEL (John, 2026-09-24: "the tab names should
   always have as much padding at the top than bottom no matter the font size"). The
   strip used to carry the top space (19px) and the chip the bottom space (13px), with the
   label nudged up 6px on top of that, so the label sat 13px from the top and 19px from
   its underline. Now the strip carries no vertical padding and the chip carries the same
   16px above and below its label. The label is centred by construction, whatever its font
   size, and the strip keeps its old 46.5px total: 16 + 13.5 + 16 + 1. */
html[data-skin="airy"] .tab-strip { height: auto; padding: 0 12px; gap: 0; background: transparent; border-bottom: 0; }
/* JOIN-AS-TAB HIGHLIGHT (John, 2026-09-23: "when I drag a session above the tabs, it
   should show on the tab area. I see nothing right now"). The base .tab-strip.drop-tab
   rule paints accent-soft, but airy's transparent .tab-strip outspecifies it, so the
   drop target showed nothing. Re-assert the highlight at airy's specificity. */
html[data-skin="airy"] .tab-strip.drop-tab { background: var(--accent-soft); border-radius: 6px; box-shadow: inset 0 0 0 2px var(--accent); }
/* Tabs were being cut mid-word because a 24px gap plus unbounded chip widths overflowed
   a half-width block long before the names ran out of room (John, 2026-09-23: "left and
   right get cropped way too early"). Tighter gutter, and each name ellipsizes at its own
   cap so every tab keeps a readable head instead of one long title eating the strip. */
html[data-skin="airy"] .tab-list { align-items: stretch; gap: 24px; -webkit-mask: none; mask: none; overflow-x: auto; }
/* The horizontal scroll on .tab-list also clips VERTICALLY: in CSS, when one overflow
   axis is not visible, the other computes to auto. The 6px label lift below therefore
   pushed the tops of the glyphs into that clip. This pads the clip box up by the same
   6px and pulls it back with an equal negative margin, so the painting area grows while
   the layout stays exactly where it was. Nothing is resized. (John, 2026-09-23.) */
html[data-skin="airy"] .tab-chip .tc-name { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-skin="airy"] .tab-chip, html[data-skin="airy"] .tab-chip.tinted:not(.active) {
  padding: 16px 0; margin: 0; gap: 8px; border: 0; border-bottom: 1px solid transparent; border-radius: 0;
  background: transparent !important; color: var(--faint); font: 13.5px/1 var(--ui-font);
}
html[data-skin="airy"] .tab-chip:hover { background: transparent !important; color: var(--text); }
/* THE ACTIVE TAB MUST READ AS SELECTED (John, 2026-09-22: "When I add a session to the
   tab section I don't see the highlight anymore"). A tabbed leaf hides the pane head, so
   the tab strip is the ONLY place that can say which session is on screen — and a 1px
   hairline in the same ink as the label was not saying it. The active tab now carries a
   2px ink underline and a heavier label; every other tab stays faint.

   THE TWO STATES MUST RESERVE THE SAME SPACE BELOW THE LABEL (John, 2026-09-23: "the
   moment I click on a tab, the text move a couple of pixels down"). Chips stretch to a
   common row height, so the label centres inside whatever the content box is after
   padding and border. Inactive spends 16 + 1 = 17 below the label; active must therefore spend 15 + 2,
   not 14 + 2, or its content box is a pixel taller and the label sinks into it. */
html[data-skin="airy"] .tab-chip.active, html[data-skin="airy"] .tab-chip.tinted.active {
  background: transparent !important; color: var(--text); font-weight: 500;
  padding-bottom: 15px; border-bottom: 2px solid var(--text);
}
html[data-skin="airy"] .tab-chip .tc-name { display: block; }
/* Tab label rides 2px higher INSIDE its own box (John, 2026-09-23: "within their own
   space, I want the tabs text to go higher a little bit. DO NOT RESIZE ANYTHING").
   A relative nudge only — it paints the glyphs higher and changes no box: the chip keeps
   its padding, the strip keeps its height, and the active tab's underline does not move.
   The status dot comes along by the same 2px so it stays on the label's centre line;
   leaving it behind would have knocked the two out of alignment. */
html[data-skin="airy"] .tab-chip .tc-name,
html[data-skin="airy"] .tab-chip .tc-dot { position: relative; top: 0; }
/* THE TAB DOT IS A STATUS LIGHT, NOT DECORATION (John, 2026-09-22: "dots should be
   activity colored dot"). updateTabChip already writes the status class (thinking /
   waiting / error / idle) and the model tint into --dot-c, but airy painted every dot
   var(--faint) and every active-or-running one var(--accent), both !important, so the
   status and the model colour never showed. Airy now only sets the SHAPE; the colour
   follows the same taxonomy as the sidebar dots. */
html[data-skin="airy"] .tab-chip .tc-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--dot-c, var(--faint)); }
html[data-skin="airy"] .tab-chip .tc-dot.thinking, html[data-skin="airy"] .tab-chip.running .tc-dot { background: var(--dot-c, var(--accent)); }
html[data-skin="airy"] .tab-chip .tc-dot.waiting { background: var(--dot-c, #45e3b0); }
html[data-skin="airy"] .tab-chip .tc-dot.error { background: #e0554a; }
html[data-skin="airy"] .tab-chip .tc-x { padding: 0 2px; }
html[data-skin="airy"] .tab-actions .pfork { color: var(--faint); }
/* title bar under the tabs: the name, big and ink; actions as mono words on the right */
html[data-skin="airy"] .pane .pane-head { height: auto; padding: 8px 22px 10px; gap: 16px; border-bottom: 0; }   /* top/bottom trimmed, top more (John, 2026-09-22) */
html[data-skin="airy"] .pane-head .phdot { display: inline-block; }
/* 17px read too large in the tab bar (John, 2026-09-22). */
html[data-skin="airy"] .pane-head .ptitle, html[data-skin="airy"] .pane.focused .pane-head .ptitle { font: 600 15px/1.3 var(--ui-font); color: var(--text); padding: 0; border-bottom: 0; margin: 0; }
html[data-skin="airy"] .pane-head .pscrap, html[data-skin="airy"] .pane-head .ppins, html[data-skin="airy"] .pane-head .pfork { opacity: 1; width: auto; height: auto; padding: 0 4px; }
html[data-skin="airy"] .pane-head .pscrap svg, html[data-skin="airy"] .pane-head .ppins svg, html[data-skin="airy"] .pane-head .pfork svg { display: none; }
html[data-skin="airy"] .pane-head .pscrap::after { content: "DOC"; }
html[data-skin="airy"] .pane-head .ppins::after { content: "PIN"; }
html[data-skin="airy"] .pane-head .pfork::after { content: "FORK"; }
html[data-skin="airy"] .pane-head .pscrap::after, html[data-skin="airy"] .pane-head .ppins::after, html[data-skin="airy"] .pane-head .pfork::after { font: 11px var(--airy-mono); letter-spacing: .12em; color: var(--faint); }
html[data-skin="airy"] .pane-head .pscrap:hover::after, html[data-skin="airy"] .pane-head .ppins:hover::after, html[data-skin="airy"] .pane-head .pfork:hover::after { color: var(--text); }

html[data-skin="airy"] .pane-head .ptitle, html[data-skin="airy"] .pane.focused .pane-head .ptitle { flex: 1 1 auto; min-width: 0; max-width: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-skin="airy"] .pane-head .phspacer { display: none; }

/* EVERY title bar keeps the paper surface (John, 2026-09-22: "some do some don't WHO KNOWS
   WHY"). This rule used to blank them to transparent, and because it listed
   .pane / .pane.focused / .pane.tinted but NOT .pane.tinted.focused, that one combination
   kept the white from the rule above it (specificity 0,4,0 beats 0,3,0, both !important).
   So the bar was white only while a tinted pane was focused — the random-looking part.
   The override is gone; .pane .pane-head above owns the background for all of them. */

html[data-skin="airy"] .pane-head .ptitle, html[data-skin="airy"] .pane.focused .pane-head .ptitle { flex: 1 1 0 !important; width: auto !important; max-width: none !important; }

/* title bar: give the name room. Tighter gaps, compact model word, DOC/PIN/FORK snug. */
html[data-skin="airy"] .pane .pane-head { gap: 12px; }
html[data-skin="airy"] .pane-head .pmodesel { font-size: 10.5px; letter-spacing: .06em; padding: 0 4px; }
html[data-skin="airy"] .pane-head .pscrap, html[data-skin="airy"] .pane-head .ppins, html[data-skin="airy"] .pane-head .pfork { padding: 0 2px; margin: 0; }
html[data-skin="airy"] .pane-head .pmore, html[data-skin="airy"] .pane-head .pclose { padding: 0; }

/* Tabbed panes get the SAME title section as a single pane (John, 2026-09-20: "this is
   the style of the session title section, even when in tabs"). Base app.css hides FORK,
   variants and the ✕ in a tab block; airy shows them so the bar reads identically. */
html[data-skin="airy"] .block .pane.in-tabblock .pane-head .pfork,
html[data-skin="airy"] .block .pane.in-tabblock .pane-head .pclose { display: inline-flex; opacity: 1; }
html[data-skin="airy"] .block .pane.in-tabblock .pane-head .pfork { width: auto; height: auto; padding: 0 2px; }

html[data-skin="airy"] .q-model-def { height: 24px; padding: 0 10px 0 8px; font: 500 12px var(--ui-font); gap: 6px; }
html[data-skin="airy"] .q-model-def::before { width: 6px; height: 6px; margin-right: 6px; }
html[data-skin="airy"] .q-attach { font-size: 16px; width: 24px; height: 24px; padding: 0; }
html[data-skin="airy"] .q-chip { height: 24px; font-size: 11.5px; }

/* ---- composer floats over the transcript (John, 2026-09-20): the wrapper is pulled up
   over the message list and made click-transparent, so text scrolls under the card;
   the list gets bottom padding so its last line can still clear the card. */
html[data-skin="airy"] .pane-composer { margin-top: -120px; background: transparent; pointer-events: none; z-index: 3; }
html[data-skin="airy"] .pane-composer > * { pointer-events: auto; }
html[data-skin="airy"] .pane-body { padding-bottom: 170px; }
/* The transcript must run under the card ALL THE WAY to the bottom edge of the pane
   (John, 2026-09-24: "I should be seeing the text going under and all the way down to
   the edge of the view here"). A negative margin only overlapped the list by 120px; the
   rest of the wrapper's height still sat below the list, leaving a blank band between
   the card and the pane edge. Take the wrapper out of the column entirely and pin it to
   the pane's bottom: .pane is position relative, so the list now fills the whole height
   and its last lines scroll behind the card and the bottom margin alike. The doc-split
   layout keeps its grid cell and the empty pane keeps its own centred placement. */
html[data-skin="airy"] .pane:not(.doc-split) > .pane-composer {
  position: absolute; left: 0; right: 0; bottom: 0; margin-top: 0;
}
html[data-skin="airy"] .pane.running .pane-body { padding-bottom: 170px; }

/* MC switch knob was the same grey as the off track (invisible). White knob with a shadow. */
html[data-skin="airy"] .mc-switch .mc-track::after { background: var(--on-ink); box-shadow: 0 1px 2px rgba(17,18,20,.25); }
html[data-skin="airy"] .mc-chip.on .mc-switch .mc-track::after { background: var(--on-ink); box-shadow: none; }

/* Hover highlights only the model/intensity chips, not the whole selector (the relay chip
   sits inside the same wrapper and lit up with it). */
html[data-skin="airy"] .pane-head .pmodesel:hover { background: transparent !important; }
html[data-skin="airy"] .pane-head .pmodesel .pmodel:hover, html[data-skin="airy"] .pane-head .pmodesel .peffort:hover { background: var(--hover) !important; color: var(--text); border-radius: 999px; }

/* Runs-on relay chip: icon only. The computer name slides out on hover; the native title
   still carries "Runs on <name>" / "<name> is asleep" (John, 2026-09-20). */
html[data-skin="airy"] .pane-head .prelay { max-width: none; height: 20px; padding: 0 5px; margin-right: 2px; border: none; border-radius: 999px; background: transparent; color: var(--accent); overflow: visible; text-overflow: clip; opacity: 1; cursor: default; }
html[data-skin="airy"] .pane-head .prelay svg { width: 13px; height: 13px; }
html[data-skin="airy"] .pane-head .prelay span { display: inline-block; max-width: 0; opacity: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--text); transition: max-width .18s ease, opacity .14s ease, padding .18s ease; }
html[data-skin="airy"] .pane-head .prelay:hover { background: var(--hover); }
html[data-skin="airy"] .pane-head .prelay:hover span { max-width: 180px; opacity: 1; padding: 0 4px 0 3px; }
html[data-skin="airy"] .pane-head .prelay.off { border: none; color: var(--faint); }
html[data-skin="airy"] .pane.minimized .pane-head .prelay span, html[data-skin="airy"] .pane-head.tight .prelay span { display: inline-block; }


/* ================================================================================
   Three surfaces rebuilt to the 06 language (John, 2026-09-20: "These three need a
   DRASTIC redesign"): the Action list popover, the account menu, and Settings.
   Paper card, no hard borders, mono eyebrows, ink pills, orange only as a signal.
   ================================================================================ */

/* ---- Action list popover (redesigned 2026-09-23) --------------------------------
   One sheet, three zones: a title row with the bulk actions, the list, and a composer
   pinned to the bottom. The composer used to sit above the list, so the first thing in
   view was an empty field with a stray scrollbar, and typing there jumped you to the
   other tab. It is now a footer well (flex order puts it last, sticky keeps it in view
   while the list scrolls), the way Reminders and Things place entry below the list.
   The title is set in the UI face, not the mono eyebrow, so it reads as a panel name
   rather than a form label. Eyebrows are kept for section heads only. Ink and accent
   pairs come from the theme tokens, so contrast holds in both modes. */
html[data-skin="airy"] .al-pop {
  display: flex; flex-direction: column;
  width: 400px; max-height: 64vh;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 16px; padding: 0;
  box-shadow: 0 1px 0 rgba(17,18,20,.05), 0 24px 60px rgba(17,18,20,.16);
  scrollbar-width: auto;
}
html[data-skin="airy"] .al-pop-head {
  flex: 0 0 auto; align-items: baseline;
  padding: 18px 20px 4px; margin: 0;
  font: 500 15px/1.2 var(--ui-font); letter-spacing: 0; text-transform: none; color: var(--text);
}
html[data-skin="airy"] .al-head-actions { gap: 14px; }
html[data-skin="airy"] .al-check-all, html[data-skin="airy"] .al-clear, html[data-skin="airy"] .al-clear-all {
  font: 500 12px/1 var(--ui-font); letter-spacing: 0; text-transform: none; color: var(--faint);
  padding: 4px 0; cursor: pointer;
}
html[data-skin="airy"] .al-check-all:hover, html[data-skin="airy"] .al-clear:hover { color: var(--text); }
html[data-skin="airy"] .al-clear-all:hover { color: #e5484d; }
html[data-skin="airy"] .al-tabs {
  flex: 0 0 auto; gap: 18px; padding: 8px 20px 0; margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
html[data-skin="airy"] .al-tab {
  flex: 0 0 auto; text-align: left; border: 0; border-radius: 0; background: transparent;
  padding: 8px 0 10px; font: 500 13px/1 var(--ui-font); color: var(--faint);
  box-shadow: inset 0 -1.5px 0 transparent; margin-bottom: -1px;
}
html[data-skin="airy"] .al-tab:hover { color: var(--text); }
html[data-skin="airy"] .al-tab.on { color: var(--text); background: transparent; box-shadow: inset 0 -1.5px 0 var(--text); }
/* rows: round check, hover well; the whole row is the target (Fitts) */
html[data-skin="airy"] .al-item {
  flex: 0 0 auto; gap: 12px; align-items: flex-start;
  margin: 0 8px; padding: 9px 12px; border-radius: 10px;
}
html[data-skin="airy"] .al-item:hover { background: var(--hover); }
html[data-skin="airy"] .al-check {
  width: 18px; height: 18px; margin-top: 1px; border: 1.5px solid rgba(var(--ink-rgb),.35);
  border-radius: 999px; background: transparent; transition: border-color .12s, background-color .12s;
}
html[data-skin="airy"] .al-item:hover .al-check { border-color: var(--text); }
html[data-skin="airy"] .al-item.done .al-check {
  background: var(--accent-live); border-color: var(--accent-live);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23111214' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-size: 11px 11px; background-position: center; background-repeat: no-repeat;
}
html[data-skin="airy"] body[data-accent="purple"] .al-item.done .al-check {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
}
html[data-skin="airy"] .al-text { font: 14px/1.45 var(--ui-font); color: var(--text); padding-top: 1px; }
html[data-skin="airy"] .al-text strong { color: var(--text); font-weight: 500; }
html[data-skin="airy"] .al-item.done .al-text { color: var(--faint); opacity: 1; text-decoration: line-through; text-decoration-color: rgba(var(--ink-rgb),.35); }
/* section heads (Done, session groups) keep the mono eyebrow */
html[data-skin="airy"] .al-done-head, html[data-skin="airy"] .al-group-head, html[data-skin="airy"] .al-tasks-head {
  flex: 0 0 auto; font: 10px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  padding: 16px 20px 4px; margin: 0; border: 0;
}
html[data-skin="airy"] .al-group-head { text-transform: none; letter-spacing: 0; font: 12px/1 var(--ui-font); }
html[data-skin="airy"] .al-group-sess { color: var(--muted); font-weight: 500; }
html[data-skin="airy"] .al-group-head.jump:hover .al-group-sess { color: var(--text); text-decoration: none; }
html[data-skin="airy"] .al-group-time { color: var(--faint); }
html[data-skin="airy"] .al-tasks { flex: 0 0 auto; border: 0; background: transparent; padding: 0; margin: 0; }
html[data-skin="airy"] .al-empty {
  flex: 0 0 auto; text-align: center; color: var(--faint); font: 13px/1.5 var(--ui-font);
  padding: 34px 32px 30px;
}
/* composer: a footer well pinned under the list */
html[data-skin="airy"] .al-add {
  order: 1; position: sticky; bottom: 0; z-index: 1; flex: 0 0 auto;
  margin: 8px 0 0; padding: 10px 12px 12px; gap: 8px; align-items: center;
  background: var(--panel-2); border-top: 1px solid var(--line);
  border-radius: 0 0 16px 16px;
}
html[data-skin="airy"] .al-add::before {
  content: "+"; flex: 0 0 auto; width: 18px; text-align: center;
  font: 400 18px/1 var(--ui-font); color: var(--faint); margin-left: 4px;
}
html[data-skin="airy"] .al-add-input {
  background: transparent; border: 0; border-radius: 0; padding: 8px 0; min-height: 32px;
  font: 14px/1.4 var(--ui-font); color: var(--text); overflow-y: auto; scrollbar-width: none;
}
html[data-skin="airy"] .al-add-input::-webkit-scrollbar { display: none; }
html[data-skin="airy"] .al-add-input:focus { border: 0; outline: none; }
html[data-skin="airy"] .al-add-input::placeholder { color: var(--faint); }
html[data-skin="airy"] .al-add-btn {
  background: var(--accent-live); color: var(--on-accent-live); border-radius: 999px;
  padding: 7px 14px; font: 500 12.5px/1 var(--ui-font);
}
html[data-skin="airy"] .al-add-btn:hover { filter: none; opacity: .85; }

/* ---- Account menu ---- */
html[data-skin="airy"] .acct-menu { width: 300px; background: var(--panel-2); border: 0; border-radius: 16px; padding: 10px; transform: none; box-shadow: 0 1px 0 rgba(17,18,20,.05), 0 24px 60px rgba(17,18,20,.16); }
html[data-skin="airy"] .acct-item { gap: 12px; padding: 9px 12px; border-radius: 10px; font: 14px var(--ui-font); color: var(--text); }
html[data-skin="airy"] .acct-item:hover { background: var(--hover); }
html[data-skin="airy"] .acct-item .acct-ic { color: var(--muted); }
html[data-skin="airy"] .acct-item .acct-ic svg { width: 15px; height: 15px; }
html[data-skin="airy"] .acct-invite { background: transparent; border: 0; margin: 0; font-weight: 500; }
html[data-skin="airy"] .acct-invite:hover { background: var(--hover); }
html[data-skin="airy"] .acct-sep { background: var(--line); opacity: .7; margin: 8px 12px; }
html[data-skin="airy"] .acct-group.eng-start, html[data-skin="airy"] .acct-solo.eng-start { border-top-color: var(--line); }
html[data-skin="airy"] .acct-footer { padding: 10px 12px 4px; }
html[data-skin="airy"] .acct-footer .acct-email, html[data-skin="airy"] .acct-footer .acct-ver, html[data-skin="airy"] .acct-email { font: 10.5px var(--airy-mono); letter-spacing: .04em; color: var(--faint); opacity: 1; }
html[data-skin="airy"] .acct-item .type { border-radius: 999px; font: 11px var(--airy-mono); letter-spacing: .04em; }
html[data-skin="airy"] .acct-item .type.plan-max { background: var(--text); color: var(--on-ink); font-weight: 500; }
html[data-skin="airy"] .acct-item .type.plan-pro { color: var(--text); border-color: var(--line); }
html[data-skin="airy"] .acct-item.is-selected::before { background: var(--text); }

/* ---- Settings ---- */
html[data-skin="airy"] .modal.set-modal { padding: 0; border-radius: 20px; }
html[data-skin="airy"] .set-head { padding: 30px 36px 10px; border-bottom: 0; }
html[data-skin="airy"] .set-head h3, html[data-skin="airy"] .modal.set-modal h3 { font: 400 28px/1.1 var(--airy-serif); letter-spacing: -.01em; color: var(--text); }
html[data-skin="airy"] .set-x { border-radius: 999px; width: 30px; height: 30px; color: var(--faint); }
html[data-skin="airy"] .set-x:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .set-nav { flex-basis: 224px; border-right: 0; background: transparent; padding: 8px 20px 20px 28px; gap: 2px; }
html[data-skin="airy"] .sn-search { margin: 4px 0 10px; }
html[data-skin="airy"] .sn-search-ic { left: 2px; }
html[data-skin="airy"] .set-nav .sn-search input, html[data-skin="airy"] .set-nav .sn-search input#setNavSearch { background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; padding: 8px 0 8px 22px; font: 13px var(--ui-font); }
html[data-skin="airy"] .set-nav .sn-search input#setNavSearch:focus { border-color: var(--text); }
html[data-skin="airy"] .sn-group { font: 10px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint); padding: 20px 10px 8px; }
html[data-skin="airy"] .sn-group:first-of-type { padding-top: 6px; }
html[data-skin="airy"] .set-nav-item { padding: 7px 10px; border-radius: 999px; font: 14px var(--ui-font); color: var(--muted); }
html[data-skin="airy"] .set-nav-item:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .set-nav-item.active { color: var(--text); background: var(--active); font-weight: 500; }
html[data-skin="airy"] .set-nav-item.active .sn-ic, html[data-skin="airy"] .sn-ic { color: var(--muted); opacity: 1; }
html[data-skin="airy"] .set-nav-item.active .sn-ic { color: var(--text); }
html[data-skin="airy"] .set-modal .set-content { padding: 4px 40px 36px 28px; }
html[data-skin="airy"] .set-card { gap: 24px; padding: 18px 0; border-radius: 0; }
html[data-skin="airy"] .set-card + .set-card { border-top: 0; padding-top: 18px; }
html[data-skin="airy"] .set-name { font: 500 15px/1.3 var(--ui-font); letter-spacing: 0; color: var(--text); }
html[data-skin="airy"] .set-sub { font: 13px/1.45 var(--ui-font); color: var(--muted); margin-top: 3px; letter-spacing: 0; }
html[data-skin="airy"] .set-hint { font: 12.5px/1.55 var(--ui-font); color: var(--faint); margin-top: 8px; }
html[data-skin="airy"] .set-hint code { background: transparent; border: 0; padding: 0; font: 12px var(--airy-mono); color: var(--text); }
html[data-skin="airy"] .settings-sec-title, html[data-skin="airy"] .set-sec-label, html[data-skin="airy"] .set-sub-title { font: 10px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint); margin: 26px 0 4px; }
html[data-skin="airy"] .settings-sec-title:first-child { margin-top: 10px; }
html[data-skin="airy"] .seg { background: transparent; border: 0; padding: 0; gap: 2px; }
html[data-skin="airy"] .seg button { color: var(--faint); font: 13px var(--ui-font); padding: 5px 11px; border-radius: 999px; }
html[data-skin="airy"] .seg button:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .seg button.active { background: var(--text); color: var(--on-ink); font-weight: 500; }
html[data-skin="airy"] .btn-ghost, html[data-skin="airy"] .modal .btn-ghost { background: transparent; color: var(--text); border: 1px solid var(--line); border-radius: 999px; font: 500 13px var(--ui-font); padding: 7px 14px; }
html[data-skin="airy"] .btn-ghost:hover, html[data-skin="airy"] .modal .btn-ghost:hover { background: var(--hover); border-color: var(--line); color: var(--text); }
html[data-skin="airy"] .btn-ghost.sm, html[data-skin="airy"] .btn-primary.sm { padding: 5px 12px; font-size: 12.5px; }
html[data-skin="airy"] .btn-primary, html[data-skin="airy"] .modal .btn-primary { background: var(--text); color: var(--on-ink); border: 0; border-radius: 999px; font: 500 13px var(--ui-font); padding: 7px 15px; }
html[data-skin="airy"] .btn-primary:hover { filter: none; opacity: .85; }
html[data-skin="airy"] .q-auto-track { background: rgba(var(--ink-rgb),.16); }
html[data-skin="airy"] .q-auto-track::after { background: var(--on-ink); box-shadow: 0 1px 2px rgba(17,18,20,.25); }
html[data-skin="airy"] .q-auto input:checked + .q-auto-track { background: var(--text); }
html[data-skin="airy"] .q-auto input:checked + .q-auto-track::after { box-shadow: none; }
html[data-skin="airy"] .set-key-input, html[data-skin="airy"] .modal input, html[data-skin="airy"] .modal.set-modal input[type="text"], html[data-skin="airy"] .modal.set-modal input[type="password"] { background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; padding: 8px 0; font: 13.5px var(--ui-font); color: var(--text); }
html[data-skin="airy"] .set-key-input:focus, html[data-skin="airy"] .modal input:focus { border-color: var(--text); outline: none; }
html[data-skin="airy"] .set-modal .set-content::-webkit-scrollbar, html[data-skin="airy"] .set-nav::-webkit-scrollbar { width: 8px; }
html[data-skin="airy"] .set-modal .set-content::-webkit-scrollbar-thumb, html[data-skin="airy"] .set-nav::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }

/* ---- settings: one row language, one control rail (John, 2026-09-23: "messy,
   unfinished") -----------------------------------------------------------------
   Measured in a headless render of this exact markup against this exact stylesheet.
   The panel did not look unfinished because any one page was wrong; it looked
   unfinished because rows spoke three different visual languages and nothing shared
   a right-hand edge, so the eye never found a repeating beat. Three measured breaks,
   fixed here and nowhere else. */

/* 1. The hint line sat 2px right of the title it belongs to (title x=442, hint x=444)
      because the base .set-hint carries margin: 9px 2px 0 while airy zeroes the card's
      own side padding. Too small to read as an indent, too big to read as aligned. */
html[data-skin="airy"] .set-hint { margin-left: 0; margin-right: 0; }

/* 2. Permissions was the only page drawing rows as bordered, tinted cards while every
      other page draws them borderless on paper — and its 12px row padding pushed the
      Open button to x=1257 while every other control lands on x=1270. Same row, same
      language, same rail. */
html[data-skin="airy"] .perm-row {
  background: transparent; border: 0; border-radius: 0; padding: 14px 0; gap: 12px;
}
html[data-skin="airy"] .perm-row + .perm-row { border-top: 1px solid var(--line); }

/* 3. Account mixed both button placements on one page: Update and Save sat on the rail
      at x=1270, while Set up authenticator (598), the plan button (603) and Delete
      account (591) sat left-aligned under their label. A row whose .acct-row holds only
      buttons now right-aligns them; rows with a field keep the field flush left and the
      button on the rail, which is where they already were. */
html[data-skin="airy"] .acct-row:not(:has(input)):not(:has(code)) { justify-content: flex-end; }


/* context card hidden for now (John, 2026-09-20); element and refreshCtxCard stay live, only the paint is off */
html[data-skin="airy"] .ctx-pop, html[data-skin="airy"] .ctx-pop.show { display: none !important; }

/* Model-colour tick on assistant replies: the skin zeroed the message padding, so the tick
   sat on the first letter. It now lives in the left gutter, clear of the text. */
html[data-skin="airy"] .msg.assistant.arrowed { padding-left: 0; }
html[data-skin="airy"] .msg.assistant.arrowed::before { left: -16px; top: 10px; width: 2px; height: 14px; }

/* Session rows sit a touch inside the folder name (John, 2026-09-20: "indent a tiny bit"). */
html[data-skin="airy"] .tree .row.session, html[data-skin="airy"] .folder-item.open > .kids .row.session { padding-left: 14px; }

/* Section eyebrows align with the row text; the fold caret moves out into the left gutter
   (John, 2026-09-20: "push the group titles to the left, so the > is out in the white space"). */
html[data-skin="airy"] .sec-head, html[data-skin="airy"] .side-branches .sb-head, html[data-skin="airy"] .folder-subhead, html[data-skin="airy"] .active-subhead { position: relative; }
html[data-skin="airy"] .sec-head .sec-caret, html[data-skin="airy"] .active-subhead .sec-caret, html[data-skin="airy"] .folder-subhead .sec-caret { position: absolute; left: 7px; bottom: 5px; margin: 0; }
html[data-skin="airy"] .side-branches .sb-head::before { position: absolute; margin: 0; }

/* One caret glyph everywhere (John, 2026-09-20): the section headers used an SVG triangle,
   Open branches a text chevron. All use the text chevron now, a touch bigger. */
html[data-skin="airy"] .sec-head .sec-caret svg, html[data-skin="airy"] .active-subhead .sec-caret svg, html[data-skin="airy"] .folder-subhead .sec-caret svg { display: none; }
html[data-skin="airy"] .sec-head .sec-caret, html[data-skin="airy"] .active-subhead .sec-caret, html[data-skin="airy"] .folder-subhead .sec-caret { width: 14px; height: 14px; left: 6px; bottom: 4px; align-items: center; justify-content: center; }
/* A BORDER TRIANGLE, NOT A TEXT CHEVRON (John, 2026-09-22: "the title still moves when
   collapsing"). Measured on his two shots, against the + button as the common anchor: the
   title sat at the same offset in both states (-2.0px), but the caret moved 5px (-6.5 open
   vs -1.5 collapsed) — and a caret jumping under the eyebrow reads as the whole row moving.
   Cause: "\203A" is not centred inside its em box, and the open state rotates the caret 90°,
   which turns that horizontal ink offset into a vertical one. A triangle drawn from borders
   is exactly centred in its box, so rotating it about that centre moves nothing. */
html[data-skin="airy"] .sec-head .sec-caret::before, html[data-skin="airy"] .active-subhead .sec-caret::before, html[data-skin="airy"] .folder-subhead .sec-caret::before {
  content: ""; width: 0; height: 0; border-style: solid;
  border-width: 3.5px 0 3.5px 5px; border-color: transparent transparent transparent currentColor;
}
/* Open Branches draws its triangle straight on the head (a 5x7 box), while every other
   section centres the same triangle inside a 14x14 .sec-caret at left:6px/bottom:4px.
   Same numbers on two different boxes put the ink 4.5px left and 3.5px low, which is the
   misalignment John saw (2026-09-22). Match the OTHERS' ink centre instead: sec-caret ink
   sits at 13px from the head's left edge and 11px from its bottom, so this 5x7 triangle
   needs left 13-2.5 and bottom 11-3.5. */
html[data-skin="airy"] .side-branches .sb-head::before { left: 10.5px; bottom: 7.5px; }

/* Master Controller "N running" badge hidden for now (John, 2026-09-20); the jobs popup still opens from the chip. */
html[data-skin="airy"] .mc-jobs-badge { display: none !important; }

/* Model picker (John, 2026-09-20): dividers span the full width; the first row (Global Model
   title) and the section eyebrows lose their extra left inset. */
html[data-skin="airy"] .row-menu-sep { margin: 6px 0; }
html[data-skin="airy"] .row-menu-header { padding-left: 10px; }
html[data-skin="airy"] .row-menu-item { padding-left: 10px; }

/* FORK lives only in the ⋯ menu now (John, 2026-09-20); hide the header/tab button. */
html[data-skin="airy"] .pane-head .pfork, html[data-skin="airy"] .tab-actions .pfork { display: none !important; }
/* No rectangle fill behind the DOC/PIN text pills on hover — ink change only. */
html[data-skin="airy"] .pane-head .pscrap:hover, html[data-skin="airy"] .pane-head .ppins:hover { background: transparent !important; }

/* Kill the orange in the invite modal (John, 2026-09-20): the gift square and buttons go ink;
   airy already maps --accent to ink but these carried hardcoded rust/orange hexes. */
html[data-skin="airy"] .invite-gift { background: var(--text); box-shadow: none; border-radius: 14px; }
html[data-skin="airy"] .invite-copy, html[data-skin="airy"] .invite-send { background: var(--text) !important; color: var(--on-ink); border-radius: 999px; font-weight: 500; }
html[data-skin="airy"] .invite-copy:hover, html[data-skin="airy"] .invite-send:hover:not(:disabled) { filter: none; opacity: .85; }
html[data-skin="airy"] .invite-copy.done { background: #2e9e5b !important; }
html[data-skin="airy"] .invite-code, html[data-skin="airy"] .invite-coderow .invite-code { color: var(--text); }
html[data-skin="airy"] .invite-card { border-radius: 20px; }

/* Orange gone everywhere (John, 2026-09-20): remap the airy accent to ink so every
   var(--accent) fill — buttons, dots, focus, links — reads monochrome. */
html[data-skin="airy"] body, html[data-skin="airy"] body[data-accent], html[data-skin="airy"] body[data-theme], html[data-skin="airy"] body[data-theme]:not([data-preset]), html[data-skin="airy"] body[data-preset] { --accent-rgb: var(--ink-rgb); --accent: var(--text); --accent-soft: rgba(var(--ink-rgb),.06); --accent-ink: var(--on-ink); }

/* Header layout (John, 2026-09-20): drop the Claude status dot; layouts control to the far
   left; Master Controller to the right by the layout tabs. Flex order reshuffles in place. */
html[data-skin="airy"] header #claudeStatus { display: none !important; }
html[data-skin="airy"] header { position: relative; }
html[data-skin="airy"] header #layoutsCtl { order: -3; margin-left: 0; }
html[data-skin="airy"] header #layoutTabs { order: -2; }
html[data-skin="airy"] header #mcChip { order: 50; margin-left: auto; margin-right: 0; padding-right: 0; }
html[data-skin="airy"] header #hdrSep2 { order: 49; margin-left: auto; margin-right: 8px; }   /* divider between Team chat and MC (John, 2026-09-24) */
html[data-skin="airy"] header #mcChip { margin-left: 0; }
html[data-skin="airy"] header { padding-right: 18px; }

/* Model as plain text, on the send-button row (John, 2026-09-20). Strip the ink pill, drop
   the dot, mono lowercase, and pin it just left of the send button. */

html[data-skin="airy"] .q-model-def:hover { opacity: 1; color: var(--text) !important; }
html[data-skin="airy"] .q-model-def::before, html[data-skin="airy"] .q-model-def .q-model-def-dot { display: none !important; }
html[data-skin="airy"] .q-model-def-name { -webkit-text-fill-color: currentColor; }


/* Queue count as a small round chip at the composer card top-right (John, 2026-09-20). */
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue { height: 22px; min-width: 22px; padding: 0 7px; border-radius: 999px; border: 1px solid var(--line); background: transparent; color: var(--muted); gap: 3px; }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue .q-n { background: transparent; color: inherit; min-width: 0; height: auto; padding: 0; font: 12px var(--airy-mono); }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue .q-caret { color: var(--faint); }

/* Branch-out fan, minimal palette (John, 2026-09-20): working lanes/dots read orange (the
   one place orange is a status, not chrome); done reads ink; queued stays faint gray. */
html[data-skin="airy"] .bo-graph { overflow: visible; }
html[data-skin="airy"] .bo-gx { stroke: rgba(var(--ink-rgb),.18); stroke-width: 1; }
html[data-skin="airy"] .bo-gx.run { stroke: var(--text); opacity: .9; }
html[data-skin="airy"] .bo-gx.done { stroke: rgba(var(--ink-rgb),.32); opacity: 1; }
html[data-skin="airy"] .bo-gx.err { stroke: #e5484d; opacity: .8; }
html[data-skin="airy"] .bo-gx.wait { stroke: rgba(var(--ink-rgb),.14); }
html[data-skin="airy"] .bo-gn { stroke: var(--panel-2); stroke-width: 1.5; }
html[data-skin="airy"] .bo-gn.ctl { fill: var(--text); }
html[data-skin="airy"] .bo-gn.run { fill: var(--text); }
html[data-skin="airy"] .bo-gn.done { fill: var(--text); }
html[data-skin="airy"] .bo-gn.err { fill: #e5484d; }
html[data-skin="airy"] .bo-gn.wait { fill: rgba(var(--ink-rgb),.28); }
html[data-skin="airy"] .bo-graphwrap { margin: 14px 0 6px; }

html[data-skin="airy"] .bo-graph { width: 100%; height: 120px; }

html[data-skin="airy"] .pane-composer .ph-flow .q-auto-track { width: 28px; height: 16px; background: rgba(var(--ink-rgb),.16); }
html[data-skin="airy"] .pane-composer .ph-flow .q-auto-track::after { width: 12px; height: 12px; background: var(--on-ink); box-shadow: 0 1px 2px rgba(17,18,20,.25); }
html[data-skin="airy"] .pane-composer .ph-flow input:checked + .q-auto-track { background: var(--text); }
html[data-skin="airy"] .pane-composer .ph-flow input:checked + .q-auto-track::after { transform: translateX(12px); box-shadow: none; }

/* ---- every transcript card wears the recap/action block (John, 2026-09-20: "make sure all
   these cards are redesigned with the new style. Also make sure the left and right padding
   are exactly the same as the text"): no panel, no chip, no divider strip. One hairline in
   the left gutter, a mono eyebrow, ink body. The rail is pulled 20px into the gutter and the
   body padded 20px back, so card text starts and ends on the same column as the prose. */
html[data-skin="airy"] :is(.ask-card, .note-card, .doc-card, .memory-card, .recap-card, .action-card,
  .raw-data-card, .cmd-card, .notice.mc-notice, .task-card, .bg-task-card, .mc-job-card) {
  --accent: var(--text); --accent-rgb: var(--ink-rgb); --accent-soft: rgba(var(--ink-rgb),.06); --accent-ink: var(--on-ink);
  --nc: var(--text); --ac: var(--text); --bo-lt: var(--text); --bo-rgb: 17, 18, 20;
  background: transparent !important; border: 0 !important;
  border-left: 1px solid var(--line) !important; border-radius: 0 !important;
  box-shadow: none !important; padding: 4px 0 4px 19px !important;
  margin: 26px 0 26px -20px !important; max-width: none;
}
html[data-skin="airy"] .msg.assistant > :is(.ask-card, .note-card, .doc-card, .memory-card, .recap-card,
  .action-card, .raw-data-card, .cmd-card, .notice.mc-notice, .task-card):first-child { margin-top: 4px !important; }
html[data-skin="airy"] .msg.assistant > :is(.ask-card, .note-card, .doc-card, .memory-card, .recap-card,
  .action-card, .raw-data-card, .cmd-card, .notice.mc-notice, .task-card):last-child { margin-bottom: 4px !important; }

/* header strips: no divider, no inset, the label becomes a mono eyebrow */
html[data-skin="airy"] :is(.ask-head, .note-card .nc-head, .doc-card .nc-head, .doc-card-head,
  .mc-notice .mc-ntc-head, .raw-data-row, .cmd-head) {
  padding: 0 !important; border-bottom: 0 !important; margin: 0 0 10px; gap: 4px 10px; background: transparent;
}
html[data-skin="airy"] :is(.ask-from, .ask-sep, .ask-kind, .ask-chip, .note-card .nc-from, .note-card .nc-sep,
  .note-card .nc-kind, .note-card .nc-chip, .doc-card-title, .doc-card-sub, .mc-notice .mc-ntc-eyebrow,
  .raw-data-label, .raw-data-toggle, .cmd-copy) {
  font: 10px var(--airy-mono) !important; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint) !important; background: transparent !important; border: 0 !important;
  padding: 0 !important; border-radius: 0 !important; font-weight: 400 !important;
}
html[data-skin="airy"] :is(.ask-from, .note-card .nc-from, .doc-card-title) { color: var(--muted) !important; }
html[data-skin="airy"] :is(.ask-sep, .note-card .nc-sep) { margin: 0 6px !important; }
html[data-skin="airy"] :is(.ask-chip, .note-card .nc-chip, .raw-data-toggle, .cmd-copy) { margin-left: auto; }
html[data-skin="airy"] .mc-notice .mc-ntc-dot { background: var(--text); animation: none; width: 5px; height: 5px; }
html[data-skin="airy"] .doc-card-ic { color: var(--faint); font-size: 11px; }

/* bodies: the reading column's own type, flush with the prose */
html[data-skin="airy"] :is(.ask-body, .note-card .nc-body, .doc-card-txt, .mc-notice .mc-ntc-body,
  .raw-data-body, .cmd-card .cmd-text) { padding: 0 !important; }
html[data-skin="airy"] :is(.ask-q, .note-card .nc-body, .mc-notice .mc-ntc-body, .doc-card-sub, .doc-card-summary) {
  font: 15px/1.6 var(--ui-font) !important; color: var(--text) !important; letter-spacing: 0; text-transform: none;
}
html[data-skin="airy"] :is(.doc-card-sub, .doc-card-summary) { color: var(--muted) !important; margin-top: 4px; }
html[data-skin="airy"] .ask-q code { background: rgba(var(--ink-rgb),.04) !important; color: var(--text) !important; font-size: .88em; }
html[data-skin="airy"] :is(.raw-data-body, .cmd-card .cmd-text) { font: 12.5px/1.6 var(--airy-mono) !important; color: var(--muted) !important; }
html[data-skin="airy"] :is(.note-card .nc-body .md-bullet, .mc-notice .md-bullet) { color: var(--faint) !important; }
html[data-skin="airy"] :is(.note-card .nc-body .a-link, .mc-notice .a-link) {
  color: var(--text) !important; font-weight: 400; text-decoration: underline;
  text-decoration-color: rgba(var(--ink-rgb),.3); text-underline-offset: 3px; filter: none;
}

/* buttons: one ink pill for the primary, hairline ghosts for the rest */
html[data-skin="airy"] :is(.ask-actions, .mc-notice .mc-ntc-actions) { gap: 10px; margin-top: 16px; }
html[data-skin="airy"] .ask-btn {
  font: 500 13px var(--ui-font) !important; letter-spacing: 0; text-transform: none;
  background: transparent !important; border: 1px solid var(--line) !important; border-radius: 8px !important;
  color: var(--muted) !important; padding: 7px 16px !important; box-shadow: none !important;
}
html[data-skin="airy"] .ask-btn:hover { background: var(--hover) !important; color: var(--text) !important; border-color: var(--line) !important; filter: none; }
html[data-skin="airy"] :is(.ask-btn.ask-yes, .ask-card.answered .ask-btn.chosen, .mc-notice .ask-yes) {
  background: var(--text) !important; border-color: var(--text) !important; color: var(--on-ink) !important; font-weight: 500 !important;
}
html[data-skin="airy"] :is(.ask-btn.ask-yes:hover, .mc-notice .ask-yes:hover) { opacity: .85; filter: none !important; }
html[data-skin="airy"] .ask-card.answered .ask-yes:not(.chosen) {
  background: transparent !important; border-color: var(--line) !important; color: var(--muted) !important; font-weight: 500 !important;
}
html[data-skin="airy"] .ask-answered { font: 10px var(--airy-mono) !important; letter-spacing: .14em; text-transform: uppercase; color: var(--faint) !important; margin-top: 12px; }
html[data-skin="airy"] .ask-reply { margin-left: auto; }

/* task rows: ink checkbox, body type */
html[data-skin="airy"] .task-card .task-card-check { border: 1.5px solid rgba(var(--ink-rgb),.3) !important; border-radius: 4px; }
html[data-skin="airy"] .task-card .task-card-row:hover .task-card-check { border-color: var(--text) !important; }
html[data-skin="airy"] .task-card .task-card-row.done .task-card-check { background: var(--text) !important; border-color: var(--text) !important; }
html[data-skin="airy"] .task-card .task-card-text { font: 15px/1.6 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .task-card .task-card-list { gap: 6px; margin-top: 4px; }


/* the doc card's right-hand action word ("EDITED", "OPEN") was still a filled chip */
html[data-skin="airy"] :is(.doc-card-go, .nc-chip, .nc-chip.nc-date, .mc-ntc-close) {
  font: 10px var(--airy-mono) !important; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint) !important; background: transparent !important; border: 0 !important;
  padding: 0 !important; border-radius: 0 !important; font-weight: 400 !important; margin-left: auto;
}
html[data-skin="airy"] .doc-card-item {
  background: transparent !important; border: 0 !important; border-radius: 0 !important;
  padding: 4px 0 !important; color: var(--text) !important;
}
html[data-skin="airy"] .doc-card-item:hover { background: transparent !important; text-decoration: underline; text-underline-offset: 3px; }
html[data-skin="airy"] .doc-card-item-name { font: 500 14px var(--ui-font) !important; color: var(--text) !important; }
html[data-skin="airy"] .doc-card-item-sum { font: 13px/1.5 var(--ui-font) !important; color: var(--muted) !important; }


/* ================= COLLAPSED RAIL, REDESIGNED (John, 2026-09-20) =====================
   Was: a column of identical gray dots — nothing identified a session. Now each session
   is a named tile carrying its initial, with state read from the tile, not a loose dot.
   Focused = filled ink. Working = ink ring + a small corner mark. Idle = quiet outline. */
html[data-skin="airy"] body.collapsed aside { width: 60px; }
html[data-skin="airy"] body.collapsed .active-list { padding: 8px 0; display: flex; flex-direction: column; align-items: center; gap: 8px; }
html[data-skin="airy"] body.collapsed .active-row {
  position: relative; width: 34px; height: 34px; margin: 0; padding: 0; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--line); color: var(--muted); overflow: visible;
  transition: background .12s, border-color .12s, color .12s;
}
html[data-skin="airy"] body.collapsed .active-row::after {
  content: attr(data-ini); font: 500 13px var(--airy-mono); letter-spacing: 0; color: inherit; line-height: 1;
}
html[data-skin="airy"] body.collapsed .active-row:hover { border-color: var(--muted); color: var(--text); background: var(--hover); }
/* focused session: solid ink tile */
html[data-skin="airy"] body.collapsed .active-row.active { background: var(--text); border-color: var(--text); color: var(--on-ink); }
/* the loose status dot becomes a small corner mark on the tile */
html[data-skin="airy"] body.collapsed .active-row .adot {
  position: absolute; top: -2px; right: -2px; width: 8px; height: 8px; margin: 0; border-radius: 50%;
  border: 2px solid var(--bg); box-shadow: none;
}
html[data-skin="airy"] body.collapsed .active-row .adot.idle { display: none; }
html[data-skin="airy"] body.collapsed .active-row .adot.thinking { background: #ff6a44; display: inline-block; }
html[data-skin="airy"] body.collapsed .active-row .adot.waiting { background: var(--muted); display: inline-block; }
/* everything textual stays hidden in the rail */
html[data-skin="airy"] body.collapsed .active-row .meta,
html[data-skin="airy"] body.collapsed .active-row .astatus,
html[data-skin="airy"] body.collapsed .active-row .row-q,
html[data-skin="airy"] body.collapsed .active-row .aconn,
html[data-skin="airy"] body.collapsed .active-row .aspec { display: none !important; }
/* the folder button matches the tiles */
html[data-skin="airy"] body.collapsed .rail-folder-btn {
  width: 34px; height: 34px; border-radius: 11px; border: 1px solid var(--line); color: var(--muted); background: transparent;
}
html[data-skin="airy"] body.collapsed .rail-folder-btn:hover { color: var(--text); border-color: var(--muted); background: var(--hover); }

/* An earlier no-hairlines pass sets border:0 !important on rows, so the rail tiles need
   !important to draw their outline. Also drop the section heads — no room in the rail. */
html[data-skin="airy"] body.collapsed .active-row { border: 1px solid var(--line) !important; background: transparent !important; }
html[data-skin="airy"] body.collapsed .active-row:hover { border-color: var(--muted) !important; background: var(--hover) !important; }
html[data-skin="airy"] body.collapsed .active-row.active { background: var(--text) !important; border-color: var(--text) !important; color: var(--on-ink); }
html[data-skin="airy"] body.collapsed .active-subhead,
html[data-skin="airy"] body.collapsed #activeWrap .sec-head,
html[data-skin="airy"] body.collapsed .folder-subhead { display: none !important; }

/* ---- the queue, in the airy language (John, 2026-09-20: "this style is way too off
   compared to the new one, adapt it completely"). The drawer was still the dark app's
   boxed list: grey filled cards, bordered icon buttons, a filled branch-out slab. Here it
   is paper: a mono eyebrow for the header, hairline-separated requests with no fill, plain
   text for the model, flat glyph buttons, and one ink send. Text starts on the same column
   as the header, so the list reads as prose, not as a stack of tiles. */
html[data-skin="airy"] .q-head { padding: 26px 20px 12px; gap: 14px; }
html[data-skin="airy"] .q-title-wrap { gap: 8px; }
html[data-skin="airy"] .q-title { font: 11px/1 var(--airy-mono); font-weight: 400; letter-spacing: .16em; text-transform: uppercase; color: var(--faint); }
html[data-skin="airy"] .q-count-badge { background: transparent; border: 0; padding: 0; color: var(--faint); font: 11px/1 var(--airy-mono); }
html[data-skin="airy"] .q-auto { gap: 8px; color: var(--faint); font-size: 12.5px; }
html[data-skin="airy"] .q-auto .q-auto-track { width: 28px; height: 16px; background: rgba(var(--ink-rgb),.16); }
html[data-skin="airy"] .q-auto .q-auto-track::after { width: 12px; height: 12px; background: var(--on-ink); box-shadow: 0 1px 2px rgba(17,18,20,.25); }
html[data-skin="airy"] .q-auto input:checked + .q-auto-track { background: var(--text); }
html[data-skin="airy"] .q-auto input:checked + .q-auto-track::after { transform: translateX(12px); box-shadow: none; }
html[data-skin="airy"] .q-auto input:checked ~ .q-auto-lbl { color: var(--muted); }
html[data-skin="airy"] :is(.q-clear, .q-x) { border: 0; background: transparent; color: var(--faint); border-radius: 999px; width: 28px; height: 28px; }
html[data-skin="airy"] .q-x:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .q-clear:hover { background: transparent; border-color: transparent; color: #d0402f; }
/* "Clear" as a word instead of a trash glyph, and the queue ✕ on the exact same column
   as the pane title ✕ (John, 2026-09-22). Both closers are 28px boxes flush to a 22px
   edge inset, so their centres land on the same x with no measuring. */
html[data-skin="airy"] .q-clear { width: auto; padding: 0 10px; font: 12.5px/1 var(--ui-font); letter-spacing: 0; text-transform: none; }
html[data-skin="airy"] .q-head { padding-right: 22px; }
html[data-skin="airy"] .pane-head .pclose,
html[data-skin="airy"] .pane-head .pmore {
  width: 28px; height: 28px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px; font-size: 16px; font-weight: 600; line-height: 1; transition: color .12s, opacity .12s, background .12s;
}
html[data-skin="airy"] .pane-head .pclose { font-size: 13px; font-weight: 400; }
/* Title-bar ✕ nudged right and set off from ⋯ by a hairline (John, 2026-09-25). */
html[data-skin="airy"] .pane-head .pclose { position: relative; margin-right: -8px; }
html[data-skin="airy"] .pane-head .pclose::before { content: ''; position: absolute; left: -8px; top: 6px; bottom: 6px; width: 1px; background: var(--line); pointer-events: none; }

/* Branch out: a quiet full-width action with one hairline, ink type, no orange slab. */
html[data-skin="airy"] .q-branchout { background: transparent; border: 1px solid var(--line); border-radius: 999px; color: var(--text); font-size: 13px; font-weight: 500; padding: 10px; margin: 2px 0 14px; }
html[data-skin="airy"] .q-branchout:hover { background: var(--hover); border-color: rgba(var(--ink-rgb),.22); }
html[data-skin="airy"] .q-branchout svg { color: var(--faint); }

/* One request = one block of prose with a hairline above it. No fill, no card border. */
html[data-skin="airy"] .q-item { background: transparent !important; border: 0; border-top: 1px solid var(--line); border-radius: 0; padding: 14px 0 16px; margin: 0; gap: 9px; }
html[data-skin="airy"] .q-item:first-of-type { border-top: 0; }
html[data-skin="airy"] .q-item:hover { background: transparent !important; border-color: var(--line); }
html[data-skin="airy"] .q-item.team-query { border-left: 0; padding-left: 11px; box-shadow: inset 2px 0 0 -1px var(--accent); }
html[data-skin="airy"] .q-item .q-text { font-size: 14px; line-height: 1.55; color: var(--text); padding: 0; }
html[data-skin="airy"] .q-item .q-text:focus { background: transparent; box-shadow: none; }
html[data-skin="airy"] .q-drag { color: rgba(var(--ink-rgb),.2); font-size: 13px; padding: 0 2px 0 0; }
html[data-skin="airy"] .q-item:hover .q-drag { color: var(--faint); }

/* Model pin: plain mono text, in the model's colour only once you pin it. */
html[data-skin="airy"] .q-model, html[data-skin="airy"] .q-model.pinned {
  background: transparent !important; border: 0 !important; padding: 0; max-width: 190px;
  color: var(--faint); font: 12px var(--airy-mono); font-weight: 400; letter-spacing: .03em; text-transform: lowercase;
}
html[data-skin="airy"] .q-model:hover { color: var(--text); }
html[data-skin="airy"] .q-model.pinned { color: var(--qm); }
html[data-skin="airy"] .q-model .q-model-dot { width: 5px; height: 5px; }

/* Glyph buttons: no boxes at rest, ink on hover. Send is the one filled control. */
html[data-skin="airy"] .q-actions { gap: 2px; }
html[data-skin="airy"] .q-actions button, html[data-skin="airy"] .q-actions button.q-imgflag {
  width: 26px; height: 26px; border-radius: 999px; background: transparent !important;
  border: 0 !important; color: var(--faint);
}
html[data-skin="airy"] .q-actions button:hover { background: var(--hover) !important; color: var(--text); }
html[data-skin="airy"] .q-actions button svg { width: 14px; height: 14px; }
html[data-skin="airy"] .q-actions button.q-send,
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-actions button.q-send {
  background: var(--text) !important; color: var(--on-ink); border: 0 !important;
}
html[data-skin="airy"] .q-actions button.q-send:hover { background: #2c2d30 !important; color: var(--on-ink); }
html[data-skin="airy"] .q-item.paused .q-imgflag { color: var(--accent); }

/* Empty queue: the same quiet centred voice as an empty pane. */
html[data-skin="airy"] .q-empty { color: var(--faint); font-size: 14px; padding: 64px 20px; line-height: 1.7; }

/* Layouts open as tabs (John, 2026-09-20). Two fixes found by rendering it: the dropdown
   button has a display rule that beats [hidden], and the "+" (inside #layoutsCtl) sat left
   of the strip, so the tabs get the earlier order slot. */
html[data-skin="airy"] header #layoutsBtn[hidden] { display: none !important; }
html[data-skin="airy"] header #layoutTabs { order: -3; }
html[data-skin="airy"] header #layoutsCtl { order: -2; }
html[data-skin="airy"] header #layoutTabs { display: flex; align-items: center; gap: 2px; }

/* Right edge aligns to the H of LUMINAIR (John, 2026-09-20). The logo ends 15px from the
   aside edge; heads carried 24px padding and rows 16px margin + 8px padding (25px), so both
   sat 10px short. Heads drop to 14px; rows keep 8px padding on a 7px margin. */
html[data-skin="airy"] .sec-head,
html[data-skin="airy"] .side-branches .sb-head,
html[data-skin="airy"] .folder-subhead,
html[data-skin="airy"] .active-subhead { padding-right: 14px; }
html[data-skin="airy"] .row,
html[data-skin="airy"] .row.folder,
html[data-skin="airy"] .active-row,
html[data-skin="airy"] .side-branches .sb-row { margin-right: 7px; padding-right: 8px; }

/* The fold caret rides the eyebrow text's centre line, not the header box, so it reads level
   in both states (John, 2026-09-20: "the > is too low when open and when closed"). */
/* Pinning the caret to 50% of the HEAD BOX left it 3px below the eyebrow, because the box
   is not symmetric (10px over the text, 8px under it) and the -5px nudge only took back
   2px of that. Measured on John's screenshot: caret centre 3.3px under the title's centre,
   while the pause icon sat level. Overlay the caret on the text's own line box instead —
   top = the head's padding-top, height = the eyebrow's 11px line — so it is centred in
   both the open and the collapsed state, which now share that padding-top. */
/* ONE RULE FOR EVERY CARET (John, 2026-09-22: "they should all follow the same rule ...
   not vertically centered like the text"). Measured on his screenshot, in device px on a
   1.66x crop: the branches caret started at x=9 and the section caret at x=15, while both
   titles started at x=35-36 — the section caret was centred inside its 14px hit box, the
   branches triangle was not, so they sat 3.6 CSS px apart. Both now start at the box's
   left edge, x=6, and the hit box keeps its width.
   Vertically both sat 2-3 device px (~1.5 CSS px) above the title's INK centre, because
   centring on the 11px line box ignores where the cap-height actually falls inside it.
   Each caret's centre is pushed to 17px from the head's top — its padding-top plus half
   the line, plus that 1.5px optical correction — so it lands on the title's ink. */
html[data-skin="airy"] .sec-head .sec-caret { top: 11.5px; bottom: auto; margin-top: 0; height: 11px; justify-content: flex-start; }
/* FOLDERS caret sat 3px ABOVE its own row (John, 2026-09-23: "the arrow on folders is
   the last one not aligned"). Measured on the real header: the caret box centred at
   y=17 while the FOLDERS title AND the + button both centre at y=20. The 17px target
   above was computed as padding-top(10) + half the line(5.5) + 1.5, but the title box
   actually starts at y=14.5, not at the padding edge, so that arithmetic missed by 3px.
   Centre it on what is actually there. Scoped to this header, since it is the one
   measured; the shared rule above is left alone. */
html[data-skin="airy"] #projectsHead .sec-caret { top: 14.5px; }
html[data-skin="airy"] .folder-subhead .sec-caret { top: 11.5px; bottom: auto; margin-top: 0; height: 11px; justify-content: flex-start; }
/* .active-subhead keeps app.css's own 6px padding-top, so its caret centre is 6 + 5.5 + 1.5. */
html[data-skin="airy"] .active-subhead .sec-caret { top: 9.5px; bottom: auto; margin-top: 0; height: 11px; justify-content: flex-start; }
/* Same line-box overlay as .sec-caret above, for the branches head's own caret glyph. */
/* Centre the 7px-tall triangle on the eyebrow line box (10px padding-top + 11px line → centre 15.5px). */
/* Same 17px centre as the section carets above; the triangle is 7px tall, so top = 13.5. */
html[data-skin="airy"] .side-branches .sb-head::before { top: 13.5px; bottom: auto; margin-top: 0; }

/* The unsorted row timestamp carries margin-right:-3px, pushing it 2px past the H. */
html[data-skin="airy"] .row .time { margin-right: 0; }

/* Status dots stay COLOURED (John, 2026-09-20). Killing the orange accent turned them ink,
   because the base falls back to var(--accent). Give each status its own fallback instead,
   and keep var(--dot-c) first so a session that carries a model tint still wins. */
html[data-skin="airy"] .adot { background: var(--dot-c, var(--faint)); }
html[data-skin="airy"] .adot.thinking { background: var(--dot-c, #ff6a44); }
html[data-skin="airy"] .adot.waiting { background: var(--dot-c, #45e3b0); }
html[data-skin="airy"] .adot.idle { background: #45e3b0; }
html[data-skin="airy"] .adot.error { background: #ff2d20; }
html[data-skin="airy"] .factive .fdot { background: var(--dot-c, var(--faint)); opacity: 1; }
html[data-skin="airy"] .factive .fdot.thinking { background: var(--dot-c, #ff6a44); }
html[data-skin="airy"] .factive .fdot.waiting { background: var(--dot-c, #45e3b0); opacity: 1; }
html[data-skin="airy"] .sf-active .fdot { background: var(--dot-c, var(--faint)); }
html[data-skin="airy"] .sf-active .fdot.thinking { background: var(--dot-c, #ff6a44); }
html[data-skin="airy"] .sf-active .fdot.waiting { background: var(--dot-c, #45e3b0); }

/* Unsorted session rows: the hover "⋯" is absolutely placed over the right edge where the
   timestamp lives, so the two collided on hover (John, 2026-09-20: "overlapping icons").
   The timestamp yields on hover, same rule the folder rows already follow. */
html[data-skin="airy"] .row.session .time { transition: opacity .12s; }
html[data-skin="airy"] .row.session:hover .time { opacity: 0; }

/* The working marker on a session row is a DOT, and it sits in the gutter between the
   row's edge and the title (John, 2026-09-23: "the square should be a dot ... bring it
   closer to the title. Right in between."). The base draws it as an 8px rounded SQUARE
   (border-radius 2px, on both the mask and its coloured core) parked at left:-11px,
   outside the row entirely. Round both layers and move it inside: the airy row carries
   padding-left:14px, so left:3px centres the 8px dot at x=7 — half way between the row
   edge and the first letter. It only ever shows while a session is working, and the
   title does not move either way, so nothing shifts when it appears. */
html[data-skin="airy"] .row.session .srun,
html[data-skin="airy"] .row.session .srun::after { border-radius: 50%; }
html[data-skin="airy"] .tree .row.session .srun,
html[data-skin="airy"] .subgroup .row.session .srun { left: 3px; }

/* Pane separator: exactly one hairline, using standard line color to match horizontal lines. */
html[data-skin="airy"] .gutter-row::before { background: var(--line); width: 1px; }
html[data-skin="airy"] .gutter-row:hover::before, html[data-skin="airy"] body.resizing .gutter-row:hover::before { background: rgba(var(--accent-rgb),.5); }
html[data-skin="airy"] .pane, html[data-skin="airy"] .pane.tinted, html[data-skin="airy"] .pane.focused,
html[data-skin="airy"] .col, html[data-skin="airy"] .stack, html[data-skin="airy"] .block {
  border-left: 0 !important; border-right: 0 !important; box-shadow: none !important;
}
html[data-skin="airy"] aside { border-right: 1px solid var(--line); }

html[data-skin="airy"] .pane-composer .q-model-def { width: auto; max-width: none; white-space: nowrap; }
html[data-skin="airy"] .pane-composer .q-model-def-name { max-width: none; overflow: visible; text-overflow: clip; }

/* ---- head + composer model chip: "O | M" (John, 2026-09-20) ------------------------
   Model initial in the model's own vivid colour, a hairline separator, the thinking
   letter. No pulse icon anywhere. The composer's query-level chip repeats it exactly. */
html[data-skin="airy"] .pane-head .pmodesel .peffort svg { display: none; }
html[data-skin="airy"] .pane-head .pmodesel .peffort { gap: 0; border: 0; padding: 2px 5px 2px 0; font-weight: 600; color: var(--muted); }
html[data-skin="airy"] .pane-head .pmodesel .peffort::before { content: "|"; color: var(--line); font-weight: 400; margin: 0 6px 0 2px; }
html[data-skin="airy"] .pane-head .pmodel, html[data-skin="airy"] .pane-head .pmodel.mini {
  width: auto; min-width: 0; height: 19px; border: 0; padding: 0 0 0 4px; font-weight: 700;
}
html[data-skin="airy"] .q-model-def-name .qm-sep { color: var(--line); margin: 0 6px; -webkit-text-fill-color: var(--line); }
html[data-skin="airy"] .q-model-def-name .qm-eff { color: var(--muted); -webkit-text-fill-color: var(--muted); }
/* The initial was too loud at 700 (John, 2026-09-22: "the acronym is a little too
   prominent, make it a lighter color"). Keep the model hue, lighten the weight and
   soften the ink so it sits with the rest of the composer chrome. */
html[data-skin="airy"] .q-model-def-name .qm-ini { -webkit-text-fill-color: currentColor; font-weight: 500; opacity: .72; }

/* Collapse toggle moved INTO the side panel, right of the wordmark (John, 2026-09-22).
   Collapsed, the wordmark (both the full one and the /OW mark) is hidden and only the
   toggle remains, centred in the rail, so the panel can still be reopened.
   Both pinned to the TOP of the row (John, 2026-09-22: "I want the logo at the top,
   along with the collapse button"): .side-top's 30px top padding exists only to clear
   the traffic lights over .win-ctrls, which is already position:absolute in the base
   skin (app.css) and so never needed that padding either — cut it here since airy
   never overrode win-ctrls' own position. */
/* The right anchor is the SESSION TITLE across the divider, not the window controls:
   the sidebar and the pane start at the same y, and the airy pane head puts its title
   box at y=22px (.pane-head padding-top: 22px). The wordmark is 22.2px tall, the
   collapse button 28px, so with align-items:center the row's padding-top must be
   19px for the wordmark's box to start at 22px too ((28 - 22.2) / 2 = 2.9 + 19 ≈ 22).
   Earlier guesses of 10px and 14px both read as "too high" because they sat above the
   session title; 34px-tall bar read as the old cramped UI (John, 2026-09-22). */
/* The wordmark rides at the TOP of the strip, not centred in it (John, 2026-09-22,
   from a side-by-side: the mark sits 15px higher while "Open branches" below it does
   not move at all). So the row keeps its 58px box and only the content moves up: the
   space taken off the top is given back to the bottom, and the items align to the
   start instead of the centre. */
/* The strip's total height must EQUAL the header's, or the hairline under it steps at the
   sidebar/main seam (John, 2026-09-22: "the line should be continuous"). Measured on his
   crop: the sidebar rule sat at row 63, the header's at row 60. The header is 56px tall
   (see `html[data-skin="airy"] header` above) and the tallest thing in this row is the 28px
   collapse button, so the paddings must add up to 28. Change one, change the other. */
/* Sidebar top strip height must match header height (56px) exactly so the bottom border
   aligns 100% continuously across the sidebar/main seam (John, 2026-09-22: "they need to
   feel like one"). Centred vertically so wordmark and collapse button share the 28px centre line. */
html[data-skin="airy"] .side-top { display: flex; align-items: center; gap: 10px; height: 56px; padding: 0 14px; }
html[data-skin="airy"] .side-top .appname { margin-top: 0; position: static; margin-left: auto; }
html[data-skin="airy"] .side-top .collapse-btn {
  -webkit-app-region: no-drag; position: static; flex: 0 0 auto; margin: 0;
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; color: var(--faint); border-radius: 999px;
}
html[data-skin="airy"] .side-top .collapse-btn:hover { color: var(--text); background: var(--hover); }
/* collapsed rail: icon only */
html[data-skin="airy"] body.collapsed .side-top { justify-content: center; padding: 0; gap: 0; }
html[data-skin="airy"] body.collapsed .side-top #appName,
html[data-skin="airy"] body.collapsed .side-top .appname-short { display: none !important; }
html[data-skin="airy"] body.collapsed .side-top .collapse-btn { margin: 0 auto; }

/* Relay LED lives in the empty gutter LEFT of the row, not in the flow (John, 2026-09-22):
   in-flow it pushed the activity dot right, so a relayed row's dot no longer lined up with
   every other row's. Absolute + half size keeps one dot column down the whole list. */
html[data-skin="airy"] .active-row .aconn {
  position: absolute; left: -7px; top: 50%; transform: translateY(-50%);
  width: 9px; height: 14px; margin: 0; z-index: 2;
}
html[data-skin="airy"] .active-row .aconn svg { width: 9px; height: 14px; }


/* ================================================================================
   COMPOSER LAYOUT, SINGLE SOURCE (John, 2026-09-22: "serious issue with the layouts
   on the input area ... audit those elements and do a clean up").
   Every block that used to live above pinned one control into the card with its own
   absolute offsets, each added at a different time, so the controls ended up in two
   different bands (flow toggle and queue count on the top edge, +, model chip and
   buttons on the bottom) and a pane read differently depending on which controls it
   happened to be showing.
   The composer now has one layout, in normal flow, and the DOM order is the visual
   order (the q-bar moved after the input in renderer.js). The card is two rows: the
   prompt chevron and the input on top, and a single action row underneath, reading
   + attach | model chip | flow toggle | queue chips | stop | mic | send.
   The model chip carries the auto margin, so it is also the spacer that pushes the
   right-hand group over and the row keeps its shape whichever controls are present.
   Nothing in the composer is absolutely positioned.
   ================================================================================ */
html[data-skin="airy"] .pane-composer .composer {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px; padding: 10px 12px 10px 14px;
}
/* The prompt chevron is .composer::before, a flex item in its own right. It shares row
   one with the input: the input's basis is the row minus the chevron (7px) and the gap
   (8px), so every control after it wraps onto the action row. */
html[data-skin="airy"] .pane-composer .composer > .ta-wrap { flex: 1 1 calc(100% - 15px); min-width: 0; }
html[data-skin="airy"] .pane-composer .composer textarea { padding-right: 0; }
/* q-bar dissolves so its four controls are items of the action row themselves. */
html[data-skin="airy"] .pane-composer .q-bar { display: contents; }
html[data-skin="airy"] .pane-composer .q-attach,
html[data-skin="airy"] .pane-composer .q-model-def,
html[data-skin="airy"] .pane-composer .q-model-def.pinned,
html[data-skin="airy"] .pane-composer .composer .pstop,
html[data-skin="airy"] .pane-composer .composer .pvoice,
html[data-skin="airy"] .pane-composer .composer .psend {
  margin: 0; align-self: center; flex: 0 0 auto;
}
html[data-skin="airy"] .pane-composer .q-model-def, html[data-skin="airy"] .pane-composer .q-model-def.pinned {
  margin-left: auto; height: auto; padding: 0; width: auto; max-width: none; white-space: nowrap;
  background: transparent !important; border: 0 !important; -webkit-text-fill-color: currentColor;
  /* The model COLOUR must reach this chip: JS sets it inline, so no !important colour here
     (John, 2026-09-22: "you did not fix the color"). Uppercase initial, same as the head. */
  font: 12px var(--airy-mono) !important; letter-spacing: .04em; text-transform: none;
}
html[data-skin="airy"] .pane-composer .q-model-def-name { max-width: none; overflow: visible; text-overflow: clip; }
html[data-skin="airy"] .pane-composer .q-bar-chips { display: flex; align-items: center; gap: 6px; }
/* An empty chips holder would still claim a gap and open a hole in the row. */
html[data-skin="airy"] .pane-composer .q-bar-chips:empty { display: none; }

/* ---------------------------------------------------------------------------
   The composer action row, stated explicitly. Nothing here is positioned: the
   first group clears any leftover absolute offset from an older build, and the
   second fixes the reading order of the row so it does not depend on the order
   the elements happen to sit in the DOM.
   --------------------------------------------------------------------------- */
html[data-skin="airy"] .pane-composer .q-attach,
html[data-skin="airy"] .pane-composer .q-bar-chips,
html[data-skin="airy"] .pane-composer .q-model-def,
html[data-skin="airy"] .pane-composer .q-model-def.pinned,
html[data-skin="airy"] .pane-composer .ph-flow,
html[data-skin="airy"] .pane-composer .composer .pstop,
html[data-skin="airy"] .pane-composer .composer .pvoice,
html[data-skin="airy"] .pane-composer .composer .psend { position: static; inset: auto; }
html[data-skin="airy"] .pane-composer .composer::before { order: 0; }
html[data-skin="airy"] .pane-composer .composer > .ta-wrap { order: 1; }
html[data-skin="airy"] .pane-composer .q-attach { order: 2; }
html[data-skin="airy"] .pane-composer .q-model-def { order: 3; }
html[data-skin="airy"] .pane-composer .ph-flow { order: 4; }
html[data-skin="airy"] .pane-composer .q-bar-chips { order: 5; }
html[data-skin="airy"] .pane-composer .composer .pstop { order: 6; }
html[data-skin="airy"] .pane-composer .composer .pvoice { order: 7; }
html[data-skin="airy"] .pane-composer .composer .psend { order: 8; }

/* The query text sits flush at 0 under airy, so the chevron drawn at left:1px in the
   base skin was touching the first letter. Move it into the left gutter, on the same
   -16px line as the assistant tick, which leaves a 9px gap before the text. */
html[data-skin="airy"] .msg.user::before { left: -16px; }

/* Queue count and the queue-flow toggle move to the TOP RIGHT of the composer card
   (John, 2026-09-22). Both get a negative order so they are laid out before the prompt
   chevron: the input's 100%-wide basis then pushes the chevron and textarea onto the next
   line, which leaves these two alone on the card's first row. The toggle carries the auto
   left margin, so the pair sits flush right whether or not a queue chip is present. */
/* The toggle and the queue chip share the FIRST line with the input, at its right end
   (John, 2026-09-22: "on the same line at the top the toggle and input"). The textarea is
   shortened by the width of that group plus a gap, so the two never touch; everything else
   still wraps onto the action row below.
   Pin both to the top with align-self: flex-start and optical margins so they stay aligned
   with the first line/sentence of text even when the textarea expands vertically
   (John, 2026-09-22: "Wait before make sure the toggle and queue stay at the top aligned
   with the first sentance. Always."). */
html[data-skin="airy"] .pane-composer .composer > .ta-wrap { flex: 1 1 calc(100% - 140px); }
html[data-skin="airy"] .pane-composer .ph-flow {
  order: 2;
  margin: 12px 0 0 auto;
  align-self: flex-start;
  flex: 0 0 auto;
}
html[data-skin="airy"] .pane-composer .q-bar-chips {
  order: 3;
  margin: 9px 0 0 0;
  align-self: flex-start;
  flex: 0 0 auto;
}
/* Zero-height full-width break right after the pair, so the + and the rest of the action
   row cannot creep up into the leftover space on line one. */
html[data-skin="airy"] .pane-composer .composer::after {
  content: ""; order: 4; flex: 0 0 100%; height: 0; margin: 0;
}
html[data-skin="airy"] .pane-composer .q-attach { order: 5; }
/* JOBS SITS BESIDE THE + , NOT ON THE QUERY LINE (John, 2026-09-22). `.q-bar` is
   `display: contents` here, so its children are laid out directly by .composer's order
   list; .q-bar-jobs had no order, defaulted to 0, and landed on line one next to the
   prompt chevron. Same order as the + means source order decides, and the jobs container
   follows the attach button in the DOM. */
html[data-skin="airy"] .pane-composer .q-bar-jobs { order: 5; }
html[data-skin="airy"] .pane-composer .q-model-def { order: 6; }
html[data-skin="airy"] .pane-composer .composer .pstop { order: 7; }
html[data-skin="airy"] .pane-composer .composer .pvoice { order: 8; }
html[data-skin="airy"] .pane-composer .composer .psend { order: 9; }

/* Model and thinking are two separate controls inside the chip (John, 2026-09-22): each
   has its own tooltip and its own picker, so each needs its own hit feedback. */
html[data-skin="airy"] .q-model-def-name .qm-ini,
html[data-skin="airy"] .q-model-def-name .qm-eff,
html[data-skin="airy"] .pane-head .pmodesel .pmodel,
html[data-skin="airy"] .pane-head .pmodesel .peffort { cursor: pointer; border-radius: 4px; padding: 1px 3px; transition: background .12s ease, color .12s ease; }
html[data-skin="airy"] .q-model-def-name .qm-ini:hover,
html[data-skin="airy"] .pane-head .pmodesel .pmodel:hover { background: var(--hover); }
html[data-skin="airy"] .q-model-def-name .qm-eff:hover,
html[data-skin="airy"] .pane-head .pmodesel .peffort:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .q-model-def-name .qm-sep { cursor: default; }

/* The session-level chip in the pane head and the query-level chip in the composer are
   the same control, so they get the same design (John, 2026-09-22). The head carried two
   separators (the .pms-div rule plus the "|" drawn before the thinking letter) and a
   heavier, non-mono face; the composer had one separator in mono. One separator wins. */
html[data-skin="airy"] .pane-head .pms-div { display: none !important; }
html[data-skin="airy"] .pane-head .pmodesel .peffort::before { margin: 0 6px; }
html[data-skin="airy"] .pane-head .pmodesel .pmodel,
html[data-skin="airy"] .pane-head .pmodesel .pmodel.mini,
html[data-skin="airy"] .pane-head .pmodesel .peffort {
  font: 12px var(--airy-mono); letter-spacing: .04em; height: auto;
}
/* Same lightening as the composer initial (John, 2026-09-22): the head acronym read
   too heavy against the quiet title bar. */
html[data-skin="airy"] .pane-head .pmodesel .pmodel,
html[data-skin="airy"] .pane-head .pmodesel .pmodel.mini { font-weight: 500; opacity: .72; padding: 1px 3px; }
/* No left padding: the separator already carries the 6px gap, so an extra 3px here made
   the head chip 8px wider than the composer one. */
html[data-skin="airy"] .pane-head .pmodesel .peffort { font-weight: 400; color: var(--muted); padding: 1px 3px 1px 0; }
html[data-skin="airy"] .pane-head .pmodesel .pmodel:hover,
html[data-skin="airy"] .pane-head .pmodesel .peffort:hover { border-radius: 4px; }

/* Only the title itself is the rename target (John, 2026-09-22). The airy rules stretched
   .ptitle across the whole bar with flex: 1 1 0, so its hover highlight — the rename hit
   area — ran the full width. The title now sizes to its text and the spacer, which airy
   had hidden, takes the slack again so the right-hand group stays put. Padding is paired
   with an equal negative margin, so the text does not move, it just gets room. */
html[data-skin="airy"] .pane-head .ptitle,
html[data-skin="airy"] .pane.focused .pane-head .ptitle {
  flex: 0 1 auto !important;
  padding: 5px 10px; margin: 0 -10px; border-radius: 6px;
}
html[data-skin="airy"] .pane-head .phspacer { display: block; flex: 1 1 auto; }

/* The header's left inset and the Layouts button's own padding stacked up, so the layout
   name sat 34px in from the pane edge (John, 2026-09-22: "remove padding to the left").
   Both are trimmed to 6px, which puts the label 12px in and keeps the hover pill shaped. */
html[data-skin="airy"] header { padding-left: 6px; }
html[data-skin="airy"] header #layoutsCtl .layouts-btn { padding-left: 6px; }

/* ---- Jobs panel (John, 2026-09-22: "redesign the jobs. NOT on brand at all anymore.
   Maybe have them in the same pill separated by a |"). Airy had NO rules for this panel,
   so it still wore the old skin: 9px grey counts, a filled grey .job-kind block, and a
   tinted box on the open job. Brought onto the airy language — mono eyebrows, hairlines
   instead of fills, one pipe-separated pill for the counts. */
html[data-skin="airy"] .jobs-wrap { border-top: 1px solid var(--line); }
html[data-skin="airy"] .jobs-wrap .sec-head { align-items: center; gap: 10px; }
/* The counts are ONE pill: mono, quiet, with the pipe the same weight as the chip's. */
html[data-skin="airy"] .jobs-wrap .sec-head .job-count {
  font: 11px var(--airy-mono); letter-spacing: .06em; color: var(--faint); text-transform: none;
}
html[data-skin="airy"] .jobs-wrap .sec-head .job-count .jc-sep { color: var(--line); margin: 0 6px; }
/* Row eyebrow: a word, not a filled chip. */
html[data-skin="airy"] .job-kind {
  background: transparent; border-radius: 0; padding: 0;
  font: 10px var(--airy-mono); font-weight: 400; letter-spacing: .12em; color: var(--faint);
}
html[data-skin="airy"] .auto-row.job-row { border-radius: 8px; padding: 7px 8px; }
html[data-skin="airy"] .auto-row.job-row:hover { background: var(--hover); }
html[data-skin="airy"] .job-row .auto-name { font: 14px/1.3 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .job-row .auto-sum { font: 11px var(--airy-mono); letter-spacing: .04em; color: var(--faint); }
/* Open job: a hairline and a quiet surface, never the tinted ring. */
html[data-skin="airy"] .job-item { border-radius: 10px; }
html[data-skin="airy"] .job-item.expanded { background: var(--panel-2); box-shadow: none; border: 1px solid var(--line); }
html[data-skin="airy"] .job-item.expanded .job-row .job-caret { color: var(--muted); }
html[data-skin="airy"] .job-dk { font: 11px var(--airy-mono); letter-spacing: .04em; color: var(--faint); }
html[data-skin="airy"] .job-dv { color: var(--text); }
html[data-skin="airy"] .job-dtitle { font: 600 14px/1.35 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .job-dcmd { background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px; color: var(--muted); }
html[data-skin="airy"] .job-dbtn {
  background: transparent; border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); font: 11px var(--airy-mono); letter-spacing: .06em; padding: 4px 12px;
}
html[data-skin="airy"] .job-dbtn:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .job-dbtn.danger:hover { color: #e0554a; border-color: rgba(224,85,74,.5); background: transparent; }

/* ---- dictation bubble (John, 2026-09-22) -----------------------------------------
   The stock bar is a full-bleed rectangle pinned to the pane edges, 30px wider than
   the composer card on each side and with a 3px radius: it reads as a system banner,
   not as part of the airy composer. In airy it becomes a small floating bubble that
   sits just above the card, shares the card's left edge, its white panel, and its
   soft shadow, and is only as wide as its contents. */
html[data-skin="airy"] .voice-status {
  left: 16px; right: 16px; bottom: auto; top: -32px;   /* flush with the composer card, both edges (John, 2026-09-24) */
  gap: 10px; padding: 7px 8px 7px 14px; border-radius: 999px;
  font: 12px/1 var(--ui-font); font-weight: 500; letter-spacing: 0;
  color: var(--muted); background: var(--panel-2);
  border: 1px solid var(--line);
  /* No drop shadow: the bubble sits at the SAME elevation as the composer card, so
     neither one casts onto the other (John, 2026-09-22). The 1px border carries the
     edge instead. */
  box-shadow: none;
}
html[data-skin="airy"] .voice-status.show { display: inline-flex; }
html[data-skin="airy"] .voice-status .vs-dot { width: 6px; height: 6px; background: var(--accent); }
html[data-skin="airy"] .voice-status .vs-wave { flex: 1 1 auto; width: auto; min-width: 84px; height: 16px; color: var(--text); }
html[data-skin="airy"] .voice-status .vs-label { color: var(--muted); }
html[data-skin="airy"] .voice-status .vs-x {
  width: 18px; height: 18px; margin: 0; background: transparent; color: var(--faint);
}
html[data-skin="airy"] .voice-status .vs-x:hover { background: var(--hover); color: var(--text); }

/* ---- Settings > Connectors ---------------------------------------------------
   This page had never been given an airy treatment, so it inherited two things it
   should not have. First, the blanket pill radius on `.modal button` above rounded
   every connector card into a lozenge, because a card IS a <button>. Second, the
   base skin's dark-theme card chrome (a --panel-2 fill inside a 1px --line box)
   reads on warm paper as a grey slab. Cards are hairline-ruled rows here, the
   drawer is the same paper as the sheet, and colour is reserved for real state.
   (John, 2026-09-22: "WHY THAT ROUNDED CARD?! The UI is HORRIBLE.") */
html[data-skin="airy"] .set-modal .integ-grid { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 0 28px; }
html[data-skin="airy"] .set-modal .integ-card {
  background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  padding: 15px 2px 15px 0; gap: 7px; box-shadow: none;
  transition: background .12s, color .12s;
}
html[data-skin="airy"] .set-modal .integ-card:hover { background: transparent; border-color: var(--line); }
html[data-skin="airy"] .set-modal .integ-card:hover .integ-card-name { color: var(--accent); }
html[data-skin="airy"] .set-modal .integ-card:active { transform: none; }
/* Selected: an accent rule on the leading edge, not a filled box. */
html[data-skin="airy"] .set-modal .integ-card.active {
  background: transparent; border-color: var(--line);
  box-shadow: inset 2px 0 0 var(--accent); padding-left: 12px;
}
html[data-skin="airy"] .set-modal .integ-card.active .integ-card-name { color: var(--text); }
html[data-skin="airy"] .set-modal .integ-card-name { font: 500 14.5px var(--ui-font); letter-spacing: 0; }
html[data-skin="airy"] .set-modal .integ-card-sub { font: 12.5px/1.5 var(--ui-font); color: var(--muted); }
html[data-skin="airy"] .set-modal .integ-card-foot { border-top: 0; padding-top: 0; margin-top: 4px; }
html[data-skin="airy"] .set-modal .integ-logo { width: 22px; height: 22px; border-radius: 5px; background: transparent; box-shadow: none; }
/* Type tags become mono eyebrows: no pill, no tinted chip. */
html[data-skin="airy"] .set-modal .integ-tag {
  background: transparent; border-radius: 0; padding: 0; color: var(--faint);
  font: 10px var(--airy-mono); letter-spacing: .12em; font-weight: 400;
}
html[data-skin="airy"] .set-modal .integ-tag-mcp { color: #2a52ad; }
html[data-skin="airy"] .set-modal .integ-tag-api { color: #1c7d5c; }
html[data-skin="airy"] .set-modal .integ-tag-auth { color: #a8542f; }
html[data-skin="airy"] .set-modal .integ-tag-skill { color: #6b3fa0; }
html[data-skin="airy"] .set-modal .integ-tag-local { color: var(--faint); }
html[data-skin="airy"] .set-modal .integ-card .set-status { font: 11.5px var(--ui-font); font-weight: 400; color: var(--faint); }
html[data-skin="airy"] .set-modal .integ-card .set-status.on { color: #1c7d5c; font-weight: 500; }
html[data-skin="airy"] .set-modal .integ-cat { font: 10px/1 var(--airy-mono); letter-spacing: .14em; font-weight: 400; color: var(--faint); margin: 30px 0 6px; }
html[data-skin="airy"] .set-modal .integ-legend { font: 12.5px/1.5 var(--ui-font); color: var(--faint); margin: 10px 0 4px; }

/* The detail drawer is the same sheet of paper, lifted — not a white panel butted
   against the modal with a hard rule and a heavy drop shadow. */
html[data-skin="airy"] .set-modal .integ-drawer {
  background: var(--panel-2); border-left: 0; border-radius: 16px 20px 20px 16px;
  box-shadow: -1px 0 0 var(--line), -30px 0 70px rgba(17,18,20,.10);
  width: 480px;
}
html[data-skin="airy"] .set-modal .integ-drawer-body .integ-detail { padding: 0 28px 28px; }
html[data-skin="airy"] .set-modal .integ-detail-head { padding: 26px 0 6px; }
html[data-skin="airy"] .set-modal .integ-detail-title { font: 400 22px/1.15 var(--airy-serif); letter-spacing: -.01em; }
html[data-skin="airy"] .set-modal .integ-back { font: 12.5px var(--ui-font); color: var(--faint); border-radius: 999px; padding: 5px 10px; }
html[data-skin="airy"] .set-modal .integ-back:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .set-modal .integ-scrim { background: rgba(244,244,245,.62); backdrop-filter: blur(1.5px); }
html[data-skin="airy"] .set-modal .integ-acct { border-radius: 10px; }

/* ---- home view: three starting points + a larger model control ------------------
   John, 2026-09-22: on an empty pane the headline carries the line, the composer
   carries the model, and three short cards teach what is specific to this app. The
   cards sit well below the headline in the same three-column rhythm as the site. */
html[data-skin="airy"] .pane-body .empty .home-starts {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px;
  width: 100%; max-width: 600px; margin: 64px auto 0; text-align: left;
}
html[data-skin="airy"] .pane-body .empty .home-start small {
  display: block; margin-bottom: 8px;
  font: 11px/1 var(--airy-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .pane-body .empty .home-start {
  display: block; width: 100%; padding: 0; border: 0; background: transparent; text-align: left; cursor: pointer;
}
html[data-skin="airy"] .pane-body .empty .home-start.disabled { cursor: default; opacity: .48; pointer-events: none; }
html[data-skin="airy"] .pane-body .empty .home-start:not(.disabled):hover span { color: var(--text); }
html[data-skin="airy"] .pane-body .empty .home-start strong { display: block; margin-bottom: 6px; font: 500 16px/1.3 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .pane-body .empty .home-start span {
  display: block; font: 13px/1.5 var(--ui-font); color: var(--muted); letter-spacing: 0; max-width: 250px;
}

/* ---- sidebar footer (John, 2026-09-22: "that whole bottom section is not on brand") --
   It still wore the dark app's chrome: a bordered avatar, a bordered 3px account slab
   and tight 6px padding. Here it is paper like the rest of the panel: no boxes, one
   hairline above, quiet ink, and hover as the only affordance. */
html[data-skin="airy"] .side-footer { padding: 12px 16px; border-top: 1px solid var(--line); }
html[data-skin="airy"] .side-foot-left { gap: 10px; }
html[data-skin="airy"] .side-foot-right { gap: 4px; }
html[data-skin="airy"] .ow-avatar {
  width: 26px; height: 26px; border: 0; font-size: 12px; font-weight: 500;
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--muted);
}
html[data-skin="airy"] .ow-avatar:hover { background: color-mix(in srgb, var(--text) 14%, transparent); color: var(--text); }
html[data-skin="airy"] .ow-avatar .presence { width: 7px; height: 7px; right: 0; bottom: 0; border-width: 2px; border-color: var(--sidebar); }
/* The account selector reads as a label with a state square, not a slab. */
html[data-skin="airy"] .acct-btn {
  background: transparent; border: 0; border-radius: 999px; height: 28px; padding: 0 10px;
  font: 13px/1 var(--ui-font); color: var(--muted); gap: 8px;
}
html[data-skin="airy"] .acct-btn:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .acct-btn .caret { color: var(--faint); }
html[data-skin="airy"] .acct-dot { width: 6px; height: 6px; border-radius: 50%; }
html[data-skin="airy"] .side-footer .icon-btn { color: var(--faint); border: 0; background: transparent; border-radius: 999px; }
html[data-skin="airy"] .side-footer .icon-btn:hover { color: var(--text); background: var(--hover); }
/* Trial chip: a quiet mono eyebrow, not an orange pill. */
html[data-skin="airy"] .trial-chip {
  background: transparent; border: 1px solid var(--line); border-radius: 999px;
  font: 11px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); padding: 5px 9px;
}
html[data-skin="airy"] .trial-chip:hover { border-color: var(--text); color: var(--text); background: transparent; }

/* ---- open-branch rows (John, 2026-09-22: "this looks not designed") ----------------
   The row was still on the dark app's scale: a 12px name over an 8.5px grey sub-line,
   which reads as an accident next to the 13px session rows. It now matches the Active
   Sessions rhythm exactly: 13px name, mono eyebrow underneath, flat "diff" affordance. */
html[data-skin="airy"] .side-branches .sb-row { padding: 6px 10px; margin: 0 8px 1px; border-radius: 8px; }
html[data-skin="airy"] .side-branches .sb-row:hover { background: var(--hover); }
html[data-skin="airy"] .side-branches .sb-name {
  font: 13px/1.3 var(--ui-font); font-weight: 400; color: var(--text);
}
html[data-skin="airy"] .side-branches .sb-sess {
  font: 10px/1.4 var(--airy-mono); letter-spacing: .06em; color: var(--faint); margin-top: 2px;
}
html[data-skin="airy"] .side-branches .sb-from {
  font: 9.5px/1 var(--airy-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .side-branches .sb-bo-diff {
  background: transparent; border: 0; border-radius: 999px; padding: 4px 9px;
  font: 11px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .side-branches .sb-bo-diff:hover { background: var(--hover); color: var(--text); }

/* ---- one pane-head rule for every pane (John, 2026-09-22: "some titles have a line
   some dont... I want the line at the bottom") --------------------------------------
   An earlier rule set `border-bottom: 0` on .pane .pane-head, so whatever hairline showed
   under some panes was coming from a neighbouring element, not the head itself — which is
   exactly why it appeared on some and not others. The head now always draws its own. */
html[data-skin="airy"] .pane .pane-head,
html[data-skin="airy"] .pane.focused .pane-head,
html[data-skin="airy"] .pane.empty-pane .pane-head { border-bottom: 1px solid var(--line); }

/* Queue chip at zero: present but quiet, so the count is always readable without
   shouting when nothing is waiting (John, 2026-09-22). */
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue.q-empty { color: var(--faint); border-color: var(--line); }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue.q-empty:hover { color: var(--text); background: var(--hover); }

/* NEW SESSION = THE SAME COMPOSER AS EVERY SESSION (John, 2026-09-25: "I want the
   composer to be the same than in active sessions, just with the big title in the
   middle"). The empty pane no longer restyles, hides controls in or floats the
   composer: it stays pinned to the bottom exactly like a running session (see the
   .pane:not(.doc-split) > .pane-composer rule). The pane body only centres the big
   title and, under it, the small folder picker for where the session will live. */
html[data-skin="airy"] .pane-body:has(.airy-home-models) { overflow: hidden; }
html[data-skin="airy"] .pane.empty-pane .pane-body { display: flex; flex-direction: column; }
html[data-skin="airy"] .pane-body .empty.home-empty {
  margin: auto; max-width: 760px; width: 100%; padding: 0 24px; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
}
html[data-skin="airy"] .pane-body .empty.home-empty .home-title {
  margin: 0; color: var(--text); font: 500 clamp(28px, 4.2vw, 40px)/1.15 var(--ui-font) !important; letter-spacing: -.02em;
}
/* The title is real text now; the older CSS-injected lines must not add to it. */
html[data-skin="airy"] .pane-body .empty.home-empty h2.home-title::before,
html[data-skin="airy"] .pane-body .empty.home-empty h2.home-title::after { content: none; }
html[data-skin="airy"] .pane-body .empty.home-empty .home-title em { font: italic 1.1em/1 var(--airy-serif); letter-spacing: 0; }
html[data-skin="airy"] .pane-body .empty.home-empty .home-folder {
  margin-top: 14px; display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 5px 10px; border: 0; border-radius: 999px; background: transparent; cursor: pointer;
  color: var(--muted); font: 12px/1 var(--airy-mono); letter-spacing: .04em;
}
html[data-skin="airy"] .pane-body .empty.home-empty .home-folder:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .pane-body .empty.home-empty .home-folder span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-skin="airy"] .pane-body .empty.home-empty .home-folder svg { flex: 0 0 auto; }
html[data-skin="airy"] .pane-body .empty.home-empty .home-folder .hf-caret { opacity: .6; }
html[data-skin="airy"] .airy-home-models { display: flex; gap: 10px; margin-top: 40px; justify-content: center; }
html[data-skin="airy"] .airy-home-model { border: 1px solid var(--line); border-radius: 999px; padding: 10px 16px; background: transparent; color: var(--muted); font: 13px var(--ui-font); cursor: pointer; }
html[data-skin="airy"] .airy-home-model:hover,
html[data-skin="airy"] .airy-home-model.selected { background: var(--text); border-color: var(--text); color: var(--on-ink); }
html[data-skin="airy"] .pane-body .empty .home-starts { margin-top: 56px; }

/* ---- Master Controller chip: compact (John, 2026-09-22: "takes way too much space
   between the name, toggle and >") -------------------------------------------------
   The stock chip spends 7px gaps around a 30x17 track inside a 9px/5px padded box with
   an 18px caret button. Everything tightens a step: 4px gaps, a 26x15 track, a 14px
   caret, and no bordered slab — airy already reads chips as text. */
html[data-skin="airy"] header .mc-chip { gap: 4px; padding: 2px 4px 2px 7px; border-radius: 999px; border-color: transparent; }
html[data-skin="airy"] header .mc-chip:hover { border-color: transparent; background: var(--hover); }
html[data-skin="airy"] header .mc-chip.on { border-color: transparent; background: transparent; }
html[data-skin="airy"] header .mc-chip .mc-lbl { font: 11px/1 var(--airy-mono); font-weight: 400; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
html[data-skin="airy"] header .mc-chip:hover .mc-lbl, html[data-skin="airy"] header .mc-chip.on .mc-lbl { color: var(--text); }
html[data-skin="airy"] header .mc-chip .mc-switch { padding: 0; }
html[data-skin="airy"] header .mc-chip .mc-track { width: 26px; height: 15px; }
html[data-skin="airy"] header .mc-chip .mc-track::after { width: 11px; height: 11px; top: 2px; left: 2px; }
html[data-skin="airy"] header .mc-chip.on .mc-track::after { transform: translateX(11px); }
html[data-skin="airy"] header .mc-chip .mc-caret { width: 14px; height: 14px; color: var(--faint); }
html[data-skin="airy"] header .mc-chip .mc-caret:hover { color: var(--text); background: transparent; }

/* ---- Master Controller log popover (John, 2026-09-22: "that dropdown is a mess, old
   design, busy, scary") ---------------------------------------------------------------
   Only the popover shell had an airy rule; everything inside still wore the dark app:
   an 800-weight orange uppercase title, a filled "Daily report" slab, 7px saturated
   status dots and 6px rows stacked without air. Here it is paper: a mono eyebrow, text
   buttons, hairline day rules, roomy rows, and status carried by a small quiet mark. */
html[data-skin="airy"] .mc-log-pop { width: 420px; padding: 6px; border-radius: 14px; border: 1px solid var(--line); box-shadow: 0 18px 50px rgba(17,18,20,.14); }
html[data-skin="airy"] .mc-log-head { padding: 12px 14px 10px; margin-bottom: 2px; border-bottom: 1px solid var(--line); }
html[data-skin="airy"] .mc-log-title { font: 11px/1 var(--airy-mono); font-weight: 400; letter-spacing: .14em; color: var(--faint); }
html[data-skin="airy"] .mc-log-report,
html[data-skin="airy"] .mc-log-clear {
  border: 0; background: transparent; border-radius: 999px; padding: 4px 9px;
  font: 11px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .mc-log-report:hover,
html[data-skin="airy"] .mc-log-clear:hover { color: var(--text); background: var(--hover); }
/* Day rule: an eyebrow with a hairline, the same device the sidebar sections use. */
html[data-skin="airy"] .mc-log-daysep {
  padding: 14px 14px 6px; margin-top: 2px; border-top: 1px solid var(--line);
  font: 10px/1 var(--airy-mono); font-weight: 400; letter-spacing: .14em; color: var(--faint);
}
html[data-skin="airy"] .mc-log-daysep:first-child { border-top: 0; margin-top: 0; padding-top: 6px; }
html[data-skin="airy"] .mc-log-row { gap: 10px; padding: 8px 14px; border-radius: 8px; }
html[data-skin="airy"] .mc-log-row:hover { background: var(--hover); }
html[data-skin="airy"] .mc-log-dot { width: 5px; height: 5px; margin-top: 6px; opacity: .85; }
html[data-skin="airy"] .mc-log-text { font: 13px/1.4 var(--ui-font); color: var(--text); font-weight: 400; }
html[data-skin="airy"] .mc-log-row:has(.mc-log-dot.patrol) .mc-log-text,
html[data-skin="airy"] .mc-log-row:has(.mc-log-dot.startup) .mc-log-text { font-weight: 400; color: var(--muted); }
html[data-skin="airy"] .mc-log-meta { font: 11px/1.5 var(--ui-font); color: var(--faint); margin-top: 2px; }
html[data-skin="airy"] .mc-log-time { font: 10.5px/1 var(--airy-mono); color: var(--faint); }
html[data-skin="airy"] .mc-log-caret { color: var(--faint); }
html[data-skin="airy"] .mc-log-empty { padding: 28px 18px; font: 13px/1.6 var(--ui-font); color: var(--muted); }

/* ---- jobs + branching chips in the composer bar (John, 2026-09-22: "this is not on
   brand at all") ---------------------------------------------------------------------
   Only .q-queue had an airy rule, so the jobs chip still wore the dark app: a tinted
   slab in --bo with a filled gold count circle (app.css .q-chip.q-bg .q-n). They now
   match the queue chip exactly: hairline pill, transparent fill, mono count, quiet dot. */
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-bg,
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-branching {
  height: 22px; min-width: 22px; padding: 0 7px; gap: 5px; border-radius: 999px;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
}
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-bg:hover,
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-branching:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-bg .q-n,
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip .q-n-fathom {
  background: transparent; color: inherit; min-width: 0; height: auto; padding: 0;
  border-radius: 0; box-shadow: none; font: 12px var(--airy-mono); font-weight: 400;
}
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip .q-word {
  font: 11px var(--airy-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip .q-caret { color: var(--faint); font-size: 12px; opacity: 1; }
/* Status dots stay the only colour, at the sidebar's 5px scale. */
html[data-skin="airy"] .pane-composer .q-bar-chips .q-bg-dot,
html[data-skin="airy"] .pane-composer .q-bar-chips .q-branching-dot { width: 5px; height: 5px; box-shadow: none; }

/* ---- in-pane doc split (John, 2026-09-22) -------------------------------------------
   "Click DOC on the session title and it opens the doc, only the doc, in split view
   inside the session itself. Session on the right, doc on the left, the title bar still
   at the top of both, the input block only on the session split."

   The pane is normally a flex column (head / body / composer). With .doc-split it becomes
   a 3-row grid so the doc column runs the FULL height of the pane beside the transcript
   and the composer. The mockup John approved (2026-09-22) puts the session title inside
   the right column, level with the doc's eyebrow row, with no bar across the top: the
   only rule between the two halves is the vertical hairline on .pane-doc. */
html[data-skin="airy"] .pane.doc-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
}
html[data-skin="airy"] .pane.doc-split > .pane-head { grid-area: 1 / 1 / 2 / 3; }
html[data-skin="airy"] .pane.doc-split > .pane-doc { grid-area: 2 / 2 / 4 / 3; min-height: 0; }
html[data-skin="airy"] .pane.doc-split > .pane-body { grid-area: 2 / 1 / 3 / 2; min-height: 0; }
html[data-skin="airy"] .pane.doc-split > .pane-composer { grid-area: 3 / 1 / 4 / 2; }
/* Anything else in the pane (cards, drop hints, the queue drawer) stays on the session
   side so the doc column is only ever the doc. */
html[data-skin="airy"] .pane.doc-split > .ctx-pop,
html[data-skin="airy"] .pane.doc-split > .deploy-card,
html[data-skin="airy"] .pane.doc-split > .pane-queue,
html[data-skin="airy"] .pane.doc-split > .jump-latest,
html[data-skin="airy"] .pane.doc-split > .drop-ind { grid-column: 1 / 2; }
/* The END line has to be explicit (John, 2026-09-23: "the queue should open inside the
   session view. Not the doc view"). `grid-column: 1` leaves the end line `auto`, and for
   an ABSOLUTELY POSITIONED grid child auto resolves to the grid container's padding edge,
   not to the next column line — so the area ran from column 1 all the way across the doc
   column. Every overlay here is abspos, so they all needed the closing line. */

html[data-skin="airy"] .pane-doc {
  display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden;
  border-left: 1px solid var(--line);
  /* The doc column sits on the SAME surface as the session title bar above it
     (var(--panel-2)), so the two read as one sheet rather than two (John,
     2026-09-23). Follows the mode automatically in Light and Dark. */
  background: var(--panel-2);
}
html[data-skin="airy"] .pane-doc[hidden] { display: none; }
html[data-skin="airy"] .pane-doc-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 14px; padding: 26px 22px 0 56px;
  font: 11px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
html[data-skin="airy"] .pane-doc-head .pd-sess,
html[data-skin="airy"] .pane-doc-head .pd-edited { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-skin="airy"] .pane-doc-head .pd-open { margin-left: auto; }
html[data-skin="airy"] .pane-doc-head .pd-open,
html[data-skin="airy"] .pane-doc-head .pd-x {
  flex: 0 0 auto; border: 0; background: transparent; border-radius: 999px;
  font: 11px/1 var(--airy-mono); letter-spacing: .1em; color: var(--faint); cursor: pointer;
}
html[data-skin="airy"] .pane-doc-head .pd-open { padding: 4px 8px; }
html[data-skin="airy"] .pane-doc-head .pd-x {
  width: 28px; height: 28px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px;
}
html[data-skin="airy"] .pane-doc-head .pd-open:hover,
html[data-skin="airy"] .pane-doc-head .pd-x:hover { color: var(--text); background: var(--hover); }
/* The doc reads as a page: one measure, generous leading, serif emphasis intact. */
html[data-skin="airy"] .pane-doc-body {
  flex: 0 0 auto; min-height: auto; overflow: visible;
  padding: 6px 56px 64px; max-width: 620px;
  font: 15px/1.65 var(--ui-font); color: var(--text);
}
html[data-skin="airy"] .pane-doc-body h1 { font: 500 34px/1.15 var(--ui-font); letter-spacing: -.03em; margin: 8px 0 18px; }
html[data-skin="airy"] .pane-doc-body h2 { font: 500 22px/1.2 var(--ui-font); letter-spacing: -.02em; margin: 28px 0 10px; }
html[data-skin="airy"] .pane-doc-body h3 { font: 500 17px/1.3 var(--ui-font); margin: 22px 0 8px; }
html[data-skin="airy"] .pane-doc-body p { margin: 0 0 16px; }
html[data-skin="airy"] .pane-doc-body a { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
html[data-skin="airy"] .pane-doc-body code { font: 13px var(--airy-mono); background: var(--hover); padding: 1px 5px; border-radius: 4px; }
html[data-skin="airy"] .pane-doc-body pre { background: var(--hover); border-radius: 10px; padding: 14px 16px; overflow-x: auto; }
html[data-skin="airy"] .pane-doc-body pre code { background: transparent; padding: 0; }
html[data-skin="airy"] .pane-doc-body blockquote { margin: 0 0 16px; padding-left: 16px; border-left: 2px solid var(--line); color: var(--muted); }
html[data-skin="airy"] .pd-empty { color: var(--faint); font: 14px/1.6 var(--ui-font); padding: 12px 0; }
/* DOC in the title bar reads as pressed while the split is open. */
html[data-skin="airy"] .pane-head .pscrap.on::after { color: var(--text); }

/* Quick Ask burner empty state: one line, centred, nothing else (John, 2026-09-22). */
html[data-skin="airy"] .quick-empty {
  display: flex; align-items: center; justify-content: center; height: 100%;
  font: 500 28px/1.2 var(--ui-font); letter-spacing: -.02em; color: var(--text);
}

/* ---- count chips: one shape for jobs and queue (John, 2026-09-22) -------------------
   "I need the jobs to appear next to the + instead. Remove the circle around it and put
   it inside a pill just like the queue. But for both. I need the pill to be just a circle
   if there is only one number."
   .q-bar-jobs is the jobs chip's new home, directly after the + attach button; the queue
   chip stays on the right in .q-bar-chips. Both draw the identical hairline pill, and
   .q-one (set by renderQBarChips whenever the count is a single digit) squares the box so
   the pill reads as a circle. */
html[data-skin="airy"] .pane-composer .q-bar-jobs { display: flex; align-items: center; flex: 0 0 auto; }
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg,
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue {
  height: 22px; min-width: 22px; padding: 0 7px; gap: 3px;
  border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center;
}
html[data-skin="airy"] .pane-composer .q-chip.q-one { width: 22px; padding: 0; }
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg .q-n {
  background: transparent; color: inherit; min-width: 0; height: auto; padding: 0;
  font: 12px var(--airy-mono); box-shadow: none; border: 0;
}
/* Something actually running reads as ink, not as a gold badge. */
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg.q-bg-run { color: var(--text); border-color: var(--text); }

/* Every status word ends on ONE right edge (John, 2026-09-22: "align all of them to the
   right"). A top-level session row is inset by margin 8px + padding 10px; a job sub-row
   came from the base skin with margin 0 and padding-right 9px, so its label stopped 9px
   short of the column the session rows use. Same right inset on both, and the label gets
   an explicit right alignment so a shorter word still ends at that edge. */
html[data-skin="airy"] .active-row.sub { margin: 0 8px 1px; padding-right: 10px; }
html[data-skin="airy"] .active-row .astatus, html[data-skin="airy"] .active-row.sub .astatus { margin-left: auto; text-align: right; }

/* ---- the in-pane doc as a PRINTED PAGE (John, 2026-09-22) ---------------------------
   "for the doc, we're FAR from this Airy, Print style page. It's still very messy."
   The reference is a page, not a panel: a quiet mono eyebrow high on the sheet, a large
   title, one narrow measure of text, and nothing else competing. Three things were wrong
   — the eyebrow sat too close to the top, the column filled whatever width the pane had,
   and the controls read as loudly as the content. */
html[data-skin="airy"] .pane-doc-head { padding: 30px 30px 0 48px; gap: 16px; font-size: 10px; letter-spacing: .16em; }
html[data-skin="airy"] .pane-doc-head .pd-open,
html[data-skin="airy"] .pane-doc-head .pd-x { font-size: 10px; opacity: .55; }
html[data-skin="airy"] .pane-doc-head .pd-open:hover,
html[data-skin="airy"] .pane-doc-head .pd-x:hover { opacity: 1; }
html[data-skin="airy"] .pane-head.compact .pmodesel .peffort { display: inline-flex; }
html[data-skin="airy"] .pane-head .pmodesel:has(.peffort[style*="display: none"]) .pms-div { display: none !important; }
html[data-skin="airy"] .pane-doc-body {
  padding: 0 48px 72px; max-width: 620px;
  font: 15px/1.7 var(--ui-font);
}
/* The page title leads, in the same scale as the Journal's own doc view. */
html[data-skin="airy"] .pane-doc-body .pd-title {
  font: 500 34px/1.15 var(--ui-font); letter-spacing: -.03em; color: var(--text);
  margin: 18px 0 22px;
}
/* Emphasis is the serif italic of the brand, which is what gives the reference page its
   voice; headings inside the body step down from the title instead of competing with it. */
html[data-skin="airy"] .pane-doc-body em { font-family: var(--airy-serif); font-style: italic; font-size: 1.08em; }
html[data-skin="airy"] .pane-doc-body h1 { font: 500 24px/1.2 var(--ui-font); letter-spacing: -.02em; margin: 34px 0 12px; }
html[data-skin="airy"] .pane-doc-body h2 { font: 500 19px/1.25 var(--ui-font); letter-spacing: -.01em; margin: 30px 0 10px; }
html[data-skin="airy"] .pane-doc-body h3 {
  font: 10px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  margin: 26px 0 10px;
}
html[data-skin="airy"] .pane-doc-body p { margin: 0 0 18px; }
html[data-skin="airy"] .pane-doc-body ul, html[data-skin="airy"] .pane-doc-body ol { margin: 0 0 18px; padding-left: 20px; }
html[data-skin="airy"] .pane-doc-body li { margin: 0 0 6px; }
html[data-skin="airy"] .pane-doc-body hr { border: 0; border-top: 1px solid var(--line); margin: 28px 0; }

/* The query starts closer to the chevron (John, 2026-09-22: "The query can start a little
   closer to the > here"). The composer's 8px flex gap set that distance; pulling the input
   back 4px leaves a 4px gutter after the 7px chevron without touching the spacing of the
   action row below, which shares the same gap. */
html[data-skin="airy"] .pane-composer .composer > .ta-wrap { margin-left: -4px; }

/* A session's colour is a BAR along the BOTTOM edge of its title bar (John, 2026-09-24
   evening: "changed my mind. That color line on session, bottom of the title bar instead";
   it sat on the top edge earlier that day, and was a strip down the left edge since
   2026-09-23). The airy skin deliberately kills the old colour wash on the head, so
   paper stays paper and the tint lives on this one edge. --pane-tint-solid is already set
   by applyPaneTint whenever a colour is chosen, and .tinted is only present while one is. */
html[data-skin="airy"] .pane.tinted .pane-head { position: relative; }
html[data-skin="airy"] .pane.tinted .pane-head::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--pane-tint-solid); border-radius: 0;
}

/* ---- model + thinking are ONE pill (John, 2026-09-23) ------------------------------
   "put the model inside a pill including both." The head carried the model letter and the
   thinking letter as two bare controls with a separator between them; now the pair sits
   inside a single hairline pill, matching the composer's own model chip. Each half keeps
   its own hover target and its own picker. */
html[data-skin="airy"] .pane-head .pmodesel {
  display: inline-flex; align-items: center; gap: 0;
  border: 0 !important; border-radius: 0; padding: 0; background: transparent !important;
}
html[data-skin="airy"] .pane-head .pmodesel:hover { background: transparent; }
html[data-skin="airy"] .pane-head .pmodesel .pmodel,
html[data-skin="airy"] .pane-head .pmodesel .pmodel.mini {
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Jobs chip carries a blinking dot left of the count (John, 2026-09-23: "make the jobs
   with a black dot blinking inside to the left of the #"). Ink, not gold — the airy chip
   is a hairline pill, and the dot is the only moving thing in it. The pill drops its
   one-digit circle shape here because a dot plus a digit is no longer a circle's worth of
   content; the QUEUE chip keeps its circle. */
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg,
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg.q-one {
  width: auto; padding: 0 8px; gap: 5px;
}
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg .q-bg-dot {
  display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--text); box-shadow: none;
}
html[data-skin="airy"] .pane-composer .q-bar-jobs .q-chip.q-bg-run .q-bg-dot {
  animation: micpulse 1.15s ease-in-out infinite;
}

/* ---- Scheduled Jobs & Recurring Tasks (Airy skin) ---- */
html[data-skin="airy"] .sched-sec { border-top-color: var(--line); }
html[data-skin="airy"] .sched-add-btn { background: transparent; border-color: var(--line); color: var(--text); }
html[data-skin="airy"] .sched-add-btn:hover { background: var(--hover); }
html[data-skin="airy"] .sched-input,
html[data-skin="airy"] .sched-select,
html[data-skin="airy"] .sched-textarea { background: var(--panel-2); border-color: var(--line); color: var(--text); }
html[data-skin="airy"] .sched-input:focus,
html[data-skin="airy"] .sched-select:focus,
html[data-skin="airy"] .sched-textarea:focus { border-color: var(--text); }
html[data-skin="airy"] .sched-btn-save { background: var(--text); color: var(--on-ink); border: 0; }
html[data-skin="airy"] .sched-btn-cancel { border-color: var(--line); color: var(--text); }
html[data-skin="airy"] .sched-btn-cancel:hover { background: var(--hover); }
html[data-skin="airy"] .sched-modal h3 { font: 400 22px/1.2 var(--airy-serif); letter-spacing: -.01em; color: var(--text); }


/* Quick Ask header buttons: the same pill language as the rest of the airy chrome.
   They were still wearing the base skin's boxy 6px chips with an accent wash, which
   on paper read as grey slabs next to the round controls above them.
   (John, 2026-09-23: "Fix the buttons to look like the new UI at the top.") */
html[data-skin="airy"] .quick-ask-head { padding: 18px 20px 14px; border-bottom: 1px solid var(--line); gap: 10px; }
html[data-skin="airy"] .quick-ask-head .qa-title { font: 500 15px var(--ui-font); letter-spacing: 0; }
html[data-skin="airy"] .quick-ask-head .qa-sub { font: 12.5px var(--ui-font); color: var(--faint); }
html[data-skin="airy"] .quick-ask-head .qa-convert {
  height: 30px; padding: 0 16px; border: 0; border-radius: 999px;
  background: var(--text); color: var(--on-ink); font: 500 12.5px var(--ui-font); box-shadow: none;
}
html[data-skin="airy"] .quick-ask-head .qa-convert:hover { background: var(--text); }
html[data-skin="airy"] .quick-ask-head .qa-erase {
  height: 30px; padding: 0 14px; border: 1px solid var(--line); border-radius: 999px;
  background: transparent; color: var(--muted); font: 500 12.5px var(--ui-font);
}
html[data-skin="airy"] .quick-ask-head .qa-erase:hover { color: var(--text); background: var(--hover); border-color: var(--line); }
html[data-skin="airy"] .quick-ask-head .qa-close {
  width: 30px; height: 30px; border: 0; border-radius: 999px;
  background: transparent; color: var(--faint);
}
html[data-skin="airy"] .quick-ask-head .qa-close:hover { color: var(--text); background: var(--hover); }

/* The separator is NOT a control (John, 2026-09-23: "What the hover on the | ??"). It was
   drawn as .peffort::before, so it sat inside the thinking button: hovering the bar lit
   that button's background and popped its "Thinking: …" tooltip. Give the pipe back to
   .pms-div, the inert span that already exists between the two halves, and drop it from
   the button. Hover targets are now exactly the model name and the thinking word. */
html[data-skin="airy"] .pane-head .pmodesel .peffort::before { content: none; margin: 0; }
html[data-skin="airy"] .pane-head .pms-div {
  display: inline-block !important; width: auto; height: auto; background: none;
  color: var(--line); font: inherit; pointer-events: none; margin: 0 6px;
}
html[data-skin="airy"] .pane-head .pms-div::before { content: "|"; }

/* The folder acronym on a session title sat at the base skin's .5 opacity, which on
   warm paper reads almost as dark as the name it prefixes. Lighter still, and unbolded,
   so the name is the thing the eye lands on.
   (John, 2026-09-23: "I think we can make the acronym a tiny bit lighter.") */
html[data-skin="airy"] .title-acr { opacity: .38; font-weight: 400; }

/* The caret triangle has to be centred in its own box, not merely flex-centred.
   Measured on a 2x render of the real headers: the Open Branches triangle (drawn
   straight on the head) landed on the title's optical centre, while the section
   carets sat 5.25px high, because the .sec-caret box is rotated 90 degrees and any
   residual offset of the ::before inside it becomes a vertical one. Pinning the
   triangle to the box's centre makes the rotation move nothing.
   (John, 2026-09-23: "active session and folder is completely a mess.") */
html[data-skin="airy"] .sec-head .sec-caret::before,
html[data-skin="airy"] .active-subhead .sec-caret::before,
html[data-skin="airy"] .folder-subhead .sec-caret::before {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
}

/* In the unified model+thinking pill, keep the effort initial visible in compact mode,
   and hide the pipe separator whenever the engine has no thinking controls (John, 2026-09-23). */
html[data-skin="airy"] .pane-head.compact .pmodesel .peffort { display: inline-flex; }
html[data-skin="airy"] .pane-head .pmodesel:has(.peffort[style*="display: none"]) .pms-div { display: none !important; }


/* Commit lives in the Open branches action cluster next to diff. It stays ink where
   diff is faint, because on a worktree row with uncommitted work it is the only action
   that leads anywhere: merge is hidden until something is committed.
   (John, 2026-09-23: "then I need a commit button if not merge.")
   It matches diff's size exactly — the pill it started as dwarfed the row and squeezed
   the branch name into an ellipsis (John, 2026-09-23: "these buttons are way too big").
   Ink instead of faint is the only thing that separates it from diff. */
html[data-skin="airy"] .side-branches .sb-bo-commit {
  background: transparent; border: 0; border-radius: 999px; padding: 4px 9px;
  font: 11px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--text);
}
html[data-skin="airy"] .side-branches .sb-bo-commit:hover { background: var(--hover); color: var(--text); }

/* ---- global grain -----------------------------------------------------------------
   A single fixed film-grain layer over the whole window. Drawn from an inline SVG
   feTurbulence (fractalNoise), so it costs no asset and no repaint work: it is one
   static tile the compositor reuses. pointer-events:none keeps every click passing
   straight through, and it sits above the UI but below nothing it needs to block.
   Kept very low so it reads as paper texture, never as dirt on the screen.
   (John, 2026-09-23: "a global grain that looks really good can we try that?") */
html[data-skin="airy"] body::after {
  content: ""; position: fixed; inset: 0; z-index: 2147483000;
  pointer-events: none; opacity: .30; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='.42'/></svg>");
  background-size: 160px 160px;
}
/* multiply only ever darkens, so on the dark mode's #111214 page the grain would be
   mathematically present and visually absent. Screen lightens instead, which is the
   same texture read the other way up; the opacity drops because light grain on a dark
   field reads much louder than dark grain on paper. */
html[data-skin="airy"] body[data-theme="dark"]::after {
  mix-blend-mode: screen; opacity: .14;
}


/* ============================================================================
   BRANCH-OUT CARD — rebuilt in the skin's own language (John, 2026-09-23:
   "branchout card needs a complete redesign").

   The card was still written for the old dark app and never translated, which is
   why it reads as a different product sitting inside this one. Measured against
   app.css, not guessed: .bo-sub-name is hardcoded #e6e6e6 (a near-white, on paper),
   .bo-sub-req is an uppercase 800-weight badge with a tinted fill AND a border,
   .bo-sub-model, .bo-vbadge and .bo-rbadge are three more bordered chips, every
   surface is a 3px rounded box, and the type runs across eight sizes from 9.5px
   to 12.5px.

   The rules applied here are this file's own, from its header: warm paper,
   hairlines instead of boxes, ONE accent used only for "running", mono eyebrows
   for labels and counts, real air. Nothing below changes behaviour or markup —
   deleting this whole block restores the previous look exactly.
   ============================================================================ */

/* The card is paper with a hairline, not a floating dark panel. */
html[data-skin="airy"] .q-bo {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: none; padding: 18px 18px 16px;
}

/* Controller row: a mono eyebrow over its state line, hairline beneath. */
html[data-skin="airy"] .bo-super { gap: 10px; padding-bottom: 14px; border-bottom: none; }
html[data-skin="airy"] .bo-super-title {
  font: 11px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase;
  font-weight: 400; color: var(--faint);
}
html[data-skin="airy"] .bo-super-sub { font: 13.5px/1.4 var(--ui-font); color: var(--text); margin-top: 5px; }

/* The fan-out is the headline of this card, so it gets real numerals and air —
   and no box around it. */
html[data-skin="airy"] .bo-hero {
  background: transparent; border: 0; border-radius: 0; padding: 20px 0 18px; gap: 20px;
}
html[data-skin="airy"] .bo-hero-n {
  font: 500 34px/1 var(--ui-font); letter-spacing: -.03em; color: var(--text);
}
html[data-skin="airy"] .bo-hero-lab {
  font: 11px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase;
  font-weight: 400; color: var(--faint); margin-top: 8px;
}
html[data-skin="airy"] .bo-hero-x { font: 300 18px/1 var(--ui-font); color: var(--line); opacity: 1; }

/* Spend: a hairline rule, not a filled meter. */
html[data-skin="airy"] .bo-spend { margin: 0 0 14px; }
html[data-skin="airy"] .bo-spend-top {
  font: 11px/1 var(--airy-mono); letter-spacing: .1em; font-weight: 400; color: var(--faint);
}
html[data-skin="airy"] .bo-spend-bar { height: 1px; border-radius: 0; background: var(--line); margin-top: 8px; }
html[data-skin="airy"] .bo-spend-fill { border-radius: 0; background: var(--text); }
html[data-skin="airy"] .bo-spend-note { font: 12px/1.4 var(--ui-font); font-weight: 400; color: #b3261e; margin-top: 6px; }

/* Disclosure reads as a quiet mono line, like every other eyebrow in the skin. */
html[data-skin="airy"] .bo-listtog {
  font: 11px/1 var(--airy-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); padding: 10px 0; gap: 7px;
}
html[data-skin="airy"] .bo-listtog:hover { color: var(--text); background: transparent; }

/* Agent rows: hairline-separated, never filled pills. */
html[data-skin="airy"] .bo-subs { gap: 0; margin-top: 2px; }
html[data-skin="airy"] .bo-sub { padding: 12px 0; border-radius: 0; background: transparent !important; gap: 10px; }
html[data-skin="airy"] .bo-sub + .bo-sub { border-top: 1px solid var(--line); }
html[data-skin="airy"] .bo-sub:hover { background: transparent !important; }
/* #e6e6e6 was invisible on paper and wrong in dark; one ink token serves both. */
html[data-skin="airy"] .bo-sub-name { font: 500 14px/1.35 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .bo-sub-desc { font: 12.5px/1.5 var(--ui-font); color: var(--muted); margin-top: 4px; }
html[data-skin="airy"] .bo-sub-live { font: 12px/1.45 var(--airy-mono); color: var(--muted); margin-top: 5px; }

/* Every badge becomes a mono count or label: no fill, no border, no shouting. */
html[data-skin="airy"] .bo-sub-req,
html[data-skin="airy"] .bo-sub-model,
html[data-skin="airy"] .bo-vbadge,
html[data-skin="airy"] .bo-rbadge {
  background: transparent !important; border: 0 !important; border-radius: 0; padding: 0;
  font: 11px/1 var(--airy-mono); letter-spacing: .1em; font-weight: 400; text-transform: none;
}
html[data-skin="airy"] .bo-sub-req { color: var(--faint); }
html[data-skin="airy"] .bo-sub-model { color: var(--m-col, var(--faint)); }
html[data-skin="airy"] .bo-vbadge { color: var(--faint); text-transform: uppercase; }
html[data-skin="airy"] .bo-rbadge { color: #b3261e; text-transform: uppercase; }

/* Actions: the skin's text-and-hairline buttons, not accent-filled boxes. */
html[data-skin="airy"] .bo-retry,
html[data-skin="airy"] .bo-cancel,
html[data-skin="airy"] .q-bo-dismiss {
  background: transparent; border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); font: 12.5px var(--ui-font); font-weight: 400; padding: 5px 13px;
}
html[data-skin="airy"] .bo-retry:hover,
html[data-skin="airy"] .bo-cancel:hover,
html[data-skin="airy"] .q-bo-dismiss:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .q-bo-test {
  background: var(--text); border: 0; border-radius: 999px; color: var(--on-ink);
  font: 500 12.5px var(--ui-font); padding: 6px 15px;
}

/* Head / status lines share the body type instead of inventing their own. */
html[data-skin="airy"] .q-bo-head { font: 500 14px/1.35 var(--ui-font); color: var(--text); gap: 8px; }
html[data-skin="airy"] .q-bo-sub { font: 12.5px/1.5 var(--ui-font); color: var(--muted); margin-top: 6px; }
html[data-skin="airy"] .bo-test-status { font: 12.5px/1.5 var(--ui-font); color: var(--muted); margin-top: 10px; }
html[data-skin="airy"] .q-bo-branch {
  font: 12px var(--airy-mono); background: transparent; border: 0;
  border-left: 2px solid var(--line); border-radius: 0; padding: 2px 0 2px 10px; color: var(--muted);
}


/* ============================================================================
   ACCENT: BUTTONS AND CURSOR ONLY (John, 2026-09-23: "only keep the accent color
   which will only affect the buttons and cursor").

   This skin deliberately paints the whole UI in ink and reserves colour for meaning,
   so it overrides --accent to var(--text) app-wide. That left the accent picker with
   nothing to colour. --accent-live carries the CHOSEN accent separately, and only two
   things read it: the send button and the text cursor. Everything else stays ink, so
   picking an accent can never retint the app the way the removed presets did.
   Values mirror the swatches in the picker exactly (index.html #accentSeg). */
/* Default: NO TINT. The fill is the skin ink and the glyph is the page behind it, so
   the send button, toggles and caret are simply monochrome — black on paper in Light,
   white on charcoal in Dark.

   This was briefly hardcoded to #ff6a44 on the theory that a theme token was what made
   Default "turn the whole app light" (John, 2026-09-23). That was the wrong diagnosis:
   the real cause was the dark palette losing a specificity tie whenever data-accent was
   absent, fixed at the top of this file. Orange was also just a duplicate of the first
   swatch, which made the pill read as a tenth colour instead of "none". */
html[data-skin="airy"] body { --accent-live: var(--text); --on-accent-live: var(--bg); }
html[data-skin="airy"] body[data-accent="orange"]    { --accent-live: #ff6a44; --on-accent-live: #111214; }
html[data-skin="airy"] body[data-accent="blue"]      { --accent-live: #5b8def; --on-accent-live: #111214; }
html[data-skin="airy"] body[data-accent="purple"]    { --accent-live: #7725ff; --on-accent-live: #ffffff; }
html[data-skin="airy"] body[data-accent="red"]       { --accent-live: #e5484d; --on-accent-live: #111214; }
html[data-skin="airy"] body[data-accent="pink"]      { --accent-live: #ff1493; --on-accent-live: #111214; }
html[data-skin="airy"] body[data-accent="neon"]      { --accent-live: #c6ff00; --on-accent-live: #111214; }
html[data-skin="airy"] body[data-accent="neongreen"] { --accent-live: #39ff14; --on-accent-live: #111214; }
html[data-skin="airy"] body[data-accent="gray"]      { --accent-live: #86868b; --on-accent-live: #111214; }
/* --on-accent-live is DERIVED, not chosen: each glyph colour is whichever of white or
   the logo ink scores higher WCAG contrast against that fill. White wins only on
   purple (6.01 vs 3.12); ink wins everywhere else, by 15.80 on neon and 13.82 on
   neongreen — which is why a hardcoded white icon vanished on the bright ones
   (John, 2026-09-23: "make sure that bright color have the icon visible"). It was
   also failing AA on orange at 2.84, under the 3:1 floor for an icon. These are
   literals, not tokens, because the fill does not change between Light and Dark. */
/* THE BUTTON. The send control is the one filled button in the composer. */
html[data-skin="airy"] .psend { background: var(--accent-live); color: var(--on-accent-live); }
/* STOP IS AN OUTLINE, NOT A FILL (John, 2026-09-23: "make the stop an outline").
   It shares the base rule with .psend, so it inherited the same solid ink circle and
   read as a second primary action sitting beside the mic. A hairline ring with an ink
   glyph keeps it findable while saying "halt", not "go". Size and shape are untouched. */
html[data-skin="airy"] .pstop {
  background: transparent; border: 1px solid var(--line); color: var(--text);
}
html[data-skin="airy"] .pstop:hover { border-color: var(--text); background: var(--hover); }

/* THE CURSOR. Both the native caret and the skin's own drawn caret. */
html[data-skin="airy"] .composer textarea,
html[data-skin="airy"] .pane-composer textarea { caret-color: var(--accent-live); }
/* THE CURSOR TAKES THE ACCENT TOO (John, 2026-09-23: "cursor as well"). The block caret
   is drawn from var(--accent), which this skin had already rewritten to ink, so it never
   showed the chosen colour. It is REVERSE VIDEO — JS draws the glyph inside the block —
   so the glyph colour has to come from --on-accent-live, or it vanishes on neon and
   neongreen exactly like the mic icon did. The caret-solid state (held while typing) is
   specificity (0,4,0) in the base sheet and was outranking a plain .ta-caret rule, so it
   is overridden by name rather than by hope. The dim mirror caret keeps its own opacity. */
/* CRT BLOCK WITH A BLOOM, ported from mobile (John, 2026-09-23: "I love the glow on the
   cursor can you bring that to desktop"). Same recipe as the phone: fine horizontal
   scanlines cut through the accent fill plus a 6px halo in the same colour. The
   scanlines are a background-image, so the blink below has to clear them on the
   off beat or they would print over the page colour. */
html[data-skin="airy"] .composer .ta-caret {
  background: var(--accent-live);
  box-shadow: 0 0 6px var(--accent-live);
  color: var(--on-accent-live);
}
html[data-skin="airy"] .composer .ta-wrap.caret-solid .ta-caret {
  background-image: none;
  background-color: var(--accent-live);
  box-shadow: 0 0 6px var(--accent-live);
  color: var(--on-accent-live);
}
/* Light paper needs a crisp cursor, not a dark halo. !important also beats the
   box-shadow written by the caretPulse animation during its visible frame. */
html[data-skin="airy"] body[data-theme="light"] .composer .ta-caret,
html[data-skin="airy"] body[data-theme="light"] .term-cursor:not(.standalone) {
  box-shadow: none !important;
}
/* .ta-caret-mirror is visibility:hidden in the base sheet — it only measures the
   insertion point, so it is deliberately left alone. */


/* TOGGLES TAKE THE ACCENT TOO (John, 2026-09-23: "all toggles should also take from that
   color change"). Every switch painted its ON track with the skin ink — .mc-track via
   var(--text), the three .q-auto-track variants the same, and .mdl-vis-tog through
   var(--accent-rgb), which airy had already rewritten to ink. They all read the accent
   now, and each knob uses --on-accent-live so it stays visible on the bright accents for
   the same reason the mic glyph does. OFF tracks stay a neutral ink tint: an accent is
   for state that is ON, and colouring both ends would say nothing. */

/* Master Controller */
html[data-skin="airy"] .mc-chip.on .mc-switch .mc-track { background: var(--accent-live); }
html[data-skin="airy"] .mc-chip.on .mc-switch .mc-track::after { background: var(--on-accent-live); }

/* Auto-send, all three sizes it is drawn at */
html[data-skin="airy"] .q-auto input:checked + .q-auto-track { background: var(--accent-live); }
html[data-skin="airy"] .q-auto input:checked + .q-auto-track::after { background: var(--on-accent-live); }
html[data-skin="airy"] .pane-composer .ph-flow input:checked + .q-auto-track { background: var(--accent-live); }
html[data-skin="airy"] .pane-composer .ph-flow input:checked + .q-auto-track::after { background: var(--on-accent-live); }

/* Settings → visible models */
html[data-skin="airy"] .mdl-vis-tog.on { background: var(--accent-live); border-color: var(--accent-live); }
html[data-skin="airy"] .mdl-vis-tog.on::after { background: var(--on-accent-live); }


/* The accent picker is ONE ROW, and Default is a labelled pill (John, 2026-09-23:
   "look at the default button you made. Also put all the colors on one line").
   The base sheet forces every .accent-seg button to a 20x20 circle filled with var(--sw);
   my Default button has no --sw and a text label, so it collapsed to 20px and the word
   printed straight over the first swatch. It needs its own size. flex-wrap:nowrap keeps
   the swatches on a single line instead of spilling onto a second. */
html[data-skin="airy"] .accent-seg { flex-wrap: nowrap; align-items: center; }
html[data-skin="airy"] .accent-seg .accent-break { display: none; }
html[data-skin="airy"] .accent-seg button.accent-none {
  width: auto; height: 22px; padding: 0 12px; border-radius: 999px;
  background: transparent; border: 1px solid var(--line); box-shadow: none;
  color: var(--muted); font: 12.5px var(--ui-font); white-space: nowrap; margin-right: 4px;
}
html[data-skin="airy"] .accent-seg button.accent-none:hover {
  transform: none; background: var(--hover); color: var(--text);
}
html[data-skin="airy"] .accent-seg button.accent-none.active {
  background: var(--text); border-color: var(--text); color: var(--on-ink);
}


/* THE BLINK CARRIES THE ACCENT TOO (John, 2026-09-23: "two colors on the cursors white
   and orange blinking"). The idle caret animates with @keyframes caretPulse, which
   hardcodes var(--accent) — rewritten to ink by this skin, so white in Dark — while the
   caret-solid state held during typing was already the accent. The caret therefore
   changed colour depending on whether you were typing. An animation also beats a normal
   background declaration, so overriding the element alone could never have fixed it.
   Redefining the keyframes by the same name wins, because this sheet loads after the
   base one. The glyph uses --on-accent-live for the same reason the mic icon does. */
@keyframes caretPulse {
  0%, 50%      { background-color: var(--accent-live); background-image: none; box-shadow: 0 0 6px var(--accent-live); color: var(--on-accent-live); }
  50.01%, 100% { background-color: var(--bg);          background-image: none; box-shadow: none; color: var(--text); }
}
/* The thinking-meter block takes the same accent, without a halo.
   :not(.standalone) is load-bearing. The standalone variant is not a block cursor at all —
   it is the KITT scanner, an inline-flex container holding five .sq rectangles, and the
   base sheet clears its background and shadow on purpose. Without this guard the rule
   here (specificity 0,2,1) outranks that reset (0,2,0) and paints the container solid,
   which turned the scanner into one long accent bar with the squares lost inside it. */
html[data-skin="airy"] .term-cursor:not(.standalone) {
  background: var(--accent-live);
  box-shadow: none;
}

/* LIGHT MODE PREFERS A LIGHT GLYPH ON THE ACCENT (John, 2026-09-23: "in lightmode the
   dark inside the buttons should be light"). Ink-on-accent reads heavy against a paper
   page, so blue, purple, red, pink and gray flip their glyph to white here.

   Orange, neon and neongreen do NOT flip, and this is not an oversight: white scores
   2.84, 1.19 and 1.36 against those fills, all under the 3:1 WCAG floor for an icon or a
   UI component boundary. Forcing them light would bring back the invisible mic icon
   reported an hour earlier. They keep ink, which scores 6.60, 15.80 and 13.82.

   Scoped to Light only, as asked. Worth knowing: the accent FILL is identical in both
   modes, so the contrast maths does not change — if you would rather the glyph be the
   same colour in Dark too, this block just loses its :not() guard. */
html[data-skin="airy"] body:not([data-theme="dark"])[data-accent="blue"],
html[data-skin="airy"] body:not([data-theme="dark"])[data-accent="purple"],
html[data-skin="airy"] body:not([data-theme="dark"])[data-accent="red"],
html[data-skin="airy"] body:not([data-theme="dark"])[data-accent="pink"],
html[data-skin="airy"] body:not([data-theme="dark"])[data-accent="gray"] {
  --on-accent-live: #ffffff;
}

/* ONLY THE SELECTED SWATCH IS RINGED, AND THE RING IS INK (John, 2026-09-23: "remove the
   border on the not selected ones ... remove the WHITE on the selected one"). The base
   sheet gives every swatch an inset 1px dark edge (box-shadow) plus a 2px transparent
   border, then marks the active one with border-color #fff — so all of them carried an
   edge and the chosen one wore a white ring that fought the paper. Unselected swatches
   are now bare colour; the selected one is the only thing with a ring, drawn in ink so
   it reads in both modes. Same rule for the Default pill, which is part of this row. */
html[data-skin="airy"] .accent-seg button {
  box-shadow: none; border-color: transparent;
}
html[data-skin="airy"] .accent-seg button.active {
  border-color: var(--text);
}
html[data-skin="airy"] .accent-seg button.accent-none {
  border-color: transparent;
}
html[data-skin="airy"] .accent-seg button.accent-none.active {
  background: transparent; color: var(--text); border: 1px solid var(--text);
}

/* ---- wordmark halo (John, 2026-09-23) ----------------------------------------
   The Journal's /JOURNAL wordmark carries a soft glow (brain.css .bn-appname).
   The app's /LUMINAIR wordmark now carries the same halo, but only on the dark
   themes, where ink is light on a dark surface and the glow reads as a halo. On
   Light and White the same filter only smudges dark ink into a grey haze, so it is
   removed there for BOTH wordmarks. The mark is real text now, so this is a plain
   drop-shadow on glyph alpha, the same thing brain.css does for the Journal mark. */
html[data-skin="airy"] body:not([data-theme="light"]):not([data-theme="white"]) .appname {
  /* Mobile-strength halo in the live accent (John, 2026-09-23: "also the luminair").
     Ink on Default, the chosen colour otherwise; the mark itself stays ink. */
  /* Two stacked shadows, not one. The mark is only 12px tall, so a single 6px blur
     spread too thin to read as a glow at all. A tight 3px core gives the glyph its
     bloom and a wide 10px pass gives the halo around it, which is the same
     blur-to-height ratio mobile uses on its own logo. */
  /* One soft pass, the same weight brain.css gives the Journal mark (John,
     2026-09-23: "too much glow"). The earlier stacked pair was sized for a 12px
     masked mark and reads as a flare on real 15px text. */
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--accent-live) 35%, transparent));
}
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]) .appname,
html[data-skin="airy"] body:is([data-theme="light"],[data-theme="white"]) .bn-appname,
body:is([data-theme="light"],[data-theme="white"]) .bn-appname {
  filter: none;
}

/* ---- pane head: model and effort read as words, not shouting (2026-09-23) ------
   John: "I prefer not all caps." The caps were never in the data — EFFORTS is authored
   as Low / Med / High with micro L / M / H, and the model list carries short names like
   "Opus 5". The shouting came from one rule above, which puts text-transform: uppercase
   on every .pane-head button, .pbtn and .pmodesel, and it inherits into these two spans.

   So the fix is to opt the two labels out, not to transform them. An earlier attempt
   lower-cased them and tried to restore the initial with ::first-letter; that pseudo
   does not match on flex items in this engine, so the labels rendered as "o" and "m".
   Letter-spacing drops with it: the .1em tracking exists to let all-caps breathe. */
html[data-skin="airy"] .pane-head .pmodesel .pmodel,
html[data-skin="airy"] .pane-head .pmodesel .pmodel.mini,
html[data-skin="airy"] .pane-head .pmodesel .peffort,
html[data-skin="airy"] .pane-head .pmodesel .peffort span {
  text-transform: none; letter-spacing: .01em;
}

/* ---- a finished tab reads green (2026-09-23) ---------------------------------
   John: "if done the dot should be green." The dot was never showing status here.
   tintDotToModel() writes --dot-c as an INLINE style on every repaint, running or
   not, and the base rule is background: var(--dot-c, var(--faint)) — so the model
   colour always won and an idle tab wore Claude orange. The grey idle fallback was
   unreachable in practice.

   Done (paneStatus 'idle': turn over, nothing queued, no background task) now paints
   the same mint the waiting/queued state uses, so "nothing owed" reads green whether
   the session is resting or holding a queue. The declaration deliberately does NOT
   mention --dot-c, or the inline model tint would take it back.

   Thinking keeps the model tint, which is what makes the running dot match the KITT
   scanner, and error keeps its red. */
html[data-skin="airy"] .tab-chip .tc-dot.idle { background: #45e3b0; }

/* ---- Master Controller daily report card (John, 2026-09-24, //maddox: "THIS NEEDS A
   DRASTIC REDESIGN") ----------------------------------------------------------------------
   Paper, not the dark app: 14px radius, no accent rail, no orange eyebrow. Ink-only type,
   with red and green reserved for the verdict, and always paired with a mark and words. */
html[data-skin="airy"] .mcr-overlay { background: rgba(17,18,20,.28); }
html[data-skin="airy"] .mcr-card { width: 560px; padding: 20px 22px 16px; border-radius: 14px; border: 1px solid var(--line); border-left: 1px solid var(--line); background: var(--panel-2); box-shadow: 0 24px 60px rgba(17,18,20,.16); }
html[data-skin="airy"] .mcr-head { padding-bottom: 0; border-bottom: 0; }
html[data-skin="airy"] .mcr-eyebrow { font: 11px/1 var(--airy-mono); font-weight: 400; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
html[data-skin="airy"] .mcr-date { font-size: 20px; font-weight: 600; letter-spacing: -.01em; margin-top: 6px; }
html[data-skin="airy"] .mcr-sec-title { font: 11px/1 var(--airy-mono); font-weight: 400; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); margin: 18px 0 8px; padding-top: 0; border-top: 0; }
html[data-skin="airy"] .mcr-narr { font-size: 13px; line-height: 1.6; margin: 0; }
html[data-skin="airy"] .mcr-drill.open { border-left: 1px solid var(--line); margin: 10px 0 2px; }
html[data-skin="airy"] .mcr-drill-title, html[data-skin="airy"] .mcr-drill-kind { font-family: var(--airy-mono); font-weight: 400; letter-spacing: .1em; color: var(--muted); }
html[data-skin="airy"] .mcr-approve { background: var(--text); color: var(--panel, #fff); border-color: var(--text); border-radius: 999px; }
html[data-skin="airy"] .mcr-reject, html[data-skin="airy"] .mcr-undo { border-radius: 999px; }
html[data-skin="airy"] .mcr-card { --mcr-bad: #9b1c12; --mcr-ok: #1a6b35; }
html[data-skin="airy"] body[data-theme="dark"] .mcr-card { --mcr-bad: #ff9a92; --mcr-ok: #7fd89a; }

/* ---- paywall (#pw-overlay): always paper, same as the sign-in gate ------------------
   John, 2026-09-25: the first-run screens start on white, never dark, never orange.
   The overlay pins the light tokens itself so a stored Dark theme cannot reach it.
   The bottom follows one hierarchy: one ink primary button, a quiet creator-code link,
   and a single faint footer for account + legal. */
html[data-skin="airy"] #pw-overlay {
  --bg: #f7f7f8; --panel: #ffffff; --text: #242421; --muted: #777772; --faint: #9a9a95;
  --on-ink: #f7f7f8; --ink-rgb: 36,36,33;
  --line: rgba(36,36,33,.12); --accent-soft: rgba(36,36,33,.06);
  background: #f7f7f8; color: var(--text);
}
html[data-skin="airy"] #pw-overlay .pw-card { max-width: 460px; padding: 48px 32px 32px; }
html[data-skin="airy"] #pw-overlay .pw-feats li::before { background: var(--text); }
html[data-skin="airy"] #pw-overlay .pw-feat-d,
html[data-skin="airy"] #pw-overlay .pw-plan-sub,
html[data-skin="airy"] #pw-overlay .pw-free-sub { color: var(--muted); }
html[data-skin="airy"] #pw-overlay .pw-free { background: var(--accent-soft); border: 1px solid var(--line); border-radius: 10px; animation: none; }
html[data-skin="airy"] #pw-overlay .pw-free-h { color: var(--text); }
html[data-skin="airy"] #pw-overlay .pw-seg-btn { border-radius: 999px; background: transparent; }
html[data-skin="airy"] #pw-overlay .pw-seg-btn.on,
html[data-skin="airy"] #pw-overlay .pw-tab.on { border-color: var(--text); background: var(--text); color: var(--on-ink); }
html[data-skin="airy"] #pw-overlay .pw-tab { background: transparent; }
html[data-skin="airy"] #pw-overlay .pw-tab:not(.on):hover,
html[data-skin="airy"] #pw-overlay .pw-seg-btn:not(.on):hover { background: var(--accent-soft); color: var(--text); }
html[data-skin="airy"] #pw-overlay .pw-seat-btn:hover { border-color: var(--text); }

/* Primary action: the only filled element at the bottom. */
html[data-skin="airy"] #pw-overlay .pw-cta {
  margin-top: 22px; min-height: 52px; padding: 0 20px;
  background: var(--text); color: var(--on-ink); border: 0; border-radius: 999px;
  font: 500 15px/1 var(--ui-font); letter-spacing: -.005em; box-shadow: none;
}
html[data-skin="airy"] #pw-overlay .pw-cta:hover { transform: none; filter: none; opacity: .92; }
html[data-skin="airy"] #pw-overlay .pw-cta:disabled { opacity: .5; }
/* Checkout errors (for example "verify your email") read as a calm notice, not an alarm. */
html[data-skin="airy"] #pw-overlay .pw-err {
  margin-top: 14px; padding: 10px 14px; border-radius: 10px; text-align: left;
  background: rgba(165,58,42,.06); border: 1px solid rgba(165,58,42,.18);
  color: #8a3222; font-size: 12.5px; line-height: 1.45;
}
html[data-skin="airy"] #pw-overlay .pw-refresh { margin-top: 10px; font-size: 12px; color: var(--muted); }

/* Creator code: a text link that opens one field with Apply inside it. */
html[data-skin="airy"] #pw-overlay .pw-refcode { margin-top: 14px; display: flex; flex-direction: column; align-items: center; gap: 6px; }
html[data-skin="airy"] #pw-overlay .pw-refcode-toggle,
html[data-skin="airy"] #pw-overlay .pw-refcode-clear {
  background: none; border: 0; padding: 4px; color: var(--muted); cursor: pointer;
  font: 12.5px/1.2 var(--ui-font); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(36,36,33,.25);
}
html[data-skin="airy"] #pw-overlay .pw-refcode-toggle:hover,
html[data-skin="airy"] #pw-overlay .pw-refcode-clear:hover { color: var(--text); }
html[data-skin="airy"] #pw-overlay .pw-refcode-form[hidden],
html[data-skin="airy"] #pw-overlay .pw-refcode-toggle[hidden],
html[data-skin="airy"] #pw-overlay .pw-refcode-clear[hidden] { display: none; }
html[data-skin="airy"] #pw-overlay .pw-refcode-field {
  display: flex; align-items: center; width: 280px; height: 40px; box-sizing: border-box;
  padding: 0 4px 0 14px; background: var(--panel); border: 1px solid var(--line); border-radius: 999px;
}
html[data-skin="airy"] #pw-overlay .pw-refcode-field:focus-within { border-color: rgba(36,36,33,.4); }
html[data-skin="airy"] #pw-overlay .pw-refcode-in {
  flex: 1; min-width: 0; width: auto; background: none; border: 0; padding: 0; color: var(--text);
  font: 13px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase;
}
html[data-skin="airy"] #pw-overlay .pw-refcode-in::placeholder { color: var(--faint); letter-spacing: .04em; text-transform: none; font-family: var(--ui-font); }
html[data-skin="airy"] #pw-overlay .pw-refcode-apply {
  height: 30px; padding: 0 14px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--accent-soft); color: var(--text); font: 500 12.5px/1 var(--ui-font);
}
html[data-skin="airy"] #pw-overlay .pw-refcode-apply:hover { background: rgba(36,36,33,.1); }
html[data-skin="airy"] #pw-overlay .pw-refcode-msg { font-size: 12px; color: var(--muted); max-width: 320px; }
html[data-skin="airy"] #pw-overlay .pw-refcode-msg:empty { display: none; }

/* Footer: account and legal share one faint block, separated from the purchase above. */
html[data-skin="airy"] #pw-overlay .pw-foot {
  margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
html[data-skin="airy"] #pw-overlay .pw-foot .pw-legal,
html[data-skin="airy"] #pw-overlay .pw-foot .pw-whoami { margin: 0; font: 11.5px/1.5 var(--ui-font); color: var(--faint); }
html[data-skin="airy"] #pw-overlay .pw-foot a { color: var(--muted); font-weight: 400; text-decoration: underline; text-underline-offset: 2px; text-decoration-color: rgba(36,36,33,.25); }
html[data-skin="airy"] #pw-overlay .pw-foot a:hover { color: var(--text); }
html[data-skin="airy"] #pw-overlay ~ .pw-close, html[data-skin="airy"] .pw-overlay .pw-close {
  background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 999px;
}
html[data-skin="airy"] .pw-overlay .pw-close:hover { background: var(--accent-soft); color: var(--text); }
html[data-skin="airy"] #pw-overlay .pw-card.pw-casual .pw-refcode,
html[data-skin="airy"] #pw-overlay .pw-card.pw-casual .pw-legal { display: none; }

/* ---- first-run connect step (.pane.ftu-connect) --------------------------------------
   John, 2026-09-25: with no model connected, a fresh pane is step one of setup. One
   column, one decision: pick a provider and connect it. The composer is hidden because
   nothing could answer yet. Three lead providers as cards, the rest as a quiet list. */
html[data-skin="airy"] .pane.ftu-connect .pane-composer { display: none; }
html[data-skin="airy"] .pane.ftu-connect .pane-body { overflow-y: auto; }
html[data-skin="airy"] .ftu-connect-view {
  width: 100%; max-width: 940px; margin: 0 auto; padding: 56px 32px 64px; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
html[data-skin="airy"] .ftu-steps { list-style: none; margin: 0 0 36px; padding: 0; display: flex; gap: 22px; }
html[data-skin="airy"] .ftu-steps li { display: flex; align-items: center; gap: 8px; font: 12px/1 var(--ui-font); color: var(--faint); }
html[data-skin="airy"] .ftu-steps li b {
  width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); font: 500 10.5px/1 var(--airy-mono); color: var(--faint);
}
html[data-skin="airy"] .ftu-steps li.on { color: var(--text); }
html[data-skin="airy"] .ftu-steps li.on b { background: var(--text); border-color: var(--text); color: var(--on-ink); }
html[data-skin="airy"] .ftu-h { margin: 0; font: 500 30px/1.15 var(--ui-font); letter-spacing: -.02em; color: var(--text); }
html[data-skin="airy"] .ftu-sub { margin: 10px 0 32px; max-width: 460px; font: 14px/1.5 var(--ui-font); color: var(--muted); }
html[data-skin="airy"] .ftu-p-lead { width: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1000px) { html[data-skin="airy"] .ftu-p-lead { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
html[data-skin="airy"] .ftu-p-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0;
  padding: 18px 18px 16px; text-align: left; cursor: pointer;
  background: var(--panel, #fff); border: 1px solid var(--line); border-radius: 14px;
  transition: border-color .12s, transform .12s;
}
html[data-skin="airy"] .ftu-p-card:hover { border-color: rgba(var(--ink-rgb), .35); transform: translateY(-1px); }
html[data-skin="airy"] .ftu-p-head { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; }
html[data-skin="airy"] .ftu-p-logo { width: 22px; height: 22px; border-radius: 6px; object-fit: contain; flex: 0 0 auto; }
html[data-skin="airy"] .ftu-p-mono {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-soft, rgba(var(--ink-rgb), .06)); color: var(--text); font: 500 12px/1 var(--ui-font);
}
html[data-skin="airy"] .ftu-p-name { font: 500 15px/1.2 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .ftu-p-by { margin-left: auto; font: 10px/1 var(--airy-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--faint); white-space: nowrap; }
html[data-skin="airy"] .ftu-p-how { font: 12.5px/1.45 var(--ui-font); color: var(--muted); }
html[data-skin="airy"] .ftu-p-models { font: 11px/1.4 var(--airy-mono); color: var(--faint); overflow-wrap: anywhere; }
html[data-skin="airy"] .ftu-p-go {
  margin-top: auto; align-self: stretch; text-align: center; padding: 9px 0; border-radius: 999px;
  background: var(--text); color: var(--on-ink); font: 500 13px/1 var(--ui-font);
}
html[data-skin="airy"] .ftu-p-more { width: 100%; margin-top: 28px; text-align: left; }
html[data-skin="airy"] .ftu-p-more-h { margin: 0 0 8px 4px; font: 10px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
html[data-skin="airy"] .ftu-p-row {
  width: 100%; display: flex; align-items: center; gap: 10px; padding: 11px 12px; cursor: pointer;
  background: transparent; border: 0; border-top: 1px solid var(--line); text-align: left;
}
html[data-skin="airy"] .ftu-p-row:last-child { border-bottom: 1px solid var(--line); }
html[data-skin="airy"] .ftu-p-row .ftu-p-logo { width: 18px; height: 18px; border-radius: 5px; }
html[data-skin="airy"] .ftu-p-row .ftu-p-name { font-size: 13.5px; min-width: 96px; }
html[data-skin="airy"] .ftu-p-row .ftu-p-how { flex: 1; min-width: 0; font-size: 12.5px; }
html[data-skin="airy"] .ftu-p-arrow { font: 12.5px/1 var(--ui-font); color: var(--muted); }
html[data-skin="airy"] .ftu-p-row:hover { background: rgba(var(--ink-rgb), .03); }
html[data-skin="airy"] .ftu-p-row:hover .ftu-p-arrow { color: var(--text); }
@media (max-width: 760px) { html[data-skin="airy"] .ftu-p-lead { grid-template-columns: 1fr; } }


/* Folders header: the add button is a labelled pill, "Add Working Folder +" (John,
   2026-09-25), and with no folders yet the filter box is hidden since there is nothing
   to filter. */
html[data-skin="airy"] .sec-head button.add-folder-pill {
  flex: 0 0 auto; margin: 0 4px 0 auto; padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: transparent; color: var(--text);
  font: 500 11.5px/1 var(--ui-font); letter-spacing: 0; text-transform: none; white-space: nowrap;
}
html[data-skin="airy"] .sec-head button.add-folder-pill:hover { background: var(--text); border-color: var(--text); color: var(--on-ink); }
html[data-skin="airy"] #projectsHead .sec-title { flex-shrink: 0; }
html[data-skin="airy"] #projectsHead .proj-filter { flex: 1 1 40px; min-width: 0; width: auto; }
html[data-skin="airy"] #projectsHead.no-folders .proj-filter,
html[data-skin="airy"] #projectsHead.no-folders .proj-filter-x { display: none !important; }

/* ---- FIRST-RUN VIEW (John, 2026-09-25: "TWO views ... COMPLETELY separated") --------
   Until the first session exists the sidebar is gone entirely, and the composer is the
   simplified one: input and send only, centred under the title in the .ftu-comp-slot
   that renderer.js measures into --ftu-comp-top. The NEW SESSION view (every later
   empty pane) keeps the standard composer pinned to the bottom. */
html[data-skin="airy"] body.ftu-mode aside,
html[data-skin="airy"] body.ftu-mode .side-resizer,
html[data-skin="airy"] body.ftu-mode #panelToggle { display: none !important; }
/* Centred on the WINDOW, not the pane (John, 2026-09-25: "slightly lower than it should"):
   the body lost its 34px top padding, and the group lifts by about half the top bar. */
html[data-skin="airy"] .pane.ftu-home .pane-body { padding: 0 48px; }
html[data-skin="airy"] .pane.ftu-home .pane-body .empty.home-empty { transform: translateY(-3vh); }
html[data-skin="airy"] .pane.ftu-home:not(.doc-split) > .pane-composer {
  top: var(--ftu-comp-top, 45%); bottom: auto; left: 50%; right: auto;
  width: min(640px, calc(100% - 48px)); padding: 0; transform: translateX(-50%);
}
html[data-skin="airy"] .pane.ftu-home .pane-composer .q-bar,
html[data-skin="airy"] .pane.ftu-home .pane-composer .pvoice,
html[data-skin="airy"] .pane.ftu-home .pane-composer .pstop { display: none !important; }
html[data-skin="airy"] .pane.ftu-home .pane-composer .composer { flex-wrap: nowrap; align-items: center; }
html[data-skin="airy"] .pane-body .empty.home-empty .ftu-comp-slot { width: 100%; margin-top: 28px; flex: 0 0 auto; }
html[data-skin="airy"] .pane.ftu-home .airy-home-models { margin-top: 28px; }
html[data-skin="airy"] .pane.ftu-home .pane-composer .composer > .ta-wrap { flex: 1 1 auto; width: auto; min-width: 0; }
html[data-skin="airy"] .pane.ftu-home .pane-composer .composer .psend { flex: 0 0 auto; margin-left: auto; }
html[data-skin="airy"] .pane.ftu-home .pane-composer .composer::after { content: none; display: none; }

/* First run has no title bar at all (John, 2026-09-25: "Remove the title bar completely
   from ftu session"), on the connect step and the first-run home alike. */
html[data-skin="airy"] body.ftu-mode .pane.ftu-home > .pane-head,
html[data-skin="airy"] body.ftu-mode .pane.ftu-connect > .pane-head { display: none !important; }
/* The "add your first working folder" card in the Folders section: the Staged Update
   card's outline and type, placed in the tree instead of the rail's foot. */
html[data-skin="airy"] .tree .sb-staged.tree-addfolder {
  width: calc(100% - 24px); margin: 6px 12px 14px; padding: 12px 34px 12px 14px;
  text-align: left; cursor: pointer; font: inherit;
}
html[data-skin="airy"] .tree .sb-staged.tree-addfolder .sb-update-title { white-space: normal; }

/* First-run step 2, "Choose a working folder" (John, 2026-09-25), on the step-1 sheet:
   one ink pill to open the folder picker and a quiet skip link under it. Finished steps
   in the stepper show a check in an outlined dot. */
html[data-skin="airy"] .ftu-folder-view { padding-top: 96px; }
html[data-skin="airy"] .ftu-folder-go {
  padding: 13px 28px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--text); color: var(--on-ink); font: 500 14px/1 var(--ui-font);
}
html[data-skin="airy"] .ftu-folder-go:hover { opacity: .88; }
html[data-skin="airy"] .ftu-folder-skip {
  margin-top: 16px; padding: 6px 10px; border: 0; background: transparent; cursor: pointer;
  color: var(--muted); font: 12.5px/1 var(--ui-font);
}
html[data-skin="airy"] .ftu-folder-skip:hover { color: var(--text); }
html[data-skin="airy"] .ftu-steps li.done { color: var(--muted); }
html[data-skin="airy"] .ftu-steps li.done b { border-color: var(--text); color: var(--text); }
html[data-skin="airy"] .home-empty .ftu-steps { margin-bottom: 28px; }
html[data-skin="airy"] .pane-body .empty .home-starts:empty { display: none; }

/* Notification count badges: the avatar's new-user count and the Team chat count
   (John, 2026-09-25: "Either it's square, or number is not centered, or not showing at
   all"). Both painted white text on --accent, and in dark mode the accent IS white, so
   the number vanished; the avatar one also had 3px corners. One ink pill for both, in
   either theme: --text fill with --on-ink digits (black on white in dark, white on black
   in light), a round 16px pill, and the digit centred by flex rather than line-height. */
html[data-skin="airy"] .ow-avatar .ow-newbadge,
html[data-skin="airy"] .team-dot {
  top: -5px; right: -6px; min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
  align-items: center; justify-content: center; border-radius: 999px;
  background: var(--text); color: var(--on-ink); border: 1.5px solid var(--bg); box-shadow: none;
  font: 600 9.5px/1 var(--ui-font); font-variant-numeric: tabular-nums; letter-spacing: 0; text-align: center;
}
html[data-skin="airy"] .ow-avatar .ow-newbadge.show { display: inline-flex; animation: none; }
html[data-skin="airy"] .team-dot:not([hidden]) { display: inline-flex; }

/* An empty pane has nothing to jump to: never show "↓ Latest" there (John, 2026-09-25:
   "Why am I seeing Latest at the bottom?!"). The scroll handler re-showed it after the
   first-run view pinned itself to the top. */
html[data-skin="airy"] .pane.empty-pane > .jump-latest { display: none !important; }

/* First-run provider cards: logo big and centred, the name, then Connect (John,
   2026-09-25). The sign-in line and the model list are gone. */
html[data-skin="airy"] .ftu-p-card.ftu-p-card-big { align-items: center; gap: 12px; padding: 26px 18px 18px; text-align: center; }
html[data-skin="airy"] .ftu-p-card-big .ftu-p-logo { width: 48px; height: 48px; border-radius: 12px; }
html[data-skin="airy"] .ftu-p-card-big .ftu-p-mono { display: inline-flex; align-items: center; justify-content: center; font: 600 22px/1 var(--ui-font); }
html[data-skin="airy"] .ftu-p-card-big .ftu-p-name { font-size: 15px; min-width: 0; }
html[data-skin="airy"] .ftu-p-card-big .ftu-p-go { align-self: stretch; margin-top: 4px; }
html[data-skin="airy"] .ftu-folder-view .ftu-sub { max-width: 540px; }

/* First run hides the whole top bar too (John, 2026-09-25: "remove that whole top bar
   as well"): nothing in it can act before a session exists. A transparent strip keeps
   the top edge draggable, and the close/minimize squares (re-homed onto .main by
   syncFtuMode) sit above it. Finished steps keep their number and are struck through. */
html[data-skin="airy"] body.ftu-mode .main > header { display: none !important; }
html[data-skin="airy"] body.ftu-mode .main { position: relative; }
html[data-skin="airy"] body.ftu-mode .main::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 34px; z-index: 5;
  -webkit-app-region: drag;
}
html[data-skin="airy"] body.ftu-mode .main > .win-ctrls { z-index: 6; -webkit-app-region: no-drag; }
html[data-skin="airy"] .ftu-steps li.done { color: var(--faint); text-decoration: line-through; text-decoration-thickness: 1px; }
html[data-skin="airy"] .ftu-steps li.done b { border-color: var(--line); color: var(--faint); background: transparent; }

/* First run hides the whole top bar too (John, 2026-09-25: "remove that whole top bar
   as well"): nothing in it can act before a session exists. A transparent strip keeps
   the top edge draggable, and the close/minimize squares (re-homed onto .main by
   syncFtuMode) sit above it. Finished steps keep their number and are struck through. */
html[data-skin="airy"] body.ftu-mode .main > header { display: none !important; }
html[data-skin="airy"] body.ftu-mode .main { position: relative; }
html[data-skin="airy"] body.ftu-mode .main::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 34px; z-index: 5;
  -webkit-app-region: drag;
}
html[data-skin="airy"] body.ftu-mode .main > .win-ctrls { z-index: 6; -webkit-app-region: no-drag; }
html[data-skin="airy"] .ftu-steps li.done { color: var(--faint); text-decoration: line-through; text-decoration-thickness: 1px; }
html[data-skin="airy"] .ftu-steps li.done b { border-color: var(--line); color: var(--faint); background: transparent; }

/* "Import sessions" card under Unsorted: the Staged Update card's outline, a title, a
   one-line description and an ✕ that hides it for good (John, 2026-09-25). */
html[data-skin="airy"] .tree .sb-staged.import-card {
  width: calc(100% - 24px); margin: 10px 12px 14px; padding: 12px 36px 12px 14px;
  box-sizing: border-box; cursor: pointer; text-align: left;
}
html[data-skin="airy"] .tree .sb-staged.import-card::after { display: none; }
html[data-skin="airy"] .import-card .import-card-desc { font: 12px/1.4 var(--ui-font); color: var(--muted); white-space: normal; }
html[data-skin="airy"] .import-card .import-card-x {
  position: absolute; top: 8px; right: 8px; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: var(--faint); font-size: 11px; line-height: 22px; cursor: pointer;
}
html[data-skin="airy"] .import-card .import-card-x:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .import-modal { position: relative; }
html[data-skin="airy"] .import-modal .import-modal-x {
  position: absolute; top: 12px; right: 12px; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: var(--faint); cursor: pointer;
}
html[data-skin="airy"] .import-modal .import-modal-x:hover { background: var(--hover); color: var(--text); }
html[data-skin="airy"] .overlay.import-ov { background: rgba(17,18,20,.18); }

/* One line on top of the session title bar, not two (John, 2026-09-25): the top bar
   already draws its bottom border, so a lone pane's title bar drops its own top border.
   Inside a tab block the tab strip sits above it and the border stays. */
html[data-skin="airy"] .pane:not(.in-tabblock) > .pane-head { border-top: 0; }
/* Collapsed ACTIVE SESSIONS is exactly the title bar's height (--pane-head-h, measured in
   renderer.js), content centred, so both bottom lines meet. */
html[data-skin="airy"] #activeWrap.aw-collapsed {
  height: var(--pane-head-h, auto); box-sizing: border-box; overflow: hidden;
  display: flex !important; flex-direction: column; justify-content: center;
}
html[data-skin="airy"] #activeWrap.aw-collapsed .sec-head.collapsed { padding-top: 0; padding-bottom: 4px; }
html[data-skin="airy"] #activeWrap.aw-collapsed .active-dots-mini { padding-bottom: 0; }

/* The connect step must open at the top: don't let the scroll anchor keep a lower spot
   as provider logos load in above it (John, 2026-09-25). */
html[data-skin="airy"] .pane.ftu-connect .pane-body,
html[data-skin="airy"] .pane.ftu-home .pane-body { overflow-anchor: none; }

/* ---- Account switcher, "Ledger A1 compact" (John, 2026-09-25, approved from
   mockups/account-switcher-a-compact.html). White card, mono group caps with the
   provider colour square, quiet outlined plan chips, every quota window as one
   aligned line: label / hairline bar / percent / reset. Ink bars, red only at the
   limit. Footer is one strip: Refresh quota and Add account side by side. ---- */
html[data-skin="airy"] .acct-menu { width: 320px; padding: 0; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; font-size: 13px; }
html[data-skin="airy"] .acct-menu > .acct-sep { margin: 0; opacity: 1; background: var(--line); }
html[data-skin="airy"] .acct-menu > .acct-sep:not(:first-child) { opacity: .6; }
html[data-skin="airy"] .acct-autoswitch { padding: 10px 14px; border-radius: 12px 12px 0 0; }
html[data-skin="airy"] .acct-autoswitch .as-title { font: 500 14px var(--ui-font); color: var(--text); }
html[data-skin="airy"] .acct-autoswitch.on .as-title { color: var(--text); }
html[data-skin="airy"] .acct-autoswitch .mc-sw { width: 30px; height: 18px; margin: 0; background: rgba(var(--ink-rgb),.16); }
html[data-skin="airy"] .acct-autoswitch .mc-sw::after { width: 14px; height: 14px; background: var(--on-ink); }
html[data-skin="airy"] .acct-autoswitch .mc-sw.on { background: var(--text); }
html[data-skin="airy"] .acct-autoswitch .mc-sw.on::after { transform: translateX(12px); background: var(--on-ink); }
html[data-skin="airy"] .acct-group.eng-start, html[data-skin="airy"] .acct-solo.eng-start { margin: 0; padding: 0; border-top: 0; }
html[data-skin="airy"] .acct-solo { margin: 0; }
html[data-skin="airy"] .acct-group .acct-sep.in-group { margin: 0 14px; opacity: 1; background: rgba(var(--ink-rgb),.07); }
html[data-skin="airy"] .acct-eng-head { padding: 8px 14px 2px; font: 9.5px var(--airy-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--faint); }
html[data-skin="airy"] .acct-eng-head .eh-swatch { width: 8px; height: 8px; border-radius: 2px; }
html[data-skin="airy"] .acct-card { border-radius: 0; }
html[data-skin="airy"] .acct-card:hover { background: rgba(var(--ink-rgb),.025); }
html[data-skin="airy"] .acct-card .acct-item { gap: 8px; padding: 6px 14px 0 22px; border-radius: 0; font: 13.5px var(--ui-font); }
html[data-skin="airy"] .acct-card .acct-item:hover { background: transparent; }
html[data-skin="airy"] .acct-card .acct-item.is-selected::before { left: 10px; top: 50%; bottom: auto; width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: var(--text); }
html[data-skin="airy"] .acct-card .acct-item:not(.is-selected)::before { content: ''; position: absolute; left: 10px; top: 50%; width: 5px; height: 5px; margin-top: -3px; border-radius: 50%; border: 1px solid var(--line); }
html[data-skin="airy"] .acct-card .acct-item { position: relative; }
html[data-skin="airy"] .acct-card .acct-cur { display: none; }
html[data-skin="airy"] .acct-item .type,
html[data-skin="airy"] .acct-item .type.plan-max,
html[data-skin="airy"] .acct-item .type.plan-pro,
html[data-skin="airy"] .acct-item .type.plan-engine,
html[data-skin="airy"] .acct-item .type.plan-codex { background: transparent; color: var(--muted) !important; border: 1px solid var(--line); border-radius: 999px; padding: 2px 7px; font: 9.5px var(--airy-mono); letter-spacing: .06em; text-transform: uppercase; font-weight: 400; }
html[data-skin="airy"] .acct-item .type:hover { color: var(--text) !important; background: transparent; filter: none; }
html[data-skin="airy"] .acct-item .dots { color: var(--muted); font-size: 14px; padding: 0 2px 0 4px; }
html[data-skin="airy"] .acct-limits { gap: 2px; padding: 3px 14px 7px 22px; border-radius: 0; }
html[data-skin="airy"] .acct-limits .lim { display: grid; grid-template-columns: 38px 1fr 34px 30px; align-items: center; gap: 8px; height: 15px; line-height: 15px; font-family: var(--airy-mono); }
html[data-skin="airy"] .acct-limits .lim .k { width: auto; font: 9px var(--airy-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
html[data-skin="airy"] .acct-limits .lim .cells { height: 2px; border-radius: 2px; background: rgba(var(--ink-rgb),.08); }
html[data-skin="airy"] .acct-limits .lim .cells .lim-fill, html[data-skin="airy"] .acct-limits .lim.tinted .cells .lim-fill { background: var(--text); border-radius: 2px; }
html[data-skin="airy"] .acct-limits .lim .cells .lim-pace { top: -2px; bottom: -2px; width: 1px; background: var(--faint); }
html[data-skin="airy"] .acct-limits .lim .v { width: auto; font: 500 10.5px var(--airy-mono); color: var(--text); text-align: right; }
html[data-skin="airy"] .acct-limits .lim .rst { width: auto; min-width: 0; font: 10.5px var(--airy-mono); color: var(--faint); text-align: right; }
html[data-skin="airy"] .acct-limits .lim .rst:not(:empty)::before { content: none; }
html[data-skin="airy"] .acct-limits .lim.high .cells .lim-fill { background: #e0402e; }
html[data-skin="airy"] .acct-limits .lim.high .v { color: #e0402e; }
html[data-skin="airy"] .acct-limits .lim.muted .v { color: var(--faint); opacity: 1; }
html[data-skin="airy"] .acct-limits .lim-err { font: 9.5px/1.4 var(--airy-mono); color: var(--faint); padding-top: 3px; }
html[data-skin="airy"] .acct-limits .lim-err:not(.soft) { color: #e0402e; }
html[data-skin="airy"] .acct-foot { display: flex; align-items: center; gap: 4px; padding: 4px 6px; }
html[data-skin="airy"] .acct-foot .acct-item { gap: 6px; padding: 5px 8px; border-radius: 8px; font: 12.5px var(--ui-font); color: var(--muted); font-weight: 400; }
html[data-skin="airy"] .acct-foot .acct-item:hover { color: var(--text); background: var(--hover); }
html[data-skin="airy"] .acct-foot .acct-item .check { width: auto; color: inherit; font-size: 12px; }
html[data-skin="airy"] .acct-foot .acct-item .lbl { flex: 0 0 auto; }

/* Branch-out agent list, the clean way (John, 2026-09-25, from the marketing mockup): a
   plain ink mark instead of a coloured status dot (check when done, a soft dot while
   working, a faint dot while queued, a red cross on failure), the count in ink, and no
   caret after the model name. Text size and font stay as they are. The model stays
   clickable while the agent runs; its tooltip still says so. */
html[data-skin="airy"] .bo-subs .bo-sub .adot {
  width: 12px; height: auto; flex: 0 0 12px; border-radius: 0; box-shadow: none;
  background: none !important; display: inline-flex; justify-content: center;
  font: 13px/1 var(--ui-font); color: var(--faint);
}
html[data-skin="airy"] .bo-subs .bo-sub .adot::before { content: '·'; font-weight: 700; }
html[data-skin="airy"] .bo-subs .bo-sub .adot.thinking { color: var(--text); }
html[data-skin="airy"] .bo-subs .bo-sub .adot.thinking::before { content: '•'; }
html[data-skin="airy"] .bo-subs .bo-sub .adot.waiting { color: var(--text); }
html[data-skin="airy"] .bo-subs .bo-sub .adot.waiting::before { content: '✓'; font-weight: 400; }
html[data-skin="airy"] .bo-subs .bo-sub .adot.error { color: #b3261e; }
html[data-skin="airy"] .bo-subs .bo-sub .adot.error::before { content: '✕'; font-weight: 400; font-size: 11px; }
html[data-skin="airy"] .bo-subs .bo-sub-req { color: var(--text); }
html[data-skin="airy"] .bo-subs .bo-caret { display: none; }

/* Queue chip during a branch-out (John, 2026-09-25): "queued | left •" in one pill. */
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue.q-has-bo { width: auto; gap: 0; padding: 0 8px; }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue .q-sep { width: 1px; height: 12px; background: var(--line); margin: 0 7px; flex: 0 0 auto; }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue .q-n-bo { color: var(--text); }
html[data-skin="airy"] .pane-composer .q-bar-chips .q-chip.q-queue .q-bo-dot { width: 5px; height: 5px; border-radius: 50%; background: #000; margin-left: 5px; flex: 0 0 auto; }

/* Branch-out completion card, redesigned to match the live branch-out card
   (John, 2026-09-25). Same paper card with one hairline and 14px corners; a mono
   eyebrow title; big plain numerals with mono labels; ink, not green or orange;
   hairline pill buttons with the primary one filled in ink. Conflicts keep one
   quiet red so they still read as "needs you". */
html[data-skin="airy"] .msg.assistant.bo-recap-card {
  background: var(--panel-2); border: 1px solid var(--line); border-left: 1px solid var(--line);
  border-radius: 14px; padding: 18px 18px 16px; box-shadow: none; overflow: visible;
}
html[data-skin="airy"] .bo-recap-head { gap: 10px; padding-bottom: 0; border-bottom: 0; }
html[data-skin="airy"] .bo-recap-glyph { display: none; }
html[data-skin="airy"] .bo-recap-title {
  font: 11px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase;
  font-weight: 400; color: var(--faint);
}
html[data-skin="airy"] .bo-recap-badge,
html[data-skin="airy"] .bo-recap-badge.warn {
  background: transparent; border: 0; padding: 0; border-radius: 0;
  font: 11px/1 var(--airy-mono); letter-spacing: .1em; font-weight: 400; text-transform: uppercase; color: var(--text);
}
html[data-skin="airy"] .bo-recap-badge.warn { color: #b3261e; }
html[data-skin="airy"] .bo-recap-stats {
  background: transparent !important; border: 0 !important; border-radius: 0; margin: 0; padding: 20px 0 18px; gap: 20px;
}
html[data-skin="airy"] .bo-recap-stat .n,
html[data-skin="airy"] .bo-recap-stat.good .n {
  font: 500 34px/1 var(--ui-font); letter-spacing: -.03em; color: var(--text);
}
html[data-skin="airy"] .bo-recap-stat.warn .n { font: 500 34px/1 var(--ui-font); letter-spacing: -.03em; color: #b3261e; }
html[data-skin="airy"] .bo-recap-stat .l {
  font: 11px/1 var(--airy-mono); letter-spacing: .14em; text-transform: uppercase;
  font-weight: 400; color: var(--faint); margin-top: 8px;
}
html[data-skin="airy"] .bo-recap-line,
html[data-skin="airy"] .bo-recap-line.ok { font: 13.5px/1.45 var(--ui-font); font-weight: 400; color: var(--text); margin-top: 0; }
html[data-skin="airy"] .bo-recap-line.warn { color: #b3261e; }
html[data-skin="airy"] .bo-recap-ledgerh .lt {
  font: 11px/1 var(--airy-mono); letter-spacing: .12em; font-weight: 400; color: var(--faint);
}
html[data-skin="airy"] .bo-recap-ledger { border: 0; border-radius: 0; }
html[data-skin="airy"] .bo-recap-brow { padding: 12px 0; gap: 10px; border-top: 1px solid var(--line); }
html[data-skin="airy"] .bo-recap-brow:first-child { border-top: 0; }
html[data-skin="airy"] .bo-recap-brow:hover { background: transparent; }
html[data-skin="airy"] .bo-recap-dot,
html[data-skin="airy"] .bo-recap-dot.warn { background: transparent; width: 12px; height: 12px; }
html[data-skin="airy"] .bo-recap-dot svg,
html[data-skin="airy"] .bo-recap-dot.warn svg { color: #b3261e; width: 12px; height: 12px; }
html[data-skin="airy"] .bo-recap-bname { font: 500 14px/1.35 var(--ui-font); color: var(--text); }
html[data-skin="airy"] .bo-recap-bmeta { font: 11px/1 var(--airy-mono); letter-spacing: .1em; color: var(--faint); margin-top: 4px; }
html[data-skin="airy"] .bo-recap-btag,
html[data-skin="airy"] .bo-recap-btag.warn {
  background: transparent; border: 0; padding: 0; border-radius: 0;
  font: 11px/1 var(--airy-mono); letter-spacing: .1em; font-weight: 400; text-transform: uppercase; color: #b3261e;
}
html[data-skin="airy"] .bo-recap-more { border-top: 1px solid var(--line); padding: 10px 0; font: 11px/1 var(--airy-mono); letter-spacing: .1em; color: var(--faint); text-align: left; }
html[data-skin="airy"] .bo-recap-actions { margin-top: 16px; gap: 8px; }
html[data-skin="airy"] .bo-recap-act {
  border-radius: 999px; font: 12.5px var(--ui-font); font-weight: 400; padding: 6px 15px;
}
html[data-skin="airy"] .bo-recap-act.merge { background: var(--text); color: var(--on-ink, #fff); border: 1px solid var(--text); font-weight: 500; }
html[data-skin="airy"] .bo-recap-act.merge:hover:not(:disabled) { background: var(--text); border-color: var(--text); opacity: .88; }
html[data-skin="airy"] .bo-recap-act.discard { background: transparent; border: 1px solid var(--line); color: var(--muted); }
html[data-skin="airy"] .bo-recap-act.discard:hover:not(:disabled) { color: #b3261e; border-color: var(--line); background: var(--hover); }
html[data-skin="airy"] .bo-recap-act-msg { font: 12px/1.4 var(--ui-font); color: #b3261e; }
html[data-skin="airy"] .bo-recap-actions + .bo-recap-line, html[data-skin="airy"] .bo-recap-ledger + .bo-recap-line { margin-top: 14px; }
