/* ═══════════════════════════════════════════════════════════════════════════
   os-kit.css — THE PLATFORM'S SHARED COMPONENTS

   ⛔ ONE DEFINITION PER COMPONENT, AND EVERY SURFACE READS IT. The thing this
      file exists to stop was on screen when it was written: TWO loaders painted
      at once — the boot gate's 132px partner and the shell's own 34px mark and
      sentence — centred in two different boxes, overlapping, one logo growing
      out of the other. Neither was wrong on its own. Having two was the defect,
      and it survived because each lived in its own file with its own markup.
   ⚡ A component belongs here the moment a SECOND surface needs it. Until then
      it belongs to its app. This file is not a dumping ground for one screen's
      styling — it is the set of things that must look identical everywhere.
   ⚡ Everything here is theme-aware through the page's own tokens (--ink,
      --bg, --muted, --line, --violet). ⛔ Never hard-code a colour that a theme
      has a token for: a component that ignores the theme is the fastest way to
      make a dark screen look broken.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the loader ────────────────────────────────────────────────────────────
   ⛔ THE BRAND, NOT A PLACEHOLDER, AND NOT A SPINNER. A spinner says "wait";
      the wordmark says whose product you are waiting for, and the chat contour
      around AI is the one piece of this brand that is alive. It is the SAME
      artwork the header mounts (`#brainclub-contour-logo` out of the sprite),
      so it can never drift from the header the way a second copy would.
   ⛔ ONE LOADER ON SCREEN AT A TIME. `.bcLoader` is fixed and centred; the
      compact `.bcLoader.inline` is absolutely placed inside a pane. The boot
      gate suppresses the inline one — see the `html.whBoot` rule below — so
      the two can never stack the way they did before this file existed. */
/* ⛔ THE FULL VIEWPORT, because the bar is hidden while the gate is up. It was
   inset by the bar's height from when the header still painted underneath; with
   the header gone that left a 54px band of bare page above a centred mark, and
   the mark sat 27px below the true centre of what a person was looking at. */
.bcLoader{
  position:fixed; inset:0; z-index:40;
  display:none; place-items:center; pointer-events:none;
  /* ⚡ The wash behind is a wide, very soft aurora — it gives the mark a
     ground to sit on so it does not read as clip-art dropped on a blank page. */
  background:
    radial-gradient(58% 46% at 50% 44%, var(--glowA,rgba(124,92,255,.11)), transparent 72%),
    radial-gradient(42% 34% at 62% 62%, var(--glowB,rgba(34,211,238,.07)), transparent 74%);
}
.bcLoader[hidden]{display:none!important}
.bcLoader.on{display:grid}

.bcLoader .bcLoaderSpace{
  position:absolute; inset:0; width:100%; height:100%;
  pointer-events:none; z-index:1;
}

.bcLoader .in{
  position:relative; z-index:2;
  display:flex; flex-direction:column; align-items:center; gap:20px;
  animation:bcLoaderRise .5s cubic-bezier(.2,.8,.2,1) both;
}



/* ⚡ THE MARK. `--bc-mark-flow-*` and `--bc-mark-contour-animation` are the
   sprite's own switches — a page stylesheet cannot select into the `use`
   shadow tree, only inherited custom properties cross it, which is why these
   are properties and not rules. The filament traces the chat contour and the
   contour itself breathes colour: the "colourful chat icon around AI". */
.bcLoader .bcLoaderMark{
  display:block; width:min(268px,64vw); height:auto; overflow:visible;
  --bc-logo-ink:var(--ink,#0b1020);
  --bc-mark-flow-opacity:.95;
  --bc-mark-flow-play:running;
  --bc-mark-flow-speed:1.25s;
  --bc-mark-contour-animation:bc-mark-hue 4.6s ease-in-out infinite;
  filter:drop-shadow(0 14px 30px var(--shadow,rgba(60,40,120,.22)));
  animation:bcLoaderBreathe 3.6s ease-in-out infinite alternate;
}
/* ⛔ The flow filament is WHITE on dark and near-black on light. On a light
   page a white filament over a pale gradient is invisible, which reads as the
   animation being broken rather than as a colour being wrong. */
.bcLoader .bcLoaderMark{--bc-mark-flow-color:rgba(255,255,255,.92)}
:root[data-theme="light"] .bcLoader .bcLoaderMark{--bc-mark-flow-color:rgba(255,255,255,.96)}

/* ⚡ An INDETERMINATE rail, never a percentage. We do not know how long the
   workspace takes to open, and a bar that claims 60% when nothing measured
   60% is the same lie as a fabricated number anywhere else in this product. */
.bcLoader .bcLoaderRail{
  position:relative; width:180px; height:2px; border-radius:99px;
  background:var(--surf2,rgba(148,163,204,.10)); overflow:hidden;
}
.bcLoader .bcLoaderRail i{
  position:absolute; inset:0; display:block; border-radius:99px;
  background:var(--aurora,linear-gradient(100deg,#7c5cff,#22d3ee 55%,#a3e635));
  animation:bcLoaderSweep 1.5s cubic-bezier(.5,0,.3,1) infinite;
}
.bcLoader .bcLoaderSay{
  font:500 12.5px/1.4 var(--body,Inter,sans-serif); letter-spacing:.02em;
  color:var(--muted,#8b96ac); text-align:center; max-width:min(420px,80vw);
}
.bcLoader .bcLoaderSay:empty{display:none}

@keyframes bcLoaderRise{from{opacity:0;transform:translateY(9px) scale(.985)}to{opacity:1;transform:none}}
@keyframes bcLoaderBreathe{from{transform:translateY(1px) scale(.995)}to{transform:translateY(-4px) scale(1.005)}}
@keyframes bcLoaderSweep{0%{transform:translateX(-100%) scaleX(.45)}60%{transform:translateX(60%) scaleX(.7)}100%{transform:translateX(200%) scaleX(.45)}}

/* ── the compact one, inside a pane that is still fetching ─────────────── */
/* ⚠ The pane's own loader is NOT full-screen: it sits inside the shell, beside
   a rail and a dock that are both legitimately on screen by then. */
.bcLoader.inline{
  position:absolute; inset:0 0 0 var(--wh-nav,272px); z-index:1;
  background:none;
}
.bcLoader.inline .in{flex-direction:row; align-items:center; gap:12px}
.bcLoader.inline .bcLoaderMark{width:132px; filter:none; animation:none}
.bcLoader.inline .bcLoaderRail{width:64px}
@media(max-width:860px){ .bcLoader.inline{left:0} }

/* ⛔ THE GATE OWNS THE SCREEN. While `html.whBoot` is up the shell may still
   be fetching and would draw its own inline loader underneath the boot one —
   which is exactly the overlap this file was created to end. One rule, at the
   root, where no module's load order can get in front of it. */
html.whBoot .bcLoader.inline{display:none!important}

@media (prefers-reduced-motion:reduce){
  /* ⚡ Still, but NOT blank: the contour keeps its colour and the filament
     keeps its opacity — only the motion goes. A loader with nothing on it
     reads as a failed load to the very people who asked for less movement. */
  .bcLoader .in,.bcLoader .bcLoaderMark,.bcLoader .bcLoaderRail i{animation:none}
  .bcLoader .bcLoaderMark{--bc-mark-flow-play:paused;--bc-mark-contour-animation:none}
  .bcLoader .bcLoaderRail i{transform:none;opacity:.5}
}

/* ── the person's mark ─────────────────────────────────────────────────────
   ⚡ ONE AVATAR, THREE SURFACES: the pill in the bar and at the rail's foot,
      the head of the context menu, the hero of the profile page. Each had its
      own circle with its own hairline border; this is the ring they share —
      the aurora the door's hairline wears, as a conic band with a gap of
      ground between it and the picture, so a photo and an initial read as
      the same object everywhere.
   The picture arrives as an inline background-image on the element; the
   initial as its text. Size and ink are the caller's (width, height,
   font-size, color) — the kit owns only the ring.
   ⚠ The callers' own rules set `border:2px solid var(--bg)` and
     `background-clip:padding-box` again, because two of them are reached by
     an ID selector that outranks this file; the values must match these.
   ⛔ `isolation:isolate` — the band is a ::before at z -1 and must never sink
      under the surface behind the avatar.
   ⛔ THIS BLOCK LIVES ABOVE THE SHEET, VALUES UNTOUCHED (2026-09-06). The
      tokens-only gate (test-app-sheet.mjs) measures from the sheet wrap rule
      to end-of-file, so the sheet section is LAST and every shared component
      above it. The ring's aurora is the brand gradient — the same three stops
      `--aurora` carries — and rewriting it as tokens would change the face,
      not the compliance; order is the fix, not a recolour. */
.bcAvatar{position:relative;isolation:isolate;display:grid;place-items:center;border-radius:50%;flex:none;
  border:2px solid var(--bg,#04070d);background-clip:padding-box;
  background-size:cover;background-position:center;text-transform:uppercase}
.bcAvatar::before{content:'';position:absolute;inset:calc(-.14em - 1.5px);border-radius:inherit;z-index:-1;
  background:conic-gradient(from 200deg,#22d3ee,#7c5cff 38%,#f472b6 66%,#22d3ee)}
/* A stranger's mark: no aurora, a dashed ground — the absence, drawn. */
.bcAvatar.guest{color:var(--faint,#8b94a6)}
.bcAvatar.guest::before{background:none;border:1.5px dashed var(--line2,rgba(148,163,204,.26))}

/* ── the app sheet — ONE store page for every app ──────────────────────────
   ⛔ IT LIVES HERE BECAUSE A SECOND SURFACE NEEDS IT. It was private CSS in
      work-home (`.whModPage`), so the Modules screen owned the only app page in
      the product and any other surface wanting one would have had to draw a
      second — which is precisely the two-loaders defect at the top of this file,
      one release later.
   ⛔ TOKENS ONLY. Not one literal colour: this sheet carries an app's cover
      picture and its icon, and a card that ignores the theme under a photograph
      is the fastest way to make a light page look broken.
   ⚡ The card is the sheet; the BACKDROP belongs to whatever mounts it
      (`.whModWrap` on the Modules screen, `.bcAppSheetWrap` standing alone). */
.bcAppSheetWrap{
  position:fixed; inset:0; z-index:60; display:grid; place-items:center; padding:24px;
  background:color-mix(in srgb,var(--bg) 62%,transparent); backdrop-filter:blur(6px);
}
.bcAppSheet{
  width:min(720px,100%); max-height:88vh; overflow:auto; position:relative;
  border:1px solid var(--line); border-radius:18px; background:var(--panel);
  box-shadow:var(--lift); color:var(--ink);
}
.bcAppSheet .bcAsLoad{padding:34px 26px; font:400 12.5px var(--mono); color:var(--faint)}

/* the close, over the cover — its own contrast, never the picture's */
.bcAppSheet .bcAsX{
  position:absolute; top:10px; right:10px; z-index:2; width:30px; height:30px;
  display:grid; place-items:center; border:1px solid var(--line);
  border-radius:999px; background:color-mix(in srgb,var(--panel) 78%,transparent);
  color:var(--ink); font-size:18px; line-height:1; cursor:pointer;
}
.bcAppSheet .bcAsX:hover{border-color:var(--line2)}

/* ⛔ 16:9 AND CROPPED, never letterboxed: a cover is art, and bars around it
   read as a broken image. When there is no cover the ground is a token-coloured
   gradient — an honest empty surface, not a placeholder picture pretending to
   be a screenshot (§the manifest's own rule about stock imagery). */
.bcAppSheet .bcAsCover{
  position:relative; aspect-ratio:16/9; width:100%; overflow:visible;
  border-radius:18px 18px 0 0; background:var(--surf);
}
.bcAppSheet .bcAsCoverImg{
  display:block; width:100%; height:100%; object-fit:cover;
  border-radius:18px 18px 0 0;
}
.bcAppSheet .bcAsCoverGround{
  display:block; width:100%; height:100%; border-radius:18px 18px 0 0;
  background:linear-gradient(135deg,
    color-mix(in srgb,var(--violet) 26%,transparent),
    color-mix(in srgb,var(--mint) 16%,transparent) 62%,
    var(--surf2));
}
/* the icon sits ON the cover's bottom-left corner, half over the edge */
.bcAppSheet .bcAsIconWrap{position:absolute; left:22px; bottom:-16px; z-index:1}
.bcAppSheet .bcAsIcon{
  display:block; width:56px; height:56px; border-radius:16px; object-fit:contain;
  background:var(--panel); border:1px solid var(--line); box-shadow:var(--lift);
}
.bcAppSheet .bcAsIconLetter{
  display:grid; place-items:center; font:600 22px var(--disp); color:var(--muted);
}

.bcAppSheet .bcAsBody{padding:30px 24px 22px}
.bcAppSheet .bcAsName{font:600 21px/1.25 var(--disp); margin:0}
.bcAppSheet .bcAsTag{margin:6px 0 0; font:400 14px/1.6 var(--body); color:var(--muted)}
.bcAppSheet .bcAsChips{display:flex; flex-wrap:wrap; gap:7px; margin:13px 0 0}
.bcAppSheet .bcAsChip{
  border:1px solid var(--line); border-radius:999px; padding:3px 11px;
  font:400 11.5px/1.5 var(--body); color:var(--muted); background:var(--surf);
}
.bcAppSheet .bcAsChip.s-on{
  color:var(--mint); border-color:color-mix(in srgb,var(--mint) 42%,var(--line));
  background:color-mix(in srgb,var(--mint) 10%,transparent);
}
.bcAppSheet .bcAsChip.s-avail{
  color:var(--violet); border-color:color-mix(in srgb,var(--violet) 42%,var(--line));
  background:color-mix(in srgb,var(--violet) 10%,transparent);
}
.bcAppSheet .bcAsChip.s-bad{
  color:var(--amber); border-color:color-mix(in srgb,var(--amber) 42%,var(--line));
  background:color-mix(in srgb,var(--amber) 10%,transparent);
}
.bcAppSheet .bcAsChip.s-off{color:var(--faint)}
/* ⚡ THE FACTS ROW IS MONO, because it is a row of measurements — version,
   dates, how often somebody opened it — and a proportional face makes them read
   as prose that can be skimmed past. */
.bcAppSheet .bcAsFacts{
  margin:11px 0 0; font:400 11.5px/1.7 var(--mono); color:var(--faint);
}
.bcAppSheet .bcAsWhat{margin:15px 0 0; font:400 14px/1.65 var(--body); color:var(--ink)}

.bcAppSheet .bcAsActs{display:flex; flex-wrap:wrap; gap:9px; margin:18px 0 0}
/* the primary: the instrument surface, exactly as os-app.css's `.osAppBar .go` */
.bcAppSheet .bcAsGo{
  padding:9px 18px; border:0; border-radius:999px;
  background:var(--fill); color:var(--onfill); font:500 12.5px var(--body); cursor:pointer;
}
.bcAppSheet .bcAsGo:hover{filter:brightness(1.08)}
.bcAppSheet .bcAsGo[disabled]{opacity:.42; cursor:default; filter:none}
.bcAppSheet .bcAsBtn{
  padding:9px 16px; border:1px solid var(--line); border-radius:999px;
  background:var(--surf); color:var(--ink); font:500 12.5px var(--body); cursor:pointer;
}
.bcAppSheet .bcAsBtn:hover{border-color:var(--line2); background:var(--surf2)}
/* ⛔ RUNNING IS A STATE THE STREAM SAID, so it is drawn as a live thing —
   a pulse, and a press that lands on the job itself. */
.bcAppSheet .bcAsRun{
  display:inline-flex; align-items:center; gap:8px;
  padding:9px 16px; border:1px solid color-mix(in srgb,var(--mint) 42%,var(--line));
  border-radius:999px; background:color-mix(in srgb,var(--mint) 10%,transparent);
  color:var(--mint); font:500 12.5px var(--body); cursor:pointer;
}
.bcAppSheet .bcAsRun i{
  width:6px; height:6px; border-radius:50%; background:var(--mint);
  animation:bcAsBeat 2.4s ease-in-out infinite;
}
@keyframes bcAsBeat{0%,100%{opacity:.4;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}

.bcAppSheet .bcAsSay:empty{display:none}
.bcAppSheet .bcAsSay{margin-top:13px}
/* a refusal, in the same frame every app uses for one */
.bcAppSheet .osAppRefuse{
  padding:13px 15px; border:1px solid color-mix(in srgb,var(--rose) 40%,var(--line));
  border-radius:12px; background:color-mix(in srgb,var(--rose) 8%,transparent);
  color:var(--ink); font:400 13px/1.5 var(--body);
}
.bcAppSheet .bcAsOk{
  padding:11px 14px; border:1px solid color-mix(in srgb,var(--mint) 40%,var(--line));
  border-radius:12px; background:color-mix(in srgb,var(--mint) 8%,transparent);
  color:var(--ink); font:400 13px/1.5 var(--body);
}

.bcAppSheet .bcAsSec{border-top:1px solid var(--line); margin-top:20px; padding-top:15px}
.bcAppSheet .bcAsSec>h3{
  margin:0 0 11px; font:400 10.5px/1 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; color:var(--faint);
}
.bcAppSheet .bcAsNone{font:400 13px/1.5 var(--body); color:var(--muted)}
/* ⚡ THE STRIP SCROLLS AND SNAPS. Screenshots are wide; wrapping them into a
   grid makes a two-shot app look like a gallery and a six-shot app look like a
   wall, and both hide the sixth. */
.bcAppSheet .bcAsShots{
  display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory;
  padding-bottom:6px; scrollbar-width:thin;
}
.bcAppSheet .bcAsShots figure{margin:0; flex:0 0 auto; width:min(340px,78%); scroll-snap-align:start}
.bcAppSheet .bcAsShots img{
  display:block; width:100%; border:1px solid var(--line); border-radius:12px;
  background:var(--surf);
}
.bcAppSheet .bcAsShots figcaption{
  margin-top:7px; font:400 11px/1.45 var(--mono); color:var(--faint);
}
.bcAppSheet .bcAsUses{margin:0; padding-left:18px; font:400 13.5px/1.75 var(--body); color:var(--ink)}
.bcAppSheet .bcAsVerbs{display:flex; flex-wrap:wrap; gap:8px}
.bcAppSheet .bcAsVerb{
  display:inline-flex; align-items:center; gap:7px;
  border:1px solid var(--line); border-radius:999px; padding:5px 12px;
  font:400 12.5px/1.5 var(--body); color:var(--ink); background:var(--surf);
}
/* ⛔ A DECLARED VERB THAT IS NOT SERVED IS GREYED AND SAYS SO. Dropping it
   would hide a promise; printing it plain would claim it works. */
.bcAppSheet .bcAsVerb.dim{color:var(--faint); background:none}
.bcAppSheet .bcAsVerb em{font:400 10.5px var(--mono); font-style:normal; color:var(--amber)}
.bcAppSheet .bcAsAbsent{
  margin:16px 0 0; font:400 11.5px/1.6 var(--mono); color:var(--faint);
}
.bcAppSheet .bcAsNote{
  margin:14px 0 0; padding-top:12px; border-top:1px solid var(--line);
  font:400 11.5px/1.55 var(--body); color:var(--muted);
}

/* ⚡ ON A PHONE THE SHEET IS THE SCREEN. A centred card with a margin around it
   on a 380px viewport is a card with nowhere to put its cover. */
@media(max-width:860px){
  .bcAppSheetWrap{padding:0}
  .bcAppSheet{
    width:100%; max-width:none; max-height:100vh; height:100vh;
    border:0; border-radius:0;
  }
  .bcAppSheet .bcAsCover,.bcAppSheet .bcAsCoverImg,.bcAppSheet .bcAsCoverGround{border-radius:0}
  .bcAppSheet .bcAsShots figure{width:86%}
}
@media (prefers-reduced-motion:reduce){
  .bcAppSheet .bcAsRun i{animation:none}
  .bcAppSheet .bcAsShots{scroll-behavior:auto}
}

/* ── verbs — the small actions an app offers on one of its objects ─────────
   ⚡ Redo · Delete on an Image Studio frame was the first pair, rendered both
      inside the pane (`.osApp`) and inside the conversation widget, which is
      NOT under `.osApp` — so the app frame's own bar styles never reached it
      and two bare browser buttons floated at the card's corner. A verb row
      belongs here, where both surfaces read it.
   ⛔ Tokens only. `.arm` is the second-press state of a destructive verb. */
.bcVerbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:0 0 10px}
.bcVerb{appearance:none;border:1px solid var(--line);background:var(--surf);color:var(--ink);
  border-radius:999px;padding:5px 12px;font:500 12px/1.2 var(--disp);cursor:pointer;
  transition:background .15s,border-color .15s}
.bcVerb:hover{background:var(--surf2);border-color:var(--line2)}
.bcVerb.arm{border-color:var(--rose);color:var(--rose)}
.bcVerbs .isWarn{font:400 11.5px/1.3 var(--mono);color:var(--amber)}
@media (prefers-reduced-motion:reduce){.bcVerb{transition:none}}


/* ⚡ ONE FACE PER PERSON (specialists v0.2) — `.pmark` is what person-mark.js
   emits; `--pm` is the one size knob and each surface sets it. Initials share
   the tile so a missing picture and a present one sit at the same size. */
.pmark{width:var(--pm,28px);height:var(--pm,28px);border-radius:calc(var(--pm,28px)*.36);flex:none;object-fit:cover;background:color-mix(in srgb,var(--violet,#7c5cff) 14%,var(--panel,#fffbf4));box-shadow:inset 0 1px 0 rgba(255,255,255,.6)}
.pmark.ini{display:inline-grid;place-items:center;font:700 calc(var(--pm,28px)*.36)/1 var(--osDisp,Nunito,system-ui);color:var(--violet,#7c5cff);letter-spacing:.02em}

/* ── the boot ledger and the state card (SPEC-BOOT-AND-RESILIENCE §3–§4) ──
   ⚡ The loader LOADS: four rows, each flipped by the read it names. ⛔ Steps,
      never a bar — a percentage of an unmeasured wait is a fabricated number.
   ⚡ And the loader is the failing screen too: the card below replaces the
      sentence and the rail inside the SAME element, so nothing can paint under
      it and the retired thread can never be what a failed read shows. */
.bcLoader .bcLoaderLedger{
  list-style:none; margin:2px 0 0; padding:0; display:grid; gap:7px;
  min-width:232px; font:500 13px/1.45 var(--body,Inter,sans-serif);
  color:var(--muted,#655773); letter-spacing:.005em;
}
.bcLoader .bcLoaderLedger li{display:flex; align-items:center; gap:10px; opacity:.55; transition:opacity .25s ease}
.bcLoader .bcLoaderLedger li.run,.bcLoader .bcLoaderLedger li.ok,.bcLoader .bcLoaderLedger li.warn,.bcLoader .bcLoaderLedger li.fail{opacity:1}
.bcLoader .bcLoaderLedger li i{
  flex:0 0 18px; width:18px; height:18px; border-radius:50%; display:grid; place-items:center;
  font:800 11px/1 var(--body,Inter,sans-serif); font-style:normal;
  background:var(--surf2,rgba(43,36,64,.085)); color:var(--muted,#655773);
}
.bcLoader .bcLoaderLedger li.ok i{background:var(--okbg,#cdeedd); color:var(--mint,#2f7a5c)}
.bcLoader .bcLoaderLedger li.warn i{background:var(--clay-peach,#fbd9c9); color:var(--amber,#c2410c)}
.bcLoader .bcLoaderLedger li.fail i{background:var(--clay-peach,#fbd9c9); color:var(--amber,#c2410c)}
.bcLoader .bcLoaderLedger li.run i{
  background:none; border:2px solid var(--lav,#e5dcff); border-top-color:var(--violet,#7c5cff);
  animation:bcLedgerSpin .8s linear infinite;
}
.bcLoader .bcLoaderLedger li.ok span{color:var(--ink,#2b2440)}
@keyframes bcLedgerSpin{to{transform:rotate(360deg)}}

.bcLoader .bcLoaderState{
  pointer-events:auto; margin-top:6px; width:min(440px,86vw);
  padding:22px 24px 18px; border-radius:22px; text-align:center;
  background:var(--panelT,rgba(255,251,244,.94));
  box-shadow:0 18px 44px var(--shadow,rgba(58,51,72,.18)), 0 1px 0 rgba(255,255,255,.7) inset;
  animation:bcLoaderRise .4s cubic-bezier(.2,.8,.2,1) both;
}
.bcLoader .bcLoaderState .h{margin:0 0 6px; font:800 22px/1.15 var(--head,Nunito,var(--body,Inter,sans-serif)); color:var(--ink,#2b2440); letter-spacing:-.01em}
.bcLoader .bcLoaderState .l{margin:0 0 16px; font:500 13.5px/1.5 var(--body,Inter,sans-serif); color:var(--muted,#655773)}
.bcLoader .bcLoaderState .acts{display:flex; gap:10px; justify-content:center; flex-wrap:wrap}
.bcLoader .bcLoaderBtn{
  appearance:none; border:0; cursor:pointer; height:44px; padding:0 22px; border-radius:999px;
  font:700 14px/1 var(--body,Inter,sans-serif); letter-spacing:.01em;
  background:var(--clay-peach,#fbd9c9); color:var(--amber,#c2410c);
  box-shadow:0 6px 16px rgba(194,65,12,.14), 0 1px 0 rgba(255,255,255,.8) inset;
  transition:transform .12s ease, box-shadow .12s ease, filter .12s ease;
}
.bcLoader .bcLoaderBtn:hover{transform:translateY(-1px); box-shadow:0 10px 22px rgba(194,65,12,.18), 0 1px 0 rgba(255,255,255,.8) inset; filter:saturate(1.08)}
.bcLoader .bcLoaderBtn:active{transform:translateY(0) scale(.985)}
.bcLoader .bcLoaderBtn:focus-visible{outline:2px solid var(--violet,#7c5cff); outline-offset:3px}
.bcLoader .bcLoaderBtn.alt{background:transparent; color:var(--muted,#655773); box-shadow:inset 0 0 0 1.5px var(--line2,rgba(43,36,64,.2))}
.bcLoader .bcLoaderBtn.alt:hover{box-shadow:inset 0 0 0 1.5px var(--ink,#2b2440); color:var(--ink,#2b2440)}
.bcLoader .bcLoaderBtn[hidden]{display:none}
.bcLoader .bcLoaderState .cd{margin:12px 0 0; font:500 12px/1.4 var(--body,Inter,sans-serif); color:var(--muted,#655773); min-height:1.4em}
.bcLoader .bcLoaderState .cd:empty{display:none}
/* While the card is up the mark stops breathing and the flow filament rests —
   a loader that keeps sweeping under "not answering" contradicts itself. */
html.bcOffline .bcLoader .bcLoaderMark{animation:none; --bc-mark-flow-play:paused; --bc-mark-contour-animation:none}
html.bcOffline .bcLoader .bcLoaderSpace{opacity:.6; transition:opacity .4s ease}
@media (prefers-reduced-motion:reduce){ .bcLoader .bcLoaderLedger li.run i{animation:none; border-top-color:var(--lav,#e5dcff)} }

/* ⚡ THE SITUATION HAS A PICTURE (owner, 2026-09-10: "why not have a background
   image … according to situation"). The clay world at a pause: a paper boat
   resting on a still lake, a lantern lit on the shore — generated on our own
   line from the clay reference, 1920×1280 webp, 35 KB. It fades in under the
   card and out the instant a probe answers. */
html.bcOffline .bcLoader{
  background:#f4efe6 url(/art/os/bg-offline.webp) center 60%/cover no-repeat;
  animation:bcOfflineIn .6s ease both;
}
html.bcOffline .bcLoader::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(60% 48% at 50% 52%, rgba(255,251,244,.55), transparent 72%);
}
html.bcOffline .bcLoader .in{position:relative; z-index:2}
/* the rows arrive one after another — a ledger that pops in whole reads as a form */
.bcLoader .bcLoaderLedger li{animation:bcLoaderRise .35s cubic-bezier(.2,.8,.2,1) both}
.bcLoader .bcLoaderLedger li:nth-child(2){animation-delay:.06s}
.bcLoader .bcLoaderLedger li:nth-child(3){animation-delay:.12s}
.bcLoader .bcLoaderLedger li:nth-child(4){animation-delay:.18s}
@keyframes bcOfflineIn{from{opacity:.001}to{opacity:1}}
@media (prefers-reduced-motion:reduce){ html.bcOffline .bcLoader, .bcLoader .bcLoaderLedger li{animation:none} }

/* ⚡ THE MARK HAS A PLACE TO STAND: a soft cream halo behind the wordmark so the
   logo reads first against the hills and the picture — and it settles in from
   above rather than popping. */
.bcLoader .bcLoaderMark{position:relative}
.bcLoader .in::before{
  content:""; position:absolute; left:50%; top:-40px; width:min(560px,90vw); height:min(300px,60vh);
  transform:translateX(-50%); pointer-events:none; z-index:-1; border-radius:50%;
  background:radial-gradient(closest-side, rgba(255,251,244,.78), rgba(255,251,244,.35) 55%, transparent 100%);
}
.bcLoader .in{padding-top:8px}
